【问题标题】:Beautiful Soup not finding string美丽的汤找不到字符串
【发布时间】:2013-08-30 14:30:59
【问题描述】:

在解析 http://en.wikipedia.org/wiki/Israel 时,我遇到了一个带有文本的 H2 标签,但 Beautiful Soup 为它返回了一个 None 类型:

$ python
Python 2.7.3 (default, Apr 10 2013, 05:13:16)
[GCC 4.7.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import bs4
>>> import requests
>>> from pprint import pprint
>>> response = requests.get('http://en.wikipedia.org/wiki/Israel')
>>> soup = bs4.BeautifulSoup(response.content)
>>> for h in soup.find_all('h2'):
...     pprint(str(type(h)))
...     pprint(h)
...     pprint(str(type(h.string)))
...     pprint(h.string)
...     print('--')
...                     
"<class 'bs4.element.Tag'>"
<h2>Contents</h2>    
"<class 'bs4.element.NavigableString'>"
u'Contents'          
--                   
"<class 'bs4.element.Tag'>"
<h2><span class="mw-headline" id="Etymology"><span id="Etymology"></span> Etymology</span></h2>
"<type 'NoneType'>"  
None                 
--                   
"<class 'bs4.element.Tag'>"
<h2><span class="mw-headline" id="History">History</span></h2>
"<class 'bs4.element.NavigableString'>"
u'History'           
--

请注意,这不是解析问题,Beautiful Soup 可以很好地解析文档。为什么第二个 H2 元素返回 None 类型?是否由于字符串中的前导“”(空格)?我该如何解决这个问题?这是 Python 2.7 上的 Beautiful Soup 4,Kubuntu Linux 12.10。

【问题讨论】:

  • 在第 2 个 H2 上有 2 个跨度,其中一个空的跨度为 id ethymology。这可能是 bsoup 失败。
  • 我确实注意到了。我该如何围绕它编写代码?
  • 为了能够帮助您,我需要深入了解文档,因为我从不使用 bs4 - 如果您不着急,我可以尝试。

标签: python html-parsing beautifulsoup


【解决方案1】:

我在回答前半部分,怎么了……

引用documentation of bs4:“如果一个标签包含不止一个东西,那么.string应该指的是什么就不清楚了,所以.string被定义为None。”

现在是另一半,如何修复它。

再次引用同一来源:“如果标签中包含多个内容,您仍然可以只查看字符串。使用 .strings 生成器。”。更好的是,使用.stripped_strings 生成器,连接结果,我想你会得到你想要的。

【讨论】:

  • '.string'/ '.stripped_string' 不适合我。但是 '.contents' 正在工作并返回我需要的字符串列表。你能解释一下这是为什么吗?
  • @user2831683 你能提供你的问题的最小实例吗?在一个单独的问题中,如果它很长......
  • 解决了。实际上在我的例子中 bs4.element.Tag 对象有太多的字符串要引用,所以它无法决定返回哪一个字符串。所以它返回“无”。在另一个问题中找到了我的问题的确切解决方案。谢谢你
【解决方案2】:

我认为这是因为第二个 h2 没有文本,而是有一个 span 作为孩子(并且该跨度有另一个孩子作为其孩子,这使得 h2 的孙子。

对于这种解析,请使用基于生成器的属性,例如 .stripped_strings.strings

>>> s.find_all('h2')
[<h2>Contents</h2>, <h2><span class="mw-headline" id="Etymology"><span id="Etymology"></span> Etymology</span></h2>]
>>> list(s.find_all('h2')[-1].stripped_strings)
[u'Etymology']

【讨论】:

  • 您的代码有效,但理由并不完全正确。如果只有一个span(或任何嵌套的spans 列表),就可以了。
  • @nickie 你的意思是跨度(不是垃圾邮件;)
  • 实际上,第二个h2 确实有文字,就在&lt;/span&gt; 之后。但是,它看起来确实不是合法的 HTML。
猜你喜欢
  • 2016-12-18
  • 2017-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-31
相关资源
最近更新 更多