【问题标题】:Why does BeautifulSoup return empty list on search results websites?为什么 BeautifulSoup 在搜索结果网站上返回空列表?
【发布时间】:2019-02-19 00:54:49
【问题描述】:

我希望在线获取特定文章的价格,但我似乎无法获取标签下的元素,但我可以在网站的另一个(不同)站点上进行。在这个特定的站点中,我只得到一个空列表。打印soup.text 也可以。如果可能,我不想使用 Selenium,因为我想了解 BS4 如何在这种情况下工作。

import requests
from bs4 import BeautifulSoup
url = 'https://reverb.com/p/electro-harmonix-oceans-11-reverb-2018'

r = requests.get(url)
soup = BeautifulSoup(r.content, 'html.parser')
cards = soup.select(".product-row-card")
print (cards)
>>>[]

我想得到的是网站上卡片的名称和价格。我以前也遇到过这个问题,但是这里的每个解决方案都只建议使用 Selenium(我可以使用它),但我不知道为什么。我觉得它更不实用。

另外,当我读到该网站正在使用 javascript 来获取此结果时,是否有机会。如果是这样的话,为什么我可以在https://reverb.com/price-guide/effects-and-pedals 中获取数据,而不是在这里?在这种情况下,Selenium 会是唯一的解决方案吗?

【问题讨论】:

    标签: python web-scraping beautifulsoup python-requests


    【解决方案1】:

    您的目标网站依赖 javascript 来呈现您尝试获取的数据是正确的。问题是 requests 不评估 javascript。

    Selenium WebDriver 经常在这些情况下使用也是正确的,因为它驱动一个真正的、成熟的浏览器实例。但这不是唯一的选择,因为requests-html 支持 javascript,并且对于简单的抓取来说可能不那么麻烦。

    作为入门示例,以下获取您正在访问的网站上前五个项目的标题和价格:

    from requests_html import HTMLSession
    from bs4 import BeautifulSoup
    
    session = HTMLSession()
    r = session.get("https://reverb.com/p/electro-harmonix-oceans-11-reverb-2018")
    r.html.render(sleep=5)
    
    soup = BeautifulSoup(r.html.raw_html, "html.parser")
    for item in soup.select(".product-row-card", limit=5):
        title = item.select_one(".product-row-card__title__text").text.strip()
        price = item.select_one(".product-row-card__price__base").text.strip()
        print(f"{title}: {price}")
    

    结果:

    Electro-Harmonix EHX Oceans 11 十一混响厅弹簧吉他效果踏板:119.98 美元 Electro-Harmonix Oceans 11 混响 - 二手:119.99 美元 Electro-Harmonix Oceans 11 多功能数字混响效果踏板:122 美元 二手 Electro-Harmonix Oceans 11 混响多效果踏板使用:142.27 美元 Electro-Harmonix Oceans 11 混响哑光黑:110 美元

    【讨论】:

    • 嘿!惊人的答案。非常感谢。那么,这里加载 javascript 的过程是创建一个 HTMLSession 对象来获取嵌入了 javascript 的 URL?或者这能达到什么目的?你介意多解释一下它是如何工作的吗?
    • @JulianP 使HTMLSessionrequests 中的常规旧Session 不同的主要因素是render() 方法。它获取使用get() 检索的内容并将其加载到Chrome 实例(实际上是Chromium)中。这会评估 javascript 并作为结果呈现整个页面。将 sleep=5 参数传递给它会告诉它等待 5 秒,以便为诸如 ajax 数据请求之类的事情提供一些时间来完成。您可以阅读有关render() 方法here 的更多信息。
    • 我还有一个问题。 (很抱歉打扰您)但是您的代码似乎返回了六个价格和五个名称,它跳过了一个名称(第二个),我似乎不明白为什么。似乎它没有成功获得第二个名称,只是在单独打印其价格后再次尝试。
    猜你喜欢
    • 2016-02-27
    • 2016-02-06
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 2018-11-22
    • 1970-01-01
    • 2016-03-21
    相关资源
    最近更新 更多