Beautifulsoup 无法找到名称中带有连字符的类

Posted

技术标签:

【中文标题】Beautifulsoup 无法找到名称中带有连字符的类【英文标题】:Beautifulsoup Unable to Find Classes with Hyphens in Their Name 【发布时间】:2014-10-12 01:51:38 【问题描述】:

我在运行 Python 2.7.8 的 MacOSX 上使用 BeautifulSoup4。我在从以下 html 代码中提取信息时遇到困难

 <tbody tabindex="0" class="yui-dt-data" id="yui_3_5_0_1_1408418470185_1650">
      <tr id="yui-rec0" class="yui-dt-first yui-dt-even">
           <td headers="yui-dt0-th-rank" class="rank yui-dt0-col-rank"></td>
           </tr>
      <tr id="yui-rec1" class="yui-dt-odd">...</tr>
      <tr id="yui-rec2" class="yui-dt-even">...</tr>
 </tbody>

我似乎无法抓取表格或其中的任何内容,因为 BS 和/或 python 似乎无法识别带有连字符的值。所以通常的代码,比如

 Table = soup.find('tbody','class':'yui-dt-data')

 Row2 = Table.find('tr','id':'yui-rec2')

只返回一个空对象(不是 NONE,只是空的)。我对 BS4 或 Python 并不陌生,我之前已经从这个站点提取过信息,但是现在的类名与我之前做的不同。现在一切都有连字符。有什么方法可以让 Python 识别连字符或解决方法?

我需要使我的代码具有通用性,以便我可以在多个具有相同类名的页面上运行它。不幸的是,&lt;tbody&gt; 中的 id 属性对于该特定表是唯一的,因此我无法使用它来跨网页识别此表。

任何帮助将不胜感激。提前致谢。

【问题讨论】:

我无法重现这个。是否有可能是 HTML 格式错误? 【参考方案1】:

以下代码:

from bs4 import BeautifulSoup

htmlstring = """ <tbody tabindex="0" class="yui-dt-data" id="yui_3_5_0_1_1408418470185_1650">
      <tr id="yui-rec0" class="yui-dt-first yui-dt-even">
      <tr id="yui-rec1" class="yui-dt-odd">
      <tr id="yui-rec2" class="yui-dt-even">"""


soup = BeautifulSoup(htmlstring)
Table = soup.find('tbody', attrs='class': 'yui-dt-data') 
print("Table:\n")
print(Table)
tr = Table.find('tr', attrs='class': 'yui-dt-odd') 
print("tr:\n")
print(tr)

输出:

Table:

<tbody class="yui-dt-data" id="yui_3_5_0_1_1408418470185_1650" tabindex="0">
<tr class="yui-dt-first yui-dt-even" id="yui-rec0">
<tr class="yui-dt-odd" id="yui-rec1">
<tr class="yui-dt-even" id="yui-rec2"></tr></tr></tr></tbody>
tr:

<tr class="yui-dt-odd" id="yui-rec1">
<tr class="yui-dt-even" id="yui-rec2"></tr></tr>

即使您提供的 html 本身不是有效的,但似乎 BS 正在猜测它应该是怎样的,因为 soup.prettify() 产生

<tbody class="yui-dt-data" id="yui_3_5_0_1_1408418470185_1650" tabindex="0">
 <tr class="yui-dt-first yui-dt-even" id="yui-rec0">
  <tr class="yui-dt-odd" id="yui-rec1">
   <tr class="yui-dt-even" id="yui-rec2">
   </tr>
  </tr>
 </tr>
</tbody>

虽然我猜这些 tr 不应该嵌套。

您能否尝试运行该确切代码并查看输出是什么?

【讨论】:

你的代码对我来说很好用。我详细查看了代码中的汤输出,看起来 BS 正在放弃或猜测名称中包含破折号的属性。例如,解析 &lt;tbody&gt; 标记后没有任何属性,而例如,第二个 &lt;tr&gt; 标记被解析 &lt;tr class="odd"&gt;,其中前面的单词已从类名和 id 属性中删除甚至不存在。【参考方案2】:

对于试图找到解决方案以在其属性中找到带有连字符的标签的人,文档中有一个答案 https://www.crummy.com/software/BeautifulSoup/bs4/doc/#the-keyword-arguments

这段代码会报错

data_soup = BeautifulSoup('<div data-foo="value">foo!</div>')
data_soup.find_all(data-foo="value")
# SyntaxError: keyword can't be an expression

你应该这样做

data_soup.find_all(attrs="data-foo": "value")
# [<div data-foo="value">foo!</div>]

【讨论】:

【参考方案3】:

只需使用select。 bs4 4.7.1

import requests
from bs4 import BeautifulSoup as bs

html = '''
<tbody tabindex="0" class="yui-dt-data" id="yui_3_5_0_1_1408418470185_1650">
      <tr id="yui-rec0" class="yui-dt-first yui-dt-even">
           <td headers="yui-dt0-th-rank" class="rank yui-dt0-col-rank"></td>
           </tr>
      <tr id="yui-rec1" class="yui-dt-odd">...</tr>
      <tr id="yui-rec2" class="yui-dt-even">...</tr>
 </tbody>
 '''
soup = bs(html, 'lxml')
soup.select('.yui-dt-data')

【讨论】:

以上是关于Beautifulsoup 无法找到名称中带有连字符的类的主要内容,如果未能解决你的问题,请参考以下文章

如何为名称中带有“ - ”(连字符)的工件添加“要求”

REGEX - 如何在文件名中找到两个连字符?

如何使用 JSON Utility 读取键中带有连字符的对象?

Web API 2 中带连字符的参数

.Net core 3.0 API 不使用连字符绑定属性

如何将excel电子表格中带有多个连字符“-”的中的某一数字用公式提取出来,数据量比较大,一个一个的输入很