【问题标题】:Why does bs4 return tags and then an empty list to this find_all() method?为什么 bs4 返回标签,然后是一个空列表到这个 find_all() 方法?
【发布时间】:2014-12-09 18:03:20
【问题描述】:

看着US Census QFD,我正试图按县抢占比赛百分比。我正在构建的循环超出了我的问题范围,这与此代码有关:

url = 'http://quickfacts.census.gov/qfd/states/48/48507.html'
#last county in TX; for some reason the qfd #'s counties w/ only odd numbers
page = urllib2.urlopen(url)
soup = BeautifulSoup(page)

c_black_alone = soup.find_all("td", attrs={'headers':'rp9'})[0] #c = county %
s_black_alone = soup.find_all("td", attrs={'headers':'rp9'})[1] #s = state %

它抓取 html 元素,包括其标签,而不仅仅是其中的文本:

c_black_alone, s_black_alone

(<td align="right" headers="rp9 p1" valign="bottom">96.9%<sup></sup></td>,
 <td align="right" headers="rp9 p2" valign="bottom">80.3%<sup></sup></td>)

在 ^ 上面,我只想要元素内的 %...

还有,为什么

test_black = soup.find_all("td", text = "Black")

不返回与上面相同的元素(或其文本),而是返回一个空的 bs4 ResultSet 对象? (编辑:我一直在关注文档,所以我希望这个问题看起来不会太模糊......)

【问题讨论】:

  • 您为什么希望第二个 find_all() 返回第一个元素?这些元素中没有直接包含此类文本。除非您使用正则表达式,否则第二次搜索不会匹配任何内容。
  • @MartijnPieters 我实际上也尝试过test_black = soup.find_all("td", text = re.compile("Black")),它也返回一个空的ResultSet obj。我的印象是,因为文本出现在父元素中,所以它会找到(_all)那个元素并返回它......
  • 我在这里误解了什么吗? bs4: text argument
  • 文字字符串值只匹配全部内容,而不是部分匹配。

标签: python html web-scraping beautifulsoup


【解决方案1】:

要从这些匹配中获取文本,请使用.text 获取所有包含的文本:

>>> soup.find_all("td", attrs={'headers':'rp9'})[0].text
u'96.9%'
>>> soup.find_all("td", attrs={'headers':'rp9'})[1].text
u'80.3%'

您的 text 搜索不匹配任何内容,原因有两个:

  1. 文字字符串只匹配 整个 包含的文本,而不是部分匹配。它仅适用于以&lt;td&gt;Black&lt;/td&gt; 作为sole 内容的元素。
  2. 它将使用.string property,但仅当文本是给定元素的only 子元素时才设置该属性。如果存在其他元素,则搜索将完全失败。

解决这个问题的方法是使用 lambda;它将传递整个元素,您可以验证每个元素:

soup.find_all(lambda e: e.name == 'td' and 'Black' in e.text)

演示:

>>> soup.find_all(lambda e: e.name == 'td' and 'Black' in e.text)
[<td id="rp10" valign="top">Black or African American alone, percent, 2013 (a)  <!-- RHI225213 --> </td>, <td id="re6" valign="top">Black-owned firms, percent, 2007  <!-- SBO315207 --> </td>]

这两个匹配项在 &lt;td&gt; 元素中都有注释,从而使使用 text 匹配项的搜索无效。

【讨论】:

  • 这太好了,谢谢。我认为演示的输出可以使用您上面提到的相同 .text 方法提取其 96.9% 和 80.3%?
  • 我基于您在问题中提供的 URL 的演示;我发布的输出完全是实时的。所以是的,您可以使用.text 提取这些值。
猜你喜欢
  • 1970-01-01
  • 2021-10-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-01
  • 2020-11-10
  • 2021-12-22
  • 1970-01-01
  • 2018-08-31
相关资源
最近更新 更多