#python-3.x #web-scraping #scrapy
#python-3.x #веб-очистка #scrapy
Вопрос:
Некоторое время назад я настроил веб-скребок с использованием BS4, регистрируя стоимость виски каждый день
import requests
from bs4 import BeautifulSoup
def getPrice() -> float:
try:
URL = "https://www.thewhiskyexchange.com/p/2940/suntory-yamazaki-12-year-old"
website = requests.get(URL)
except:
print("ERROR requesting Price")
try:
soup = BeautifulSoup(website.content, 'html.parser')
price = str(soup.find("p", class_="product-action__price").next)
price = float(price[1::])
return price
except:
print("ERROR parsing Price")
Это сработало так, как задумывалось. Запрос содержал полный веб-сайт, и было извлечено правильное значение.
На этот раз я пытался очистить другие сайты от данных о других виски, используя SCRAPY.
Я попробовал следующие URL-адреса:
https://www.thegrandwhiskyauction.com/past-auctions/q-macallan/180-per-page/relevance
import scrapy
class QuotesSpider(scrapy.Spider):
name = "whisky"
def start_requests(self):
user_agent = 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36'
urls = [
'https://www.thegrandwhiskyauction.com/past-auctions/q-macallan/180-per-page/relevance',
]
for url in urls:
yield scrapy.Request(url=url, callback=self.parse)
def parse(self, response):
page = response.url.split("/")[-2]
filename = f'whisky-{page}.html'
#data = response.css('.itemDetails').getall()
with open(filename, 'wb') as f:
f.write(response.body)
Я просто настроил базовый пример из руководства для создания быстрого прототипа выше.
Однако он не вернул полный веб-сайт. В теле ответа действительно отсутствовали несколько тегов и особенно контент, который я искал.
Я снова попытался решить это с помощью BS4 следующим образом:
import requests
from bs4 import BeautifulSoup
URL = "https://www.thegrandwhiskyauction.com/past-auctions/q-macallan/180-per-page/relevance"
website = requests.get(URL)
soup = BeautifulSoup(website.content, 'html.parser')
with open("whiskeySoup.html", 'w') as f:
f.write(str(soup.body))
К моему удивлению, это привело к тому же результату. Запрос и его тело не содержали полного веб-сайта, отсутствовали все данные, которые я искал.
Я также включил заголовок user-agent, поскольку узнал, что некоторые сайты распознают запросы от ботов и пауков и не доставляют все свои данные. Однако это не решило проблему.
Я не могу выяснить или отладить, почему данные, запрошенные с этих URL-адресов, являются неполными. Есть ли способ решить эту проблему с помощью SCRAPY?
Ответ №1:
Многие веб-сайты в значительной степени полагаются на javascript для создания окончательной HTML-страницы веб-сайта. Когда вы отправляете запрос на сервер, он возвращает html-код с помощью некоторых скриптовых веб-браузеров, таких как Chrome, Firefox и другие, обрабатывают этот код javascript, и появляется конечный html, который вы можете видеть. Но когда вы используете scrapy, request или какую-либо библиотеку, они не имеют функциональности выполнения кода javascript, и, следовательно, html-код отличается от html, и поскольку поисковый робот видит веб-страницу. Если вы хотите увидеть, как поисковый робот видит веб-сайт (html-код веб-страницы, видимый сканером), вы можете запустить команду ‘scrapy view {url}’, это откроет страницу в браузере, или если вы хотите получить html-код веб-страницы, видимый сканером, вы можете запустить команду ‘scrapy fetch{url}’. Когда вы работаете с scrapy, рекомендуется открыть URL-адрес в оболочке (команда ‘scrapy shell {url}’ ), а затем протестировать вашу логику извлечения желаемого содержимого с помощью метода xpath или css (response.css (‘some_css’).css (‘again_some_css’). )и затем, наконец, добавьте эту логику в свой окончательный поисковый робот. Если вы хотите посмотреть, какой ответ вы получили в shell. вы можете просто ввести view (ответ), и он откроет ответ, полученный в браузере. Надеюсь, это понятно. Но если вы хотите обработать javascript перед окончательной обработкой ответа (когда это необходимо), вы можете использовать selenium, который является безголовым браузером, или splash, который является легким веб-браузером. selenium довольно прост в использовании.
Редактировать 1. Для первого URL: перейдите в оболочку scrapy и проверьте путь css div.bidPrice::text. Внутри этого вы увидите, что содержимое внутри генерируется динамически, и нет html-кода, а содержимое генерируется динамически.
Комментарии:
1. Спасибо, но я все еще немного в замешательстве. Пытаясь использовать первый упомянутый мной URL-адрес, scrapy view {url} и scrapy shell {url} view (response) отображают веб-сайт правильно, то есть заполняют все данные, которые я ищу. Цена корректно доступна через css path div.bidPrice::text в предварительном просмотре ответа в браузере. Однако response.css(«div.bidPrice::text»).getall() возвращает только некоторое «n».
2. в оболочке scrapy запустите response.css(‘div.bidPrice’).get() здесь вы увидите первый блок div, поскольку он извлекается сканером. здесь цена предложения и другой текст внутри поля отсутствуют, вместо этого есть некоторые переменные, такие как%bid_descriptor_text% %multi_currency% и тому подобное. Но когда тот же HTML-код просматривается в веб-браузере, я думаю, должен быть какой-скрипт в код HTML код ( добавлено с <script> tag ) which gets executed when this code is opened with browser. но при запуске из shell n внутри этого div присутствует только текст. Я думаю, что здесь необходим selenium.