#python #class #web-scraping #beautifulsoup
#python #класс #веб-скрапингинг #beautifulsoup
Вопрос:
Я пытаюсь получить информацию о продукте из Etsy и следую относительно простому руководству для этого.
Это мой текущий код:
headers = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.9 (KHTML, like Gecko) Version/9.0.2 Safari/601.3.9'}
#opening up connection, grabbing url
url = "https://www.etsy.com/sg-en/search/bath-and-beauty/soaps?q=green beautyamp;explicit=1amp;ref=paginationamp;page=1"
uclient = ureq(url)
page_html = uclient.read()
#html parsing
page_soup = soup(page_html, 'lxml')
print(page_soup.p)
#grabs each product
listings = page_soup.findAll("li", {"class":"wt-list-unstyled wt-grid__item-xs-6 wt-grid__item-md-4 wt-grid__item-lg-3 wt-order-xs-0 wt-order-sm-0 wt-order-md-0 wt-order-lg-0 wt-order-xl-0 wt-order-tv-0 grid__item-xl-fifth tab-reorder"})
len(listings)
Последний шаг повторно выводит 0, специально для этого класса, поэтому я не уверен, что я делаю неправильно. Основываясь на коде проверки, это подходящее имя класса и тип класса css для использования.
Etsy проверяет код здесь
Был бы очень признателен за любую помощь! Спасибо (-:
Комментарии:
1. сначала проверьте, не используется ли страница
javascript
для добавления элемента. Отключите JavScript в браузере и загрузите paga, чтобы посмотреть, что он показывает. Затем проверьте, что вы получаетеpage_soup
— возможно, сервер отправляет HTML с разными классами — или отправляет Captcha для блокировки ботов / скриптов. Наконец, используйте упрощенные классы — ie.find_all("li", {"class": "tab-reorder"})
— вам не обязательно использовать все классы, которые вы видите в браузере. Вы можете даже начать только с"li"
того, чтобы посмотреть, сможет ли он их найти.2. @firas, проверил javascript, и все в порядке! использовал ваш класс, и он сработал! как вы определили класс?
3. сначала я проверил только
li
и получил ~ 150 элементов. Затем я проверяю код в Inspect Code и сохраняю толькоtab-reorder
то, что что-то значит. Подобные классыgrid_item
могут использоваться во многих других элементах, а сервер может использовать разные значения / классы для разных устройств — ноутбука, планшета, телефона. Позже я увидел, что всеli
dev
они имеют аналогичный классtab-reorder-container
, и это сократило количество элементов до 65 — подобных элементов на странице.
Ответ №1:
Я могу получить 65 элементов, как на странице, используя более простые
soup.find("div", {"class": "tab-reorder-container"}).find_all("li", {"class":"tab-reorder"})
Сначала я использую find()
для получения региона со всеми элементами, а позже я использую find_all()
для поиска только li
в этом регионе.
import requests
from bs4 import BeautifulSoup as BS
headers = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_2) AppleWebKit/601.3.9 (KHTML, like Gecko) Version/9.0.2 Safari/601.3.9'}
#opening up connection, grabbing url
url = "https://www.etsy.com/sg-en/search/bath-and-beauty/soaps?q=green beautyamp;explicit=1amp;ref=paginationamp;page=1"
r = requests.get(url, headers=headers)
soup = BS(r.text, 'lxml')
print(soup.p)
#grabs each product
listings = soup.find('div', {'class': 'tab-reorder-container'}).find_all("li", {"class":"tab-reorder"})
print(len(listings))
for item in listings:
item = item.find('h3')
if item:
print(item.get_text(strip=True))
Но проблема в том, что эта страница используется JavaScript
для добавления элементов на страницу, и она находит 65 элементов, но большинство из них пустые, потому BS
что не удается запустить JavaScript
, чтобы добавить все значения в HTML.
Возможно, потребуется использовать Selenium для управления реальным веб-браузером, который может работать JavaScript
. Или может потребоваться проверить, есть ли другие данные где-то JavaScript
на странице, или если JavaScript
не считывает данные с другого URL-адреса — и тогда вы можете использовать этот URL с requests
Редактировать:
Версия, которая использует Selenium для загрузки страницы в Chrome / Firefox, закрывает всплывающее окно, прокручивает его до конца страницы и получает элементы с BeautifulSoup
и без BeautifulSoup
from bs4 import BeautifulSoup as BS
import selenium.webdriver
import time
#opening up connection, grabbing url
url = "https://www.etsy.com/sg-en/search/bath-and-beauty/soaps?q=green beautyamp;explicit=1amp;ref=paginationamp;page=1"
driver = selenium.webdriver.Chrome()
#driver = selenium.webdriver.Firefox()
driver.get(url)
time.sleep(3)
driver.find_element_by_xpath('//button[@data-gdpr-single-choice-accept]').click()
# Get scroll height
last_height = driver.execute_script("return document.body.scrollHeight")
while True:
# Scroll down to bottom
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
# Wait to load page
time.sleep(1.5)
# Calculate new scroll height and compare with last scroll height
new_height = driver.execute_script("return document.body.scrollHeight")
if new_height == last_height:
break
last_height = new_height
print('--- version 1 - BeautifulSoup ---')
html = driver.page_source
soup = BS(html, 'lxml')
print(soup.p)
#grabs each product
listings = soup.find('div', {'class': 'tab-reorder-container'}).find_all("li", {"class":"tab-reorder"})
print(len(listings))
for item in listings:
item = item.find('h3')
if item:
print(item.get_text(strip=True))
print('--- version 2 - Selenium ---')
#grabs each product
listings = driver.find_elements_by_css_selector('div.tab-reorder-container li.tab-reorder')
print(len(listings))
for item in listings:
item = item.find_element_by_css_selector('h3')
if item:
print(item.text.strip())
Комментарии:
1. хм, я пробовал этот код, но он продолжает говорить мне, что у str нет атрибута find_all
2. @firas также, когда я попытался выполнить цикл с помощью listings = page_soup.findAll(«li», {‘class’ = ‘tab-reorder’}), я получил результат 130; но некоторые из этих результатов [<li class=»wt-list-unstyled wt-grid__item-xs-6 wt-grid__item-md-4 wt-grid__item-lg-3 wt-order-xs-17 wt-order-sm-17 wt-order-md-11 wt-order-lg-9 wt-order-xl-7 wt-order-tv-7 grid__item-xl-пятая вкладка-изменить порядок»> <div> <p class=»только для чтения с экрана»> Загрузка… </p> <div class=»wt-display-block»> <div class=»wt-skeleton-ui wt-skeleton-ui—image-landscape»></div> <div class=»wt-skeleton-ui wt-skeleton-ui—body-01wt-mt-xs-1″>…
3. по сути, это всего лишь набор из них, и я не знаю, что делать с этой информацией — очень ценю вашу помощь!
4. и это то, что я говорил ранее — он используется
JavaScript
для добавления информацииHTML
вместоLoading...
, ноBS
не может быть запущенJavaScript
, и вам может понадобиться Selenium для управления реальным веб-браузером, который может работатьJavaScript
, и он может предоставить вамHTML
всю информацию. Но может потребоваться также прокручивать страницу, чтобы принудительноJavaScript
добавлять информацию — потому что многие страницы добавляют элементы только на страницу прокрутки пользователя.5. Я добавил код, который использует Selenium для получения всех элементов. Для этого нужно было открыть браузер, закрыть всплывающее окно, прокрутить страницу — так он работает дольше.
Ответ №2:
Особенность bs4 (или, может быть, я не до конца понимаю это …), Попробуйте это вместо:
listings = page_soup.find_all("li", class_="wt-list-unstyled wt-grid__item-xs-6 wt-grid__item-md-4 wt-grid__item-lg-3 wt-order-xs-0 wt-order-sm-0 wt-order-md-0 wt-order-lg-0 wt-order-xl-0 wt-order-tv-0 grid__item-xl-fifth tab-reorder")