BeautifulSoup的find_all方法使用名称列表时,无法找到另一个目标之后的目标。

huangapple go评论91阅读模式
英文:

BeautifulSoup's findall with a list of names does not find targets after another target

问题

如果我执行以下代码:

  1. from bs4 import BeautifulSoup
  2. soup = BeautifulSoup("<html><body><p>111</p><p>before<ul><li>222</li></ul>after</p></body></html>", "lxml")
  3. soup.find_all(["p", "li"])

我会得到以下结果:

  1. [<p>111</p>, <p>before</p>, <li>222</li>]

我期望在结果中也找到 "after",要么作为第二个 "p" 元素的一部分,要么作为列表中的第四个项目。

这是否是预期的行为?有没有方法来检索文本 "after"?

更奇怪的是,如果我执行 print(soup.prettify()),结果如下:

  1. <html>
  2. <body>
  3. <p>
  4. 111
  5. </p>
  6. <p>
  7. before
  8. </p>
  9. <ul>
  10. <li>
  11. 222
  12. </li>
  13. </ul>
  14. after
  15. </body>
  16. </html>

"ul" 和 "after" 不再是第二个 "p" 的一部分。我假设源代码可能不是有效的 HTML(?),但再次提问:

有没有办法处理这个问题,而不仅仅是丢弃 "after"?

英文:

Other questions with similar titles did not answer my question.

If I execute this:

  1. from bs4 import BeautifulSoup
  2. soup = BeautifulSoup(&quot;&lt;html&gt;&lt;body&gt;&lt;p&gt;111&lt;/p&gt;&lt;p&gt;before&lt;ul&gt;&lt;li&gt;222&lt;/li&gt;&lt;/ul&gt;after&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;&quot;, &quot;lxml&quot;)
  3. soup.find_all([&quot;p&quot;, &quot;li&quot;])

I get this result:

  1. [&lt;p&gt;111&lt;/p&gt;, &lt;p&gt;before&lt;/p&gt;, &lt;li&gt;222&lt;/li&gt;]

I expected to find "after" in the result as well, either as part of the second "p" element or as a 4th item in the list.

Is this expected behaviour? Is there a way to retrieve the text "after"?

More weirdness, if I do print(soup.prettify()), this is the result.

  1. &lt;html&gt;
  2. &lt;body&gt;
  3. &lt;p&gt;
  4. 111
  5. &lt;/p&gt;
  6. &lt;p&gt;
  7. before
  8. &lt;/p&gt;
  9. &lt;ul&gt;
  10. &lt;li&gt;
  11. 222
  12. &lt;/li&gt;
  13. &lt;/ul&gt;
  14. after
  15. &lt;/body&gt;
  16. &lt;/html&gt;

The "ul" and "after" are no longer part of the second "p". I assume that the source is not valid html (?), but again:

Is there a way to deal with this, except from just dropping "after"?

答案1

得分: 2

建议在这种情况下使用不同于 lxml 的解析器:html.parserlxmlhtml.parser 更严格:

  1. soup = BeautifulSoup("<html><body><p>111</p><p>before<ul><li>222</li></ul>after</p></body></html>", "html.parser")
  2. print(soup.find_all(["p", "li"]))

输出结果:

  1. [<p>111</p>, <p>before<ul><li>222</li></ul>after</p>, <li>222</li>]
英文:

I suggest to use different parser than lxml in this case: html.parser. lxml is more strict than html.parser:

  1. soup = BeautifulSoup(&quot;&lt;html&gt;&lt;body&gt;&lt;p&gt;111&lt;/p&gt;&lt;p&gt;before&lt;ul&gt;&lt;li&gt;222&lt;/li&gt;&lt;/ul&gt;after&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;&quot;, &quot;html.parser&quot;)
  2. print(soup.find_all([&quot;p&quot;, &quot;li&quot;]))

Prints:

  1. [&lt;p&gt;111&lt;/p&gt;, &lt;p&gt;before&lt;ul&gt;&lt;li&gt;222&lt;/li&gt;&lt;/ul&gt;after&lt;/p&gt;, &lt;li&gt;222&lt;/li&gt;]

huangapple
  • 本文由 发表于 2023年6月8日 04:28:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76426904.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定