【问题标题】:Using web scraping to check if an item is in stock使用网络抓取检查商品是否有货
【发布时间】:2021-02-01 13:04:16
【问题描述】:

我正在创建一个 Python 程序,该程序使用网络抓取来检查商品是否有货。该代码是 Python 3.9 脚本,使用 Beautiful Soup 4 并请求抓取该项目的可用性。我最终想让程序搜索多个网站和每个网站内的多个链接,这样我就不必一次运行一堆脚本。程序的预期结果是这样的:
200
0
In Stock
但我得到了:
200
[]
Out Of Stock

'200'表示代码是否可以访问服务器,200是预期结果。 “0”是一个布尔值,用于查看该项目是否有库存,预期的响应是“0”表示有货。我已经给它提供了库存商品和缺货商品,它们都给出了相同的回复200 [] Out Of Stock。我感觉def check_item_in_stock 中的out_of_stock_divs 有问题,因为这是我得到[] 的结果,因为它找到了该项目的可用性

昨天早些时候我的代码可以正常工作,但我一直在添加功能(比如它抓取多个链接和不同的网站),结果破坏了它,我无法让它恢复到工作状态

这是程序代码。 (我确实将此代码基于 Arya Boudaie 先生在他的网站上的代码,https://aryaboudaie.com/ 我摆脱了他的文本通知,因为我打算只在我旁边的备用计算机上运行它并让它播放响亮的声音,这将在以后实施。)

from bs4 import BeautifulSoup
import requests

def get_page_html(url):
    headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"}
    page = requests.get(url, headers=headers)
    print(page.status_code)
    return page.content


def check_item_in_stock(page_html):
    soup = BeautifulSoup(page_html, 'html.parser')
    out_of_stock_divs = soup.findAll("text", {"class": "product-inventory"})
    print(out_of_stock_divs)
    return len(out_of_stock_divs) != 0

def check_inventory():
    url = "https://www.newegg.com/hp-prodesk-400-g5-nettop-computer/p/N82E16883997492?Item=9SIA7ABC996974"
    page_html = get_page_html(url)
    if check_item_in_stock(page_html):
        print("In stock")
    else:
        print("Out of stock")

while True:
    check_inventory()
    time.sleep(60)```

【问题讨论】:

    标签: python python-3.x web-scraping beautifulsoup


    【解决方案1】:

    产品库存状态位于<div> 标签内,而不是<text> 标签内:

    import requests
    from bs4 import BeautifulSoup
    
    
    def get_page_html(url):
        headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"}
        page = requests.get(url, headers=headers)
        print(page.status_code)
        return page.content
    
    
    def check_item_in_stock(page_html):
        soup = BeautifulSoup(page_html, 'html.parser')
        out_of_stock_divs = soup.findAll("div", {"class": "product-inventory"})  # <--- change "text" to div
        print(out_of_stock_divs)
        return len(out_of_stock_divs) != 0
    
    def check_inventory():
        url = "https://www.newegg.com/hp-prodesk-400-g5-nettop-computer/p/N82E16883997492?Item=9SIA7ABC996974"
        page_html = get_page_html(url)
        if check_item_in_stock(page_html):
            print("In stock")
        else:
            print("Out of stock")
    
    check_inventory()
    

    打印:

    200
    [<div class="product-inventory"><strong>In stock.</strong></div>]
    In stock
    

    注意:该站点的 HTML 标记过去可能已更改,我将修改 check_item_in_stock 函数:

    def check_item_in_stock(page_html):
        soup = BeautifulSoup(page_html, 'html.parser')
        out_of_stock_div = soup.find("div", {"class": "product-inventory"})
        return out_of_stock_div.text == "In stock."
    

    【讨论】:

    • 谢谢!我很快就会在这里试试。我想知道为什么 Boudaie 先生有 ```return out_of_stock_div != 0,我很可能会将其更改为更具可读性。
    【解决方案2】:

    您可以使用lxml 库以一种非常易读且稍微优雅的方式来完成这项工作:

    import config
    import requests
    from lxml import html
    
    def in_stock(url: str = config.upstream_url) -> tuple:
        """ Check the website for stock status """
        page = requests.get(url, headers={'User-agent': config.user_agent})
        proc_html = html.fromstring(page.text)
        checkout_button = proc_html.get_element_by_id('addToCart')
        return (page.status, not ('disabled' in checkout_button.attrib['class']))
    

    我建议使用 xpath 来识别页面上您要检查的元素。这使得它在上游网站更新(超出您的控制范围)的情况下成为Easy to Change,因为您只需要调整 xpath 字符串以反映上游更改:

    # change me, if upstream web content changes
    xpath_selector = r'''///button[@id='addToCart']'''
    checkout_button = proc_html.xpath(xpath_selector)[0]
    

    顺便说一句,在风格上,一些纯粹主义者会建议在编写函数时避免副作用(即在函数中使用print())。您可以返回带有状态代码和结果的元组。这是 Python 中一个非常好的特性。

    【讨论】:

    • 好的!我得试一试!
    • 如果您运行的是 Firefox,则很容易找到元素的 XPath。右键单击元素,选择Inspect。在开发人员工具(检查器)中,右键单击感兴趣的 HTML 标记,* Copy->XPath * 您可能需要对其进行一些编辑,但这应该可以帮助您入门。
    【解决方案3】:

    也许您已经知道这一点,但 Git 是您的朋友。每当您进行更改时,将其推送到 github 或您选择保存的任何地方。其他人可以克隆它,他们将拥有您编写的代码,因此如果多次克隆它可以在多个地方检索。

    【讨论】:

      猜你喜欢
      • 2023-03-30
      • 1970-01-01
      • 2021-12-04
      • 2022-09-27
      • 2021-02-02
      • 1970-01-01
      • 2017-03-17
      • 1970-01-01
      • 2021-07-22
      相关资源
      最近更新 更多