#python #selenium-webdriver #web-scraping
#python #selenium-webdriver #очистка веб-страниц
Вопрос:
Это URL для тестирования https://stockx.com/puma?prices=300-400 ,200-300amp;size_types= мужчины и годы = 2017
Я могу извлечь все href
ссылки на страницу с подробным описанием продукта, однако в конце я получаю только один результат. Предполагается, что он переходит по всем ссылкам и извлекает мне имя и URL-адрес img. Чего мне здесь не хватает?
Текущий результат вывода в формате json
[
{
"product_name": "Puma Clyde WWE Undertaker Black",
"imgurl": "https://stockx.imgix.net/Puma-Clyde-WWE-Undertaker-Black.png?fit=fillamp;bg=FFFFFFamp;w=700amp;h=500amp;auto=format,compressamp;q=90amp;dpr=2amp;trim=coloramp;updated_at=1538080256"
}
]
это рабочий код
import selenium
import json
import time
import re
import string
import requests
import bs4
from selenium import webdriver
from selenium.webdriver import Firefox
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support.select import Select
domain = 'https://stockx.com/puma?prices=300-400,200-300amp;size_types=menamp;years=2017'
def prepare_driver(url):
options = Options()
# options.add_argument('-headless')
driver = webdriver.Chrome(executable_path='/Users/Documents/python/Selenium/bin/chromedriver')
driver.get(url)
time.sleep(2)
wait = WebDriverWait(driver, 10).until(EC.presence_of_element_located(
(By.CLASS_NAME, 'title-container')))
return driver
def fill_form(driver, search_argument):
'''Finds all the input tags in form and makes a POST requests.'''
#search_field = driver.find_element_by_id('q')
#search_field.send_keys(search_argument)
# We look for the search button and click it
#driver.find_element_by_class_name('search__submit')
#.click()
wait = WebDriverWait(driver, timeout=10).until(
EC.presence_of_all_elements_located(
(By.CLASS_NAME, 'title-container')))
def scrape_results(driver, n_results):
'''Returns the data from n_results amount of results.'''
product_urls = list()
product_data = list()
for product_title in driver.find_elements_by_css_selector("div[class*='tile browse-tile']"):
product_urls.append(product_title.find_element_by_css_selector(
"a[href*='/']").get_attribute('href'))
print(*product_urls, sep = "n")
for url in range(0, n_results):
if url == n_results:
break
url_data = scrape_product_data(driver, product_urls[url])
product_data.append(url_data)
#print(*product_data, sep = "n")
return product_data
def scrape_product_data(driver, product_url):
'''Visits an product page and extracts the data.'''
if driver == None:
driver = prepare_driver(product_url)
driver.get(product_url)
time.sleep(12)
product_fields = dict()
# Get the product name
product_fields['product_name'] = driver.find_element_by_xpath(
'//div[@class="col-md-12"]/h1').text
# Get the image url
product_fields['imgurl'] = driver.find_element_by_xpath(
'//img[@class="product-image"]').get_attribute('src')
return product_fields
if __name__ == '__main__':
try:
driver = prepare_driver(domain)
#fill_form(driver, 'juniole tf')
product_data = scrape_results(driver, 4)
product_data = json.dumps(product_data, indent=4) #ensure_acii => changes japanese to correct character
with open('booking_data_stockx.json', 'w') as f:
f.write(product_data)
finally:
driver.quit()
Комментарии:
1. Я не запускал код, но я думаю, что это связано с областью видимости. Вы не добавляете следующий элемент в свой dict(), вы перезаписываете его каждый раз, когда находите элемент.
2. это странно, потому что я сделал то же самое с другим веб-сайтом, и это сработало нормально. Также было бы неплохо посмотреть, сможет ли кто-нибудь запустить код, когда у них будет время, и посмотреть, сможет ли кто-нибудь решить это.
3. почему вы не можете взять URL-адрес img и названия продуктов с первой страницы. Чем отличается от страниц, которые вы посещаете?
4. У меня есть другие данные, которые доступны только на страницах сведений о продукте. Я сначала тестирую его с базовой информацией, прежде чем разрабатывать более сложный код.
Ответ №1:
Я думаю, вы можете сделать все это с помощью запросов. Я выбрал несколько случайных элементов из посещенных страниц, чтобы подтвердить посещаемость.
import requests
from bs4 import BeautifulSoup as bs
import pandas as pd
baseURL = 'https://stockx.com'
final = []
with requests.Session() as s:
res = s.get('https://stockx.com/puma?prices=300-400,200-300amp;size_types=menamp;years=2017')
soup = bs(res.content, 'lxml')
items = soup.select('#products-container [href]')
titles = [item['id'] for item in items]
links = [baseURL item['href'] for item in items]
results = list(zip(titles, links))
df = pd.DataFrame(results)
for result in results:
res = s.get(result[1])
soup = bs(res.content, 'lxml')
details = [item.text for item in soup.select('.detail')]
final.append([result[0], result[1], details])
df2 = pd.DataFrame(final)
df2.to_csv(r'C:UsersUserDesktopdata.csv', sep=',', encoding='utf-8',index = False )
Комментарии:
1. большое вам спасибо и вау, я не знал, что этот метод намного проще и короче. Я хотел бы подробнее остановиться на вашей работе. Если я могу попросить немного больше информации для очистки. Как бы я получил информацию в этом контейнере?
details = [item.text for item in soup.select('.pinfo-container')]
. Кроме того, каков наилучший способ выгрузить эту информацию в формате csv, json или text?2. привет, сейчас я посмотрю. Какую информацию вы хотели?
3. привет, Qharr, действительно ценю ваше время. Эта информация приведена на странице сведений о продукте. СТИЛЬ 364669-04 COLORWAY ЧЕРНЫЙ / ЗОЛОТОЙ РОЗНИЧНАЯ ЦЕНА $ 500 ДАТА ВЫПУСКА 2017-04-01
4. с какого URL-адреса вы это извлекли, пожалуйста?
5. еще раз большое вам спасибо за помощь здесь. Для всех, кто посещает эту тему, мой первоначальный план состоял в использовании selenium, но использовать
requests
было намного проще для моих целей. Надеюсь, это поможет.