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

5 投票
3 回答
4898 浏览
提问于 2025-04-18 17:44

我在一台运行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>

我似乎无法抓取表格或它的任何内容,因为BeautifulSoup和/或Python似乎不识别带有连字符的值。所以我通常使用的代码,比如说

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

或者

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

结果只是返回一个空对象(不是NONE,只是空的)。我对BeautifulSoup4和Python并不陌生,之前也从这个网站提取过信息,但这次的类名和之前的不一样了。现在所有的类名都有连字符。有没有办法让Python识别连字符,或者有什么解决方法?

我需要让我的代码更通用,这样我才能在多个页面上运行,因为这些页面的类名都是一样的。不幸的是,id属性在<tbody>中是特定于某个表格的,所以我不能用它来在不同网页中识别这个表格。

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

3 个回答

1

只需要用 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')
6

对于那些想要找到带有连字符的标签属性的解决方案的人,文档中有一个答案: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>]
6

以下代码:

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本身并不完全有效,但看起来Beautiful Soup(简称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>

不过我猜那些标签不应该是嵌套在一起的。

你能试着运行一下这段代码,看看输出结果是什么吗?

撰写回答