BeautifulSoup 有时会出现异常
Posted
技术标签:
【中文标题】BeautifulSoup 有时会出现异常【英文标题】:BeautifulSoup sometimes gives exceptions 【发布时间】:2015-02-13 18:01:30 【问题描述】:奇怪的是,有时 BeautifulSoup 对象确实提供了所需的数据,但有时我会收到类似或 listindex error
或 out of range
或 nonetype object does not have attribute findNext()
的错误,这是嵌套在其他元素中的数据。
这是代码:
url = 'http://www.computerstore.nl/product/470130/category-208983/asrock-z97-extreme6.html'
source_code = requests.get(url)
plain_text = source_code.text
soup = BeautifulSoup(plain_text)
a = soup.find(text=('Socket')).find_next('dd').string
print(a)
【问题讨论】:
【参考方案1】:实际问题是单元格值并不总是Socket
,有时它被制表符或空格包围。不要检查确切的text
匹配,而是传递compiled regular expression pattern:
import re
soup.find(text=re.compile('Socket')).find_next('dd').get_text(strip=True)
总是打印1150
。
解释我使用过的“有时”这个词(感谢@carpetsmoker 在 cmets 中的最初提议):
如果您打开页面,然后清理 cookie 并刷新页面,您可能会看到同一页面的两种不同外观:
如您所见,页面上的块排列方式不同。因此,同一个页面有两种不同的外观和 HTML 源代码 - 您看到的是 AB-testing 技术:
在营销和商业智能中,A/B 测试是 有两个变体 A 和 B 的随机实验,它们是 对照实验中的对照和处理。它是一种形式 使用两种变体的统计假设检验导致 技术术语,双样本假设检验,用于以下领域 统计数据。
换句话说,他们正在尝试产品页面并收集统计数据,例如点击率、销售数量等。
仅供参考,这是我目前得到的工作代码:
import re
from bs4 import BeautifulSoup
import requests
session = requests.Session()
headers = 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36'
session.get('http://www.computerstore.nl', headers=headers)
response = session.get('http://www.computerstore.nl/product/470130/category-208983/asrock-z97-extreme6.html', headers=headers)
soup = BeautifulSoup(response.content)
print(soup.find(text=re.compile('Socket')).find_next('dd').get_text(strip=True))
【讨论】:
"反网页抓取技术";不,这似乎是 AB 测试;如果您在浏览器中禁用 cookie,并打开几个选项卡,您将在某些页面中获得不同的 HTML 页面 :-) 我试图通过回显 cookie 来保持相同的页面布局,但似乎没有一种明显的方法可以获取您实际查看的页面,因此您被困在同样的问题,但这很丑:-/ @Carpetsmoker 我已经更新了答案——显然是 AB 测试。再次感谢您的提示。 好吧,你说得对,它现在可以工作的套接字,谢谢,但我也有这个问题,因为另外两个数据 'Format Moederbord' 和 'Chipset' 。如果我使用你说的代码而不是'Socket''Formaat Moederbord'或'Chipset',它会再次出现问题,我该如何解决这个问题。 @user3660293 好吧,它适用于Chipset
,就像它适用于Socket
一样,但Formaat Moederbord
- 这是一个不同的故事,这是你可以找到的方法它(适用于 A 和 B 情况)print(soup.find(text=re.compile('Formaat moederbord')).find_parent(['td', 'dt']).find_next(['td', 'dd']).find_next(['td', 'dd']).get_text(strip=True))
.【参考方案2】:
我对您的代码进行了建议更改:
url = 'http://www.computerstore.nl/product/470130/category-208983/asrock-z97-extreme6.html'
source_code = requests.get(url)
plain_text = source_code.text
soup = BeautifulSoup(plain_text)
if soup.find(text=('Socket')):
a = soup.find(text=('Socket')).find_next('dd').string
else:
# Display some error info, and/or do some error logging
print "error"
print(a)
【讨论】:
你应该只发布完整的答案,而不是关于如何改进代码的 cmets。那些可以留在问题上的 cmets 或 pehaps na Answer... 所以,帮助我提高理解力。在 alexce 的原始问题的上下文中,我的答案如何或将成为“完整”答案? 见this help page;它与大多数论坛等有点不同,只提供诸如此类的有用提示就可以了。这样做的最大好处是,当您通过互联网搜索或其他方式进入这样的页面时,它大大减少了“噪音”的数量(在论坛上,您有时会有页面和垃圾页面需要挖掘).. . 感谢帮助页面链接。但是,我没有看到任何提到“完整”答案的内容,我仍然对是什么让我的答案不完整感到困惑?特别是,考虑到我使用了该人的原始问题并补充了我的解决方案。【参考方案3】:这意味着商店返回的数据由于某种原因不包含您寻找的元素。
在代码中添加一些适当的错误处理,以捕获异常并在中断时转储输入。这样,您可以查看下载的内容并改进代码。
第一步是:
try:
a = soup.find(text=('Socket')).find_next('dd').string
print(a)
except:
print(plain_text)
raise
如果文本很多,则将其写入文件。
将这么多操作串在一行中也很危险。如果出现问题,那么您将不知道是什么。将其拆分为几行,以便您快速查看是否可以找到Socket
或dd
元素等。
【讨论】:
“你应该改进你的错误处理”似乎更适合评论而不是回答我......以上是关于BeautifulSoup 有时会出现异常的主要内容,如果未能解决你的问题,请参考以下文章
ajax异步提交 有时会出现无bug的数据处理异常-----debug没有问题,正常运行却数据处理不正确,极少机会会出现正常的处理结果