#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 или куда угодно, где вы хотите их сохранить. Другие могут его клонировать, и у них будет написанный вами код, поэтому его можно получить в нескольких местах, если он клонируется более одного раза.