【问题标题】:BeautifulSoup sometimes gives exceptionsBeautifulSoup 有时会出现异常
【发布时间】:2015-02-13 18:01:30
【问题描述】:

奇怪的是,有时 BeautifulSoup 对象确实提供了所需的数据,但有时我会收到类似或 listindex errorout of rangenonetype 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)

【问题讨论】:

    标签: python web-scraping beautifulsoup html-parsing web-crawler


    【解决方案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
    

    如果文本很多,则将其写入文件。

    将这么多操作串在一行中也很危险。如果出现问题,那么您将不知道是什么。将其拆分为几行,以便您快速查看是否可以找到Socketdd 元素等。

    【讨论】:

    • “你应该改进你的错误处理”似乎更适合评论而不是回答我......
    猜你喜欢
    • 2013-08-17
    • 2017-07-18
    • 1970-01-01
    • 1970-01-01
    • 2013-01-13
    • 2018-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多