【问题标题】:Why am I getting an AttributeError scraping with BeautifulSoup?为什么我在使用 BeautifulSoup 进行抓取时出现 AttributeError 错误?
【发布时间】:2021-12-11 22:33:25
【问题描述】:

我在使用 BeautifulSoup 抓取网页时收到AttributeError。我想从具有特定选择器的网页中获取特定文本,但出现此错误。谁能告诉我如何正确使用下面给出的 CSS 选择器?

错误:

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

CSS 选择器

#col-body > div > social-influence > div.row.row-zero.influence-others.panel-inactive > div:nth-child(3) > h4

我的代码

from bs4 import BeautifulSoup
import requests

html = requests.get("https://www.cryptocompare.com/coins/bnb/influence/USDT").text
soup = BeautifulSoup(html, 'html.parser')
total_commit = soup.select_one("#col-body div social-influence div.row.row-zero.influence-others.panel-inactive div:nth-child(3) h4").text
print(total_commit)

预期输出:

We don't have any code repository data yet.

【问题讨论】:

  • 您在代码中使用的 CSS 选择器与单独显示的选择器不同吗? > 表示直接在下面找到一个元素,而空格表示它将继续深入查看树。
  • @CrazyChucky 它们是相同的选择器,我刚刚删除了> 以使其工作,这是错误的吗?我只是直接从检查元素复制并粘贴了选择器,我曾经使用 node.js 处理 puppet,我只是复制粘贴了选择器,但在 BS4 中我必须删除 > 是不是错了?你能告诉我在这种情况下使用 CSS 选择器的正确顺序吗?

标签: python beautifulsoup


【解决方案1】:

事实证明,您的 CSS 选择器没有任何问题(您显示的原始版本或代码中使用的修改版本;两者都选择了相同的内容)。问题是您想要的页面部分是由 JavaScript 动态生成的,所以它不在 HTML 中。要查看此内容,请尝试:

from bs4 import BeautifulSoup
import requests

html = requests.get(
    'https://www.cryptocompare.com/coins/bnb/influence/USDT'
).text
with open('output.txt', 'w') as f:
    f.write(html)

如果您在结果文件中搜索 "We don't have any code repository data yet.",您会发现它不存在。

因此,我们不仅需要访问 HTML 页面,还需要运行其 JavaScript,并保存生成页面的源代码。正如this answer 中所述,您可以使用 Selenium 执行此操作。您首先必须安装 Selenium(pip install selenium 应该可以工作),然后根据您的操作系统下载 geckodriver 可执行文件。

完成后,您的代码(带有Mr.Manhattan's addition)将如下所示:

from contextlib import closing

from bs4 import BeautifulSoup
from selenium.webdriver import Firefox

with closing(Firefox()) as browser:
    browser.get('https://www.cryptocompare.com/coins/bnb/influence/USDT')
    html = browser.page_source

soup = BeautifulSoup(html, 'html.parser')
total_commit_node = soup.select_one(
    '#col-body > div > social-influence > '
    'div.row.row-zero.influence-others.panel-inactive > div:nth-child(3) > h4'
)

if total_commit_node:
    print(total_commit_node.text)
else:
    print('Could not match CSS selector')

(注意:我将选择器分成两行以避免滚动。它的功能完全相同,因为consecutive string literals are automatically concatenated。)

对我来说,这正确输出:

We don't have any code repository data yet.

【讨论】:

  • @SiddharthTiwari 这解决了您的问题吗?如果您认为它回答了您的问题,请考虑点击复选标记接受它。
【解决方案2】:

您的查询与任何内容都不匹配:

total_commit_node  = soup.select_one(
    '#col-body div social-influence div.row.row-zero.influence-others.panel-inactive div:nth-child(3) h4')

if total_commit_node:
    print(total_commit_node.text)
else:
    print('Could not match css selector')

【讨论】:

  • 我已经编辑了抱歉给您带来的不便
  • 不适合我
  • Mr.Manhattan,编辑后的问题还是您回答的问题吗?如果没有,OP 应该撤消问题编辑,在这种情况下,可以重新打开当前版本的其他地方的副本。
  • @Yunnosch 答案仍然正确地适用于该问题。 (它没有解决第二部分——如何使用 CSS 选择器——但它涵盖了错误发生的原因,这在编辑之前和之后都是一样的。)
  • @SiddharthTiwari “不工作”是什么意思?该答案可能无法涵盖您提出的所有问题,但就其而言是正确的。而且没有必要要求他们删除它;其他人仍然可以根据需要添加答案。
猜你喜欢
  • 2020-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-18
  • 1970-01-01
  • 2019-08-28
  • 1970-01-01
  • 2019-03-24
相关资源
最近更新 更多