Skip to content

Commit 6b121fb

Browse files
committed
deploy: 1c24dea
1 parent 80adccb commit 6b121fb

16 files changed

Lines changed: 4469 additions & 1632 deletions

File tree

docs/api/core/utils/index.html

Lines changed: 665 additions & 220 deletions
Large diffs are not rendered by default.

docs/deep-dive/network/socks-proxies/index.html

Lines changed: 282 additions & 22 deletions
Large diffs are not rendered by default.

docs/features/automation/iframes/index.html

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,78 @@
870870
</ul>
871871
</nav>
872872

873+
</li>
874+
875+
<li class="md-nav__item">
876+
<a href="#cross-iframe-selectors" class="md-nav__link">
877+
<span class="md-ellipsis">
878+
879+
Cross-iframe Selectors
880+
881+
</span>
882+
</a>
883+
884+
<nav class="md-nav" aria-label="Cross-iframe Selectors">
885+
<ul class="md-nav__list">
886+
887+
<li class="md-nav__item">
888+
<a href="#css-selectors" class="md-nav__link">
889+
<span class="md-ellipsis">
890+
891+
CSS selectors
892+
893+
</span>
894+
</a>
895+
896+
</li>
897+
898+
<li class="md-nav__item">
899+
<a href="#xpath-expressions" class="md-nav__link">
900+
<span class="md-ellipsis">
901+
902+
XPath expressions
903+
904+
</span>
905+
</a>
906+
907+
</li>
908+
909+
<li class="md-nav__item">
910+
<a href="#how-it-works" class="md-nav__link">
911+
<span class="md-ellipsis">
912+
913+
How it works
914+
915+
</span>
916+
</a>
917+
918+
</li>
919+
920+
<li class="md-nav__item">
921+
<a href="#when-splitting-does-not-happen" class="md-nav__link">
922+
<span class="md-ellipsis">
923+
924+
When splitting does NOT happen
925+
926+
</span>
927+
</a>
928+
929+
</li>
930+
931+
<li class="md-nav__item">
932+
<a href="#find_all-support" class="md-nav__link">
933+
<span class="md-ellipsis">
934+
935+
find_all support
936+
937+
</span>
938+
</a>
939+
940+
</li>
941+
942+
</ul>
943+
</nav>
944+
873945
</li>
874946

875947
<li class="md-nav__item">
@@ -4323,6 +4395,78 @@
43234395
</ul>
43244396
</nav>
43254397

4398+
</li>
4399+
4400+
<li class="md-nav__item">
4401+
<a href="#cross-iframe-selectors" class="md-nav__link">
4402+
<span class="md-ellipsis">
4403+
4404+
Cross-iframe Selectors
4405+
4406+
</span>
4407+
</a>
4408+
4409+
<nav class="md-nav" aria-label="Cross-iframe Selectors">
4410+
<ul class="md-nav__list">
4411+
4412+
<li class="md-nav__item">
4413+
<a href="#css-selectors" class="md-nav__link">
4414+
<span class="md-ellipsis">
4415+
4416+
CSS selectors
4417+
4418+
</span>
4419+
</a>
4420+
4421+
</li>
4422+
4423+
<li class="md-nav__item">
4424+
<a href="#xpath-expressions" class="md-nav__link">
4425+
<span class="md-ellipsis">
4426+
4427+
XPath expressions
4428+
4429+
</span>
4430+
</a>
4431+
4432+
</li>
4433+
4434+
<li class="md-nav__item">
4435+
<a href="#how-it-works" class="md-nav__link">
4436+
<span class="md-ellipsis">
4437+
4438+
How it works
4439+
4440+
</span>
4441+
</a>
4442+
4443+
</li>
4444+
4445+
<li class="md-nav__item">
4446+
<a href="#when-splitting-does-not-happen" class="md-nav__link">
4447+
<span class="md-ellipsis">
4448+
4449+
When splitting does NOT happen
4450+
4451+
</span>
4452+
</a>
4453+
4454+
</li>
4455+
4456+
<li class="md-nav__item">
4457+
<a href="#find_all-support" class="md-nav__link">
4458+
<span class="md-ellipsis">
4459+
4460+
find_all support
4461+
4462+
</span>
4463+
</a>
4464+
4465+
</li>
4466+
4467+
</ul>
4468+
</nav>
4469+
43264470
</li>
43274471

43284472
<li class="md-nav__item">
@@ -4500,6 +4644,71 @@ <h3 id="take-a-screenshot-from-inside-an-iframe">Take a screenshot from inside a
45004644
</span><span id="__span-3-2"><a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a><span class="n">chart</span> <span class="o">=</span> <span class="k">await</span> <span class="n">iframe</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="s1">&#39;sales-chart&#39;</span><span class="p">)</span>
45014645
</span><span id="__span-3-3"><a id="__codelineno-3-3" name="__codelineno-3-3" href="#__codelineno-3-3"></a><span class="k">await</span> <span class="n">chart</span><span class="o">.</span><span class="n">take_screenshot</span><span class="p">(</span><span class="s1">&#39;chart.png&#39;</span><span class="p">)</span>
45024646
</span></code></pre></div>
4647+
<h2 id="cross-iframe-selectors">Cross-iframe Selectors</h2>
4648+
<p>Instead of manually finding each iframe and then searching inside it, you can write a <strong>single selector</strong> that crosses iframe boundaries. Pydoll automatically detects <code>iframe</code> steps in your XPath or CSS selector, splits them into segments, and walks the iframe chain for you.</p>
4649+
<h3 id="css-selectors">CSS selectors</h3>
4650+
<p>Use any standard combinator (<code>&gt;</code>, space) after an <code>iframe</code> compound:</p>
4651+
<div class="language-python highlight"><pre><span></span><code><span id="__span-4-1"><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-1"></a><span class="c1"># Single iframe crossing</span>
4652+
</span><span id="__span-4-2"><a id="__codelineno-4-2" name="__codelineno-4-2" href="#__codelineno-4-2"></a><span class="n">button</span> <span class="o">=</span> <span class="k">await</span> <span class="n">tab</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s1">&#39;iframe &gt; .submit-btn&#39;</span><span class="p">)</span>
4653+
</span><span id="__span-4-3"><a id="__codelineno-4-3" name="__codelineno-4-3" href="#__codelineno-4-3"></a>
4654+
</span><span id="__span-4-4"><a id="__codelineno-4-4" name="__codelineno-4-4" href="#__codelineno-4-4"></a><span class="c1"># With attribute selectors on the iframe</span>
4655+
</span><span id="__span-4-5"><a id="__codelineno-4-5" name="__codelineno-4-5" href="#__codelineno-4-5"></a><span class="n">button</span> <span class="o">=</span> <span class="k">await</span> <span class="n">tab</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s1">&#39;iframe[src*=&quot;checkout&quot;] &gt; #pay-button&#39;</span><span class="p">)</span>
4656+
</span><span id="__span-4-6"><a id="__codelineno-4-6" name="__codelineno-4-6" href="#__codelineno-4-6"></a>
4657+
</span><span id="__span-4-7"><a id="__codelineno-4-7" name="__codelineno-4-7" href="#__codelineno-4-7"></a><span class="c1"># Nested iframes</span>
4658+
</span><span id="__span-4-8"><a id="__codelineno-4-8" name="__codelineno-4-8" href="#__codelineno-4-8"></a><span class="n">element</span> <span class="o">=</span> <span class="k">await</span> <span class="n">tab</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s1">&#39;iframe.outer &gt; iframe.inner &gt; div.content&#39;</span><span class="p">)</span>
4659+
</span><span id="__span-4-9"><a id="__codelineno-4-9" name="__codelineno-4-9" href="#__codelineno-4-9"></a>
4660+
</span><span id="__span-4-10"><a id="__codelineno-4-10" name="__codelineno-4-10" href="#__codelineno-4-10"></a><span class="c1"># Multiple steps after the iframe</span>
4661+
</span><span id="__span-4-11"><a id="__codelineno-4-11" name="__codelineno-4-11" href="#__codelineno-4-11"></a><span class="n">link</span> <span class="o">=</span> <span class="k">await</span> <span class="n">tab</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s1">&#39;iframe &gt; nav &gt; a.home-link&#39;</span><span class="p">)</span>
4662+
</span><span id="__span-4-12"><a id="__codelineno-4-12" name="__codelineno-4-12" href="#__codelineno-4-12"></a>
4663+
</span><span id="__span-4-13"><a id="__codelineno-4-13" name="__codelineno-4-13" href="#__codelineno-4-13"></a><span class="c1"># Iframe inside another element (not at root)</span>
4664+
</span><span id="__span-4-14"><a id="__codelineno-4-14" name="__codelineno-4-14" href="#__codelineno-4-14"></a><span class="n">button</span> <span class="o">=</span> <span class="k">await</span> <span class="n">tab</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s1">&#39;div &gt; iframe &gt; button.submit&#39;</span><span class="p">)</span>
4665+
</span><span id="__span-4-15"><a id="__codelineno-4-15" name="__codelineno-4-15" href="#__codelineno-4-15"></a><span class="n">content</span> <span class="o">=</span> <span class="k">await</span> <span class="n">tab</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s1">&#39;.wrapper iframe &gt; div.content&#39;</span><span class="p">)</span>
4666+
</span></code></pre></div>
4667+
<h3 id="xpath-expressions">XPath expressions</h3>
4668+
<p>Use <code>/</code> after an <code>iframe</code> step — Pydoll splits at the iframe node:</p>
4669+
<div class="language-python highlight"><pre><span></span><code><span id="__span-5-1"><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a><span class="c1"># Single iframe crossing</span>
4670+
</span><span id="__span-5-2"><a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a><span class="n">button</span> <span class="o">=</span> <span class="k">await</span> <span class="n">tab</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s1">&#39;//iframe/body/button[@id=&quot;submit&quot;]&#39;</span><span class="p">)</span>
4671+
</span><span id="__span-5-3"><a id="__codelineno-5-3" name="__codelineno-5-3" href="#__codelineno-5-3"></a>
4672+
</span><span id="__span-5-4"><a id="__codelineno-5-4" name="__codelineno-5-4" href="#__codelineno-5-4"></a><span class="c1"># Iframe inside another element (not at root)</span>
4673+
</span><span id="__span-5-5"><a id="__codelineno-5-5" name="__codelineno-5-5" href="#__codelineno-5-5"></a><span class="n">div</span> <span class="o">=</span> <span class="k">await</span> <span class="n">tab</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s1">&#39;//div/iframe/div&#39;</span><span class="p">)</span>
4674+
</span><span id="__span-5-6"><a id="__codelineno-5-6" name="__codelineno-5-6" href="#__codelineno-5-6"></a><span class="n">item</span> <span class="o">=</span> <span class="k">await</span> <span class="n">tab</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s1">&#39;//div[@class=&quot;wrapper&quot;]/iframe/body/div&#39;</span><span class="p">)</span>
4675+
</span><span id="__span-5-7"><a id="__codelineno-5-7" name="__codelineno-5-7" href="#__codelineno-5-7"></a>
4676+
</span><span id="__span-5-8"><a id="__codelineno-5-8" name="__codelineno-5-8" href="#__codelineno-5-8"></a><span class="c1"># With predicates on the iframe</span>
4677+
</span><span id="__span-5-9"><a id="__codelineno-5-9" name="__codelineno-5-9" href="#__codelineno-5-9"></a><span class="n">heading</span> <span class="o">=</span> <span class="k">await</span> <span class="n">tab</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s1">&#39;//iframe[@src*=&quot;cloudflare&quot;]//h1&#39;</span><span class="p">)</span>
4678+
</span><span id="__span-5-10"><a id="__codelineno-5-10" name="__codelineno-5-10" href="#__codelineno-5-10"></a>
4679+
</span><span id="__span-5-11"><a id="__codelineno-5-11" name="__codelineno-5-11" href="#__codelineno-5-11"></a><span class="c1"># Nested iframes</span>
4680+
</span><span id="__span-5-12"><a id="__codelineno-5-12" name="__codelineno-5-12" href="#__codelineno-5-12"></a><span class="n">element</span> <span class="o">=</span> <span class="k">await</span> <span class="n">tab</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s1">&#39;//iframe[@id=&quot;outer&quot;]//iframe[@id=&quot;inner&quot;]//div&#39;</span><span class="p">)</span>
4681+
</span></code></pre></div>
4682+
<h3 id="how-it-works">How it works</h3>
4683+
<p>When Pydoll encounters a selector like <code>iframe[src*="checkout"] &gt; form &gt; button</code>:</p>
4684+
<ol>
4685+
<li><strong>Parses</strong> the selector into segments: <code>iframe[src*="checkout"]</code> and <code>form &gt; button</code></li>
4686+
<li><strong>Finds</strong> the iframe element using the first segment</li>
4687+
<li><strong>Searches inside</strong> the iframe using the second segment</li>
4688+
<li>For nested iframes, repeats the process at each boundary</li>
4689+
</ol>
4690+
<p>This is equivalent to the manual approach but in a single call:</p>
4691+
<div class="language-python highlight"><pre><span></span><code><span id="__span-6-1"><a id="__codelineno-6-1" name="__codelineno-6-1" href="#__codelineno-6-1"></a><span class="c1"># Manual (still works)</span>
4692+
</span><span id="__span-6-2"><a id="__codelineno-6-2" name="__codelineno-6-2" href="#__codelineno-6-2"></a><span class="n">iframe</span> <span class="o">=</span> <span class="k">await</span> <span class="n">tab</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">tag_name</span><span class="o">=</span><span class="s1">&#39;iframe&#39;</span><span class="p">,</span> <span class="n">src</span><span class="o">=</span><span class="s1">&#39;*checkout*&#39;</span><span class="p">)</span>
4693+
</span><span id="__span-6-3"><a id="__codelineno-6-3" name="__codelineno-6-3" href="#__codelineno-6-3"></a><span class="n">button</span> <span class="o">=</span> <span class="k">await</span> <span class="n">iframe</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s1">&#39;form &gt; button&#39;</span><span class="p">)</span>
4694+
</span><span id="__span-6-4"><a id="__codelineno-6-4" name="__codelineno-6-4" href="#__codelineno-6-4"></a>
4695+
</span><span id="__span-6-5"><a id="__codelineno-6-5" name="__codelineno-6-5" href="#__codelineno-6-5"></a><span class="c1"># Automatic (same result, one line)</span>
4696+
</span><span id="__span-6-6"><a id="__codelineno-6-6" name="__codelineno-6-6" href="#__codelineno-6-6"></a><span class="n">button</span> <span class="o">=</span> <span class="k">await</span> <span class="n">tab</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s1">&#39;iframe[src*=&quot;checkout&quot;] &gt; form &gt; button&#39;</span><span class="p">)</span>
4697+
</span></code></pre></div>
4698+
<h3 id="when-splitting-does-not-happen">When splitting does NOT happen</h3>
4699+
<p>Selectors are only split when <code>iframe</code> appears as a <strong>tag name</strong>. These selectors pass through unchanged:</p>
4700+
<ul>
4701+
<li><code>.iframe &gt; body</code> — class selector, not a tag</li>
4702+
<li><code>#iframe &gt; body</code> — ID selector</li>
4703+
<li><code>div.iframe &gt; body</code> — tag is <code>div</code>, not <code>iframe</code></li>
4704+
<li><code>[data-type="iframe"] &gt; body</code> — attribute selector</li>
4705+
<li><code>iframe</code> or <code>//iframe</code> — no content after iframe (nothing to search inside)</li>
4706+
</ul>
4707+
<h3 id="find_all-support">find_all support</h3>
4708+
<p>The last segment respects <code>find_all=True</code>, returning all matching elements inside the final iframe:</p>
4709+
<div class="language-python highlight"><pre><span></span><code><span id="__span-7-1"><a id="__codelineno-7-1" name="__codelineno-7-1" href="#__codelineno-7-1"></a><span class="c1"># Get all links inside an iframe</span>
4710+
</span><span id="__span-7-2"><a id="__codelineno-7-2" name="__codelineno-7-2" href="#__codelineno-7-2"></a><span class="n">links</span> <span class="o">=</span> <span class="k">await</span> <span class="n">tab</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s1">&#39;iframe &gt; a&#39;</span><span class="p">,</span> <span class="n">find_all</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
4711+
</span></code></pre></div>
45034712
<h2 id="best-practices">Best practices</h2>
45044713
<ul>
45054714
<li><strong>Use the iframe element as scope:</strong> call <code>find</code>, <code>query</code>, or other helpers on the iframe itself.</li>

0 commit comments

Comments
 (0)