#python-3.x #web-scraping #beautifulsoup #web-crawler #amazon
#python-3.x #очистка веб-страниц #beautifulsoup #веб-сканер #amazon
Вопрос:
Я пытаюсь сканировать данные обзора с Amazon с помощью Jupeter notebook.
Но есть ответ 503 от сервера.
Кто-нибудь знает, что с этим не так?
Вот мой код.
import re, requests, csv
from bs4 import BeautifulSoup
from time import sleep
def reviews_info(div):
review_text = div.find("div", "a-row a-spacing-small review-data").get_text()
review_author = div.find("span", "a-profile-name").get_text()
review_stars = div.find("span", "a-icon-alt").get_text()
on_review_date = div.find('span', 'a-size-base a-color-secondary review-date').get_text()
review_date = [x.strip() for x in re.sub("on ", "", on_review_date).split(",")]
return { "review_text" : review_text,
"review_author" : review_author,
"review_stars" : review_stars,
"review_date": review_date }
base_url = 'https://www.amazon.com/Apple-MWP22AM-A-AirPods-Pro/product-reviews/B07ZPC9QD4/ref=cm_cr_arp_d_paging_btm_next_2?ie=UTF8amp;reviewerType=all_reviewsamp;pageNumber='
reviews = []
NUM_PAGES = 8
for page_num in range(1, NUM_PAGES 1):
print("souping page", page_num, ",", len(reviews), "data collected")
url = base_url str(page_num)
soup = BeautifulSoup(requests.get(url).text, 'lxml')
for div in soup('div', 'a-section review'):
reviews.append(reviews_info(div))
sleep(30)
Наконец я попробовал
requests.get(url)
Вывод
<Response [503]>
И я также пытался
requests.get(url).text()
Вывод
TypeError: 'str' object is not callable
Amazon заблокировал сканирование?
Я был бы признателен за ваш ответ!
Ответ №1:
Amazon блокирует запрос к своим серверам при попытке его обхода с помощью библиотеки запросов python. Вы можете попробовать использовать Selenium с браузером chromium, который может помочь. Вот версия Selenium для Python: https://selenium-python.readthedocs.io /.
Ответ №2:
Я попробовал webdriver.
Вот мой код.
from selenium import webdriver
import re
import requests
import csv
from bs4 import BeautifulSoup
from time import sleep
review_list = []
NUM_PAGE = 8
base_url = 'https://www.amazon.com/Apple-MWP22AM-A-AirPods-Pro/product-reviews/B07ZPC9QD4/ref=cm_cr_arp_d_paging_btm_next_2?ie=UTF8amp;reviewerType=all_reviewsamp;pageNumber='
for num_page in range(1, NUM_PAGE 1):
chrome_driver = '/Users/chromedriver'
driver = webdriver.Chrome(chrome_driver)
url = base_url str(num_page)
driver.get(url)
src = driver.page_source
source = BeautifulSoup(src, 'lxml', from_encoding='utf-8')
driver.close()
print("souping page", num_page, ",", len(source.find_all('div', 'a-section celwidget')), "의 data를 수집")
for source in source.find_all('div', 'a-section celwidget'):
review_text = source.find("div", "a-row a-spacing-small review-data").get_text()
review_author = source.find("span", "a-profile-name").get_text()
review_stars = source.find("span", "a-icon-alt").get_text()
on_review_date = source.find('span', 'a-size-base a-color-secondary review-date').get_text()
#review_date = [x.strip() for x in re.sub("on ", "", on_review_date).split(",")]
review = { "review_text" : review_text,
"review_author" : review_author,
"review_stars" : review_stars,
"review_date": on_review_date }
review_list.append(review)
sleep(10)
Ответ №3:
Гораздо более быстрым решением, чем использование selenium / webdriver, но более дорогостоящим является использование прокси. Я использую proxycrawl — я вообще не связан с ними, кроме того, что являюсь клиентом. Я также рекомендую использовать фреймворк для очистки, такой как Scrapy. Это поможет избежать обнаружения, используя переменную синхронизацию между запросами среди других функций.
Вы платите за успешную очистку — с вас не взимается плата за неудачные очистки. Это самое дешевое прокси-решение, которое я нашел.
Вы используете его следующим образом:
import scrapy # scraping framework to parse data
from proxycrawl.proxycrawl_api import ProxyCrawlAPI
from datetime import datetime # used to convert review date string into datetime object. Useful if you plan to insert into an SQL db.
api = ProxyCrawlAPI({'token': 'NON-JS TOKEN'})
apijava = ProxyCrawlAPI({'token': 'JS TOKEN'})
def start_requests(self):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.193 Safari/537.36'
}
url = 'https://www.amazon.com/product-reviews/B07ZPC9QD4/ref=cm_cr_arp_d_paging_btm_next_2?ie=UTF8amp;reviewerType=all_reviews' # you don't need the product title in the url
# build proxcrawl url
pcurl = api.buildURL(url, {})
yield scrapy.Request(pcurl, callback=self.parse, errback=self.errback_httpbin, headers=headers, meta={'asin': 'B07ZC90D4'})
def parse(self, response):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.193 Safari/537.36'
}
reviews_count = response.xpath('//*[@id="cm_cr-review_list"]/div[@data-hook="review"]').getall()
asin = response.meta['asin']
asin_title = response.xpath('//*[@id="cm_cr-product_info"]/div/div[2]/div/div/div[2]/div[1]/h1/a/text()').get()
if reviews_count is not None: # review_count = number of reviews
for review_index in range(len(reviews_count)):
review_index = 1
review_title = response.xpath('//*[@id="cm_cr-review_list"]/div[@data-hook="review"]['
str(review_index) ']/div/div/div[2]/a[2]/span/text()').get()
review_rating_string = response.xpath('//*[@id="cm_cr-review_list"]/div[@data-hook="review"]['
str(review_index) ']/div/div/div[2]/a[1]/@title').get()
review_date_string = response.xpath('//*[@id="cm_cr-review_list"]/div[@data-hook="review"]['
str(
review_index) ']/div/div/span[@data-hook="review-date"]/text()').get()
review_body = response.xpath('//*[@id="cm_cr-review_list"]/div[@data-hook="review"]['
str(review_index) ']/div/div/div[4]/span/span/text()').get()
review_rating = str(review_rating_string).split(' ', 1)[0]
# get rid of the 00:00:00 time
review_date = str(datetime.strptime(review_date_string, '%B %d, %Y')).split(' ', 1)[0]
date_of_cur_review = datetime.strptime(review_date, '%Y-%m-%d')
# DO SOMETHING HERE. INSERT INTO A DB?
#####
# go to next page if there is one
if review_index == 10:
next_page = response.xpath('//*[@class="a-last"]/a/@href').get()
if next_page is not None:
headers = {'User-Agent': headers}
yield response.follow(api.buildURL('https://www.amazon.com' next_page, {}),
callback=self.parse, errback=self.errback_httpbin, headers=headers,
meta={'asin': response.meta['asin']})