Использование веб-очистки для проверки наличия товара на складе

#python #python-3.x #web-scraping #beautifulsoup

#python #python-3.x #веб-очистка #beautifulsoup

Вопрос:

Я создаю программу на Python, которая использует веб-очистку для проверки наличия товара на складе. Код представляет собой скрипт на Python 3.9, использующий Beautiful Soup 4 и запрашивающий информацию о доступности товара. В конечном итоге я хотел бы заставить программу выполнять поиск по нескольким веб-сайтам и нескольким ссылкам на каждом сайте, чтобы мне не приходилось запускать кучу скриптов одновременно. Ожидаемый результат программы таков:
200
0
In Stock
Но я получаю:
200
[]
Out Of Stock

«200» означает, может ли код получить доступ к серверу, 200 — ожидаемый результат. ‘0’ — это логическое значение, позволяющее узнать, есть ли товар на складе, ожидаемый ответ — либо ‘0’ для на складе. Я предоставил ему как имеющиеся в наличии, так и отсутствующие на складе товары, и оба они дают одинаковый ответ 200 [] Out Of Stock . У меня такое чувство, что что-то не так с out_of_stock_divs внутри def check_item_in_stock , потому что именно там я получаю [] результат поиска доступности товара

Ранее вчера у меня был корректный код, и я продолжал добавлять функции (например, очищать несколько ссылок и разные веб-сайты), и это сломало его, и я не могу вернуть его в рабочее состояние

Вот программный код. (Я основал этот код на коде г-на Арьи Будаи на его веб-сайте, 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)```
  

Ответ №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."
  

Комментарии:

1. Спасибо! Я скоро попробую это здесь. Мне было интересно, почему у мистера Боудаи было «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 для идентификации элемента на странице, которую вы хотите изучить. Это упрощает изменение в случае обновления веб-сайта (вне вашего контроля), поскольку вам нужно всего лишь настроить строку xpath, чтобы отразить изменения, внесенные в вышестоящий поток:

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

Кстати, стилистически некоторые пуристы советуют избегать побочных эффектов при написании функций (т. Е. Использования print() внутри функции). Вы можете вернуть кортеж с кодом состояния и результатом. Это действительно хорошая функция в Python.

Комментарии:

1. Хорошо! Я должен попробовать!

2. Если вы используете Firefox, очень легко найти XPath для элемента. Щелкните правой кнопкой мыши на элементе, выберите Проверить . В инструментах разработчика (Инспектор) щелкните правой кнопкой мыши интересующий HTML-тег, * Копировать-> XPath * Возможно, вам потребуется его немного отредактировать, но это должно помочь вам начать.

Ответ №3:

Возможно, вы это уже знаете, но Git — ваш друг. Всякий раз, когда вы вносите изменения, отправляйте их на github или куда угодно, где вы хотите их сохранить. Другие могут его клонировать, и у них будет написанный вами код, поэтому его можно получить в нескольких местах, если он клонируется более одного раза.