【问题标题】:Unable to scrape the text from a certain LI element无法从某个 LI 元素中抓取文本
【发布时间】:2014-12-03 18:57:01
【问题描述】:

我正在抓取这个URL

我必须抓取页面的主要内容,例如 Room FeaturesInternet Access

这是我的代码:

 for h3s in Column:  # Suppose this is div.RightColumn 
    for index,test in enumerate(h3s.select("h3")):
        print("Feature title: "+str(test.text))
        for v in h3s.select("ul")[index]:
            print(v.string.strip())

此代码会抓取所有 <li> 的内容,但在抓取 Internet Access 时 我明白了

AttributeError: 'NoneType' object has no attribute 'strip'

因为 Internet Access 标题下的 <li>s 数据包含在双引号内,例如 "Wired High Speed Internet Access..."

我尝试将print(v.string.strip()) 替换为print(v),结果为<li>Wired High...</li>

我也尝试过使用print(v.text),但它也不起作用

相关部分如下所示:

<h3>Internet Access</h3>
<ul>
    <li>Wired High Speed Internet Access in All Guest Rooms
     <span class="fee">
        25 USD per day
     </span>
  </li> 
 </ul>

【问题讨论】:

  • 没有双引号;也许您对浏览器开发者工具中的元素树视图感到困惑?
  • 如果你在谷歌浏览器中检查......你会看到双引号,没有跨度......但在 Firefox 中,没有 2ble-quotes,它也显示跨度
  • Chrome 中也有跨度,需要向下滚动。引号作为开发人员工具的一部分显示字符串值周围有多少空格(制表符和换行符)。它们不是该元素实际值的一部分。
  • he quotes are there as part of the developer tool to show how much whitespace 谢谢亲爱的...新信息

标签: python html python-3.x beautifulsoup


【解决方案1】:

BeautifulSoup 元素只有一个 .string 值,如果该字符串是元素中的唯一的孩子。你的&lt;li&gt; 标签有一个&lt;span&gt; 元素和一个文本。

使用.text 属性代替将所有字符串提取为一个:

print(v.text.strip())

或使用element.get_text() method

print(v.get_text().strip())

它还需要一个方便的strip 标志来删除多余的空格:

print(v.get_text(' ', strip=True))

第一个参数是用于将各种字符串连接在一起的分隔符;我在这里用了一个空格。

演示:

>>> from bs4 import BeautifulSoup
>>> sample = '''\
... <h3>Internet Access</h3>
... <ul>
...     <li>Wired High Speed Internet Access in All Guest Rooms
...      <span class="fee">
...         25 USD per day
...      </span>
...   </li> 
...  </ul>
... '''
>>> soup = BeautifulSoup(sample)
>>> soup.li
<li>Wired High Speed Internet Access in All Guest Rooms
     <span class="fee">
        25 USD per day
     </span>
</li>
>>> soup.li.string
>>> soup.li.text
u'Wired High Speed Internet Access in All Guest Rooms\n     \n        25 USD per day\n     \n'
>>> soup.li.get_text(' ', strip=True)
u'Wired High Speed Internet Access in All Guest Rooms 25 USD per day'

一定要在元素上调用它:

for index, test in enumerate(h3s.select("h3")):
    print("Feature title: ", test.text)
    ul = h3s.select("ul")[index]
    print(ul.get_text(' ', strip=True))

您可以在此处使用find_next_sibling() 函数,而不是索引到.select()

for header in h3s.select("h3"):
    print("Feature title: ", header.text)
    ul = header.find_next_sibling("ul")
    print(ul.get_text(' ', strip=True))

演示:

>>> for header in h3s.select("h3"):
...     print("Feature title: ", header.text)
...     ul = header.find_next_sibling("ul")
...     print(ul.get_text(' ', strip=True))
... 
Feature title: Room Features
Non-Smoking Room Connecting Rooms Available Private Terrace Sea View Room Suites Available Private Balcony Bay View Room Honeymoon Suite Starwood Preferred Guest Room Room with Sitting Area
Feature title: Internet Access
Wired High Speed Internet Access in All Guest Rooms 25 USD per day

【讨论】:

  • li in Internet Access 里面没有任何 span 先生......它的文字用 2ble-quotes 引用
  • @Umair:我将页面的相关部分复制到您的问题中。它非常确实里面有span元素。
  • 哦,是的...我正在使用谷歌浏览器检查它,它没有显示任何span ...但 FireBug 确实显示了这一点
  • 我收到错误 print(v.get_text(' ', strip=True)) 结果为 AttributeError: 'NavigableString' object has no attribute 'get_text'
  • @Umair:你确定你在&lt;li&gt;元素上使用它吗?
猜你喜欢
  • 1970-01-01
  • 2018-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-19
  • 1970-01-01
  • 2018-12-14
  • 2021-09-01
相关资源
最近更新 更多