|
870 | 870 | </ul> |
871 | 871 | </nav> |
872 | 872 |
|
| 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 | + |
873 | 945 | </li> |
874 | 946 |
|
875 | 947 | <li class="md-nav__item"> |
|
4323 | 4395 | </ul> |
4324 | 4396 | </nav> |
4325 | 4397 |
|
| 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 | + |
4326 | 4470 | </li> |
4327 | 4471 |
|
4328 | 4472 | <li class="md-nav__item"> |
@@ -4500,6 +4644,71 @@ <h3 id="take-a-screenshot-from-inside-an-iframe">Take a screenshot from inside a |
4500 | 4644 | </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">'sales-chart'</span><span class="p">)</span> |
4501 | 4645 | </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">'chart.png'</span><span class="p">)</span> |
4502 | 4646 | </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>></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">'iframe > .submit-btn'</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">'iframe[src*="checkout"] > #pay-button'</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">'iframe.outer > iframe.inner > div.content'</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">'iframe > nav > a.home-link'</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">'div > iframe > button.submit'</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">'.wrapper iframe > div.content'</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">'//iframe/body/button[@id="submit"]'</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">'//div/iframe/div'</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">'//div[@class="wrapper"]/iframe/body/div'</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">'//iframe[@src*="cloudflare"]//h1'</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">'//iframe[@id="outer"]//iframe[@id="inner"]//div'</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"] > form > button</code>:</p> |
| 4684 | +<ol> |
| 4685 | +<li><strong>Parses</strong> the selector into segments: <code>iframe[src*="checkout"]</code> and <code>form > 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">'iframe'</span><span class="p">,</span> <span class="n">src</span><span class="o">=</span><span class="s1">'*checkout*'</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">'form > button'</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">'iframe[src*="checkout"] > form > button'</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 > body</code> — class selector, not a tag</li> |
| 4702 | +<li><code>#iframe > body</code> — ID selector</li> |
| 4703 | +<li><code>div.iframe > body</code> — tag is <code>div</code>, not <code>iframe</code></li> |
| 4704 | +<li><code>[data-type="iframe"] > 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">'iframe > a'</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> |
4503 | 4712 | <h2 id="best-practices">Best practices</h2> |
4504 | 4713 | <ul> |
4505 | 4714 | <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