CoderCastrov logo
CoderCastrov
Питон

Парсинг amazon с помощью Python

Парсинг amazon с помощью Python
просмотров
12 мин чтение
#Питон

Мониторинг цен стал важным аспектом в сфере электронной коммерции. Мониторинг цен может помочь вам сэкономить затраты и увеличить прибыльность. Когда у вас есть доступ к информации о ценах, установленных вашими конкурентами, вы можете получить конкурентное преимущество на рынке.

Когда у вас есть доступ к этим данным, вы можете определить оптимальную цену для увеличения продаж. Эта техника также эффективна, если вы занимаетесь туристическим бизнесом. Вы можете снизить цены, чтобы получить больше преимущества. В таких типах бизнеса стратегия ценообразования очень важна.

В этой статье мы собираемся парсить amazon с помощью Python, чтобы отслеживать изменения цен на определенный товар.

Настройка предварительных требований

Я предполагаю, что вы уже установили python 3.x на своем компьютере. Если нет, то вы можете загрузить его отсюда here. Кроме того, нам понадобятся две сторонние библиотеки Python.

  • Requests- С помощью этой библиотеки мы будем устанавливать HTTP-соединение с веб-страницей Amazon. Эта библиотека поможет нам извлечь необработанный HTML-код из целевой страницы.
  • BeautifulSoup- Это мощная библиотека для обработки данных. С помощью нее мы будем извлекать необходимые данные из необработанного HTML-кода, полученного с помощью библиотеки requests.

Прежде чем установить эти библиотеки, нам нужно создать отдельную папку для нашего проекта.

mkdir amazonscraper

Теперь мы должны установить эти две библиотеки в эту папку. Вот как это сделать.

pip install beautifulsoup4
pip install requests

Теперь вы можете создать файл на языке Python с любым именем, которое вам нравится. Это будет основной файл, где мы разместим наш код. Я называю его amazon.py.

Загрузка исходных данных с amazon.com

Давайте выполним обычный GET-запрос к нашей целевой странице и посмотрим, что произойдет. Для GET-запроса мы будем использовать библиотеку requests.

import requests
from bs4 import BeautifulSoup

target_url="https://www.amazon.com/dp/B0BSHF7WHW"

resp = requests.get(target_url)

print(resp.text)

После выполнения этого кода вы можете увидеть следующее.

Это капча от amazon.com, и это происходит, когда их архитектура обнаруживает, что входящий запрос поступает от бота/скрипта, а не от реального человека.

Чтобы обойти эту защиту на сайте amazon, мы можем отправить некоторые заголовки, такие как User-Agent. Вы даже можете проверить, какие заголовки отправляются на amazon.com, открыв URL в вашем браузере. Вы можете проверить их на вкладке network.

После того, как вы передадите этот заголовок в запрос, ваш запрос будет выглядеть как запрос, поступающий из реального браузера. Это может обойти защиту от ботов на amazon.com. Давайте передадим несколько заголовков в наш запрос.

import requests
from bs4 import BeautifulSoup

target_url="https://www.amazon.com/dp/B0BSHF7WHW"

headers={"accept-language": "en-US,en;q=0.9","accept-encoding": "gzip, deflate, br","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36","accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"}

resp = requests.get(target_url, headers=headers)

print(resp.text)

После выполнения этого кода вы, возможно, сможете обойти защиту от скрапинга на amazon.

Теперь давайте определим, какую именно информацию мы хотим извлечь со страницы.

Что мы собираемся парсить?

Всегда полезно заранее решить, что вы собираетесь извлекать со страницы-цели. Таким образом, мы можем заранее проанализировать, где находится каждый элемент внутри DOM.

Мы собираемся извлечь пять элементов данных со страницы.

  • Название продукта
  • Изображения
  • Цена (самое важное😜)
  • Рейтинг
  • Спецификации

Сначала мы сделаем GET-запрос на целевую страницу, используя библиотеку requests, а затем, используя BS4, мы будем разбирать эти данные. Конечно, есть и другие библиотеки, такие как lxml, которые можно использовать вместо BS4, но BS4 имеет самый мощный и простой в использовании API.

Перед отправкой запроса мы собираемся проанализировать страницу и найти расположение каждого элемента внутри DOM. Всегда стоит выполнить это упражнение, чтобы определить местоположение каждого элемента.

Мы собираемся сделать это, просто используя инструмент разработчика. К нему можно получить доступ, просто щелкнув правой кнопкой мыши на целевом элементе, а затем щелкнув на **inspect**. Это самый распространенный метод, вы возможно уже знаете это.

Определение местоположения каждого элемента

Местоположение тега заголовка.

После проверки title вы увидите, что текст заголовка находится внутри тега **h1** с **id title**.

Вернемся к нашему файлу **amazon.py** и напишем код для извлечения этой информации с Amazon.

import requests
from bs4 import BeautifulSoup

l=[]
o={}


url="https://www.amazon.com/dp/B0BSHF7WHW"

headers={"accept-language": "en-US,en;q=0.9","accept-encoding": "gzip, deflate, br","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36","accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"}

resp = requests.get(url, headers=headers)
print(resp.status_code)

soup=BeautifulSoup(resp.text,'html.parser')


try:
    o["title"]=soup.find('h1',{'id':'title'}).text.strip()
except:
    o["title"]=None





print(o)

Здесь строка soup=BeautifulSoup(resp.text,’html.parser’) использует библиотеку BeautifulSoup для создания объекта BeautifulSoup из текста HTTP-ответа с указанным парсером HTML.

Затем, используя метод **soup.find()**, мы получаем первое вхождение тега **h1** с **id title**. Мы используем метод **.text** для получения текста из этого элемента. Затем, наконец, я использую метод **.strip()**, чтобы удалить все пробелы из полученного текста.

После запуска этого кода вы получите следующий результат.

[{'title': 'Apple 2023 MacBook Pro Laptop M2 Pro chip with 12‑core CPU and 19‑core GPU: 16.2-inch Liquid Retina XDR Display, 16GB Unified Memory, 1TB SSD Storage. Works with iPhone/iPad; Space Gray'}]

Если вы не прочитали предыдущий раздел, где мы говорили о загрузке HTML-данных с целевой страницы, то вы не сможете понять приведенный выше код. Поэтому, пожалуйста, прочитайте предыдущий раздел, прежде чем продолжить дальше.

Расположение тега изображения.

Это может быть самая сложная часть этого полного руководства. Давайте проанализируем и выясним, почему это немного сложно.

Как вы можете видеть, тег **img**, в котором скрыто изображение, хранится внутри тега **div** с классом **imgTagWrapper**.

allimages = soup.find_all("div",{"class":"imgTagWrapper"})
print(len(allimages))

При печати этого кода будет возвращено значение 3. Теперь здесь есть 6 изображений, и мы получаем только 3. Причина в том, что происходит рендеринг JS. Amazon загружает изображения через запрос AJAX на сервере. Поэтому мы никогда не получаем эти изображения, когда делаем HTTP-запрос к странице с помощью библиотеки **requests**.

Нахождение изображений с высоким разрешением не так просто, как нахождение тега заголовка. Но я пошагово объясню вам, как вы можете найти все изображения продукта🔥.

Вы обнаружите, что все изображения хранятся в качестве значения ключа **hiRes**.

Вся эта информация хранится внутри тега script. Теперь мы будем использовать регулярные выражения, чтобы найти этот шаблон **"hiRes":"image_url"**

Мы все равно можем использовать BS4, но это сделает процесс немного длиннее и может замедлить наш парсер. Пока что мы будем использовать **(.+?)** нежадные совпадения для одного или более символов. Позвольте мне объяснить, что означает каждый символ в этом выражении.

  • . соответствует любому символу, кроме новой строки
  • + соответствует одному или более вхождениям предыдущего символа.
  • ? делает совпадение нежадным, что означает, что оно будет соответствовать минимальному количеству символов, необходимых для удовлетворения шаблона.

По сути, регулярное выражение вернет все совпадающие последовательности символов из переданной HTML-строки.

images = re.findall('"hiRes":"(.+?)"', resp.text)
o["images"]=images

Это вернет все изображения с высоким разрешением продукта в виде списка. В общем, не рекомендуется использовать регулярные выражения при разборе данных, но иногда они могут сделать чудеса.

Парсинг ценника

На странице есть два ценника, но мы будем извлекать только тот, который находится прямо под рейтингом.

Мы видим, что ценник хранится внутри тега span с классом a-price. Как только вы найдете этот тег, вы можете найти первый дочерний тег span, чтобы получить цену. Вот как это можно сделать.

try:
    o["price"]=soup.find("span",{"class":"a-price"}).find("span").text
except:
    o["price"]=None

После печати объекта o вы увидите цену.

{'price': '$2,499.00'}

Извлечение рейтинга

Рейтинг можно найти в первом теге i с классом a-icon-star. Давайте посмотрим, как его извлечь.

try:
    o["rating"]=soup.find("i",{"class":"a-icon-star"}).text
except:
    o["rating"]=None

Это вернет следующее:

{'rating': '4.1 из 5 звезд'}

Аналогичным образом мы можем извлечь спецификации устройства.

Извлечение спецификаций устройства

Эти спецификации хранятся внутри тегов tr с классом a-spacing-small. Как только вы найдете их, вам нужно найти оба тега span внутри них, чтобы получить текст. Вы можете увидеть это на изображении выше. Вот как это можно сделать:

specs_arr=[]
specs_obj={}

specs = soup.find_all("tr",{"class":"a-spacing-small"})

for u in range(0,len(specs)):
    spanTags = specs[u].find_all("span")
    specs_obj[spanTags[0].text]=spanTags[1].text


specs_arr.append(specs_obj)
o["specs"]=specs_arr

С помощью find_all() мы находим все теги tr с классом a-spacing-small. Затем мы запускаем цикл for, чтобы перебрать все теги tr. Затем внутри цикла мы находим все теги span. И, наконец, мы извлекаем текст из каждого тега span.

После печати объекта o он будет выглядеть так:

На протяжении учебника мы использовали операторы try/except для избежания ошибок времени выполнения. Мы не смогли извлечь все данные, которые решили извлечь в начале учебника.

Полный код

Вы, конечно, можете внести несколько изменений в код, чтобы извлечь больше данных, поскольку страница заполнена большим количеством информации. Вы даже можете использовать cron-задания, чтобы отправлять себе оповещение, когда цена падает. Или вы можете интегрировать эту технику в свое приложение, эта функция может отправлять вашим пользователям электронную почту, когда цена любого товара на Amazon снижается.

Но пока код будет выглядеть так.

import requests
from bs4 import BeautifulSoup
import re

l=[]
o={}
specs_arr=[]
specs_obj={}

target_url="https://www.amazon.com/dp/B0BSHF7WHW"

headers={"accept-language": "en-US,en;q=0.9","accept-encoding": "gzip, deflate, br","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36","accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"}

resp = requests.get(target_url, headers=headers)
print(resp.status_code)
if(resp.status_code != 200):
    print(resp)
soup=BeautifulSoup(resp.text,'html.parser')


try:
    o["title"]=soup.find('h1',{'id':'title'}).text.lstrip().rstrip()
except:
    o["title"]=None


images = re.findall('"hiRes":"(.+?)"', resp.text)
o["images"]=images

try:
    o["price"]=soup.find("span",{"class":"a-price"}).find("span").text
except:
    o["price"]=None

try:
    o["rating"]=soup.find("i",{"class":"a-icon-star"}).text
except:
    o["rating"]=None


specs = soup.find_all("tr",{"class":"a-spacing-small"})

for u in range(0,len(specs)):
    spanTags = specs[u].find_all("span")
    specs_obj[spanTags[0].text]=spanTags[1].text


specs_arr.append(specs_obj)
o["specs"]=specs_arr
l.append(o)


print(l)

Изменение заголовков на каждый запрос

С помощью приведенного выше кода ваш путь парсинга остановится, как только Amazon распознает шаблон запроса. Чтобы избежать этого, вы можете продолжать изменять заголовки, чтобы парсер продолжал работать. Вы можете перебирать несколько заголовков, чтобы преодолеть эту проблему. Вот как это можно сделать.

import requests
from bs4 import BeautifulSoup
import re
import random

l=[]
o={}
specs_arr=[]
specs_obj={}

useragents=['Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4894.117 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4855.118 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4892.86 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4854.191 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4859.153 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.79 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36/null',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36,gzip(gfe)',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4895.86 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 12_3_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_13) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4860.89 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4885.173 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4864.0 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_12) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4877.207 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 12_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML%2C like Gecko) Chrome/100.0.4896.127 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.133 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_16_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.75 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4872.118 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 12_3_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_13) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4876.128 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML%2C like Gecko) Chrome/100.0.4896.127 Safari/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36']

target_url="https://www.amazon.com/dp/B0BSHF7WHW"

headers={"User-Agent":useragents[random.randint(0,31)],"accept-language": "en-US,en;q=0.9","accept-encoding": "gzip, deflate, br","accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"}

resp = requests.get(target_url,headers=headers)
print(resp.status_code)
if(resp.status_code != 200):
    print(resp)
soup=BeautifulSoup(resp.text,'html.parser')


try:
    o["title"]=soup.find('h1',{'id':'title'}).text.lstrip().rstrip()
except:
    o["title"]=None


images = re.findall('"hiRes":"(.+?)"', resp.text)
o["images"]=images

try:
    o["price"]=soup.find("span",{"class":"a-price"}).find("span").text
except:
    o["price"]=None

try:
    o["rating"]=soup.find("i",{"class":"a-icon-star"}).text
except:
    o["rating"]=None


specs = soup.find_all("tr",{"class":"a-spacing-small"})

for u in range(0,len(specs)):
    spanTags = specs[u].find_all("span")
    specs_obj[spanTags[0].text]=spanTags[1].text


specs_arr.append(specs_obj)
o["specs"]=specs_arr
l.append(o)


print(l)

Использование Scrapingdog для парсинга Amazon

Преимущества использования Scrapingdog:

  • Вам больше не нужно управлять заголовками.
  • Каждый запрос будет проходить через новый IP. Это сохраняет ваш IP-адрес анонимным.
  • Наш API автоматически повторит запрос, если первый не удался.
  • Scrapingdog использует резидентные прокси для парсинга Amazon. Это увеличивает успешность парсинга Amazon или любого другого подобного веб-сайта.

Вам нужно зарегистрироваться для бесплатной учетной записи, чтобы начать использовать его. Вам потребуется всего 10 секунд, чтобы начать работу с Scrapingdog.

После регистрации вы будете перенаправлены на свою панель управления. Панель управления будет выглядеть примерно так.

Вам нужно использовать свой собственный API-ключ.

Теперь вы можете вставить ссылку на целевую страницу слева, а затем выбрать JS Rendering как No. Затем нажмите Copy Code справа. Теперь используйте этот API в своем скрипте для парсинга Amazon.

import requests
from bs4 import BeautifulSoup
import re


l=[]
o={}
specs_arr=[]
specs_obj={}



target_url="https://api.scrapingdog.com/scrape?api_key=xxxxxxxxxxxxxxxxxxxx&url=https://www.amazon.com/dp/B0BSHF7WHW&dynamic=false"



resp = requests.get(target_url)
print(resp.status_code)
if(resp.status_code != 200):
    print(resp)
soup=BeautifulSoup(resp.text,'html.parser')


try:
    o["title"]=soup.find('h1',{'id':'title'}).text.lstrip().rstrip()
except:
    o["title"]=None


images = re.findall('"hiRes":"(.+?)"', resp.text)
o["images"]=images

try:
    o["price"]=soup.find("span",{"class":"a-price"}).find("span").text
except:
    o["price"]=None

try:
    o["rating"]=soup.find("i",{"class":"a-icon-star"}).text
except:
    o["rating"]=None


specs = soup.find_all("tr",{"class":"a-spacing-small"})

for u in range(0,len(specs)):
    spanTags = specs[u].find_all("span")
    specs_obj[spanTags[0].text]=spanTags[1].text


specs_arr.append(specs_obj)
o["specs"]=specs_arr
l.append(o)


print(l)

Вы заметите, что код останется примерно таким же, как и выше. Мы просто должны изменить одну вещь, и это наша целевая ссылка. Я даже больше не передаю заголовки. Не так ли удобно для парсинга?

С помощью этого скрипта вы сможете парсить Amazon с молниеносной скоростью, при этом не получая блокировки.

Заключение

В этом руководстве мы извлекли различные элементы данных с Amazon. Сначала мы использовали библиотеку requests для загрузки исходного HTML-кода, а затем, используя BS4, мы разобрали нужные нам данные. Вы также можете использовать lxml вместо BS4 для извлечения данных. Python и его библиотеки делают парсинг очень простым даже для начинающих. Когда вы масштабируете свой парсер, вы можете перейти к использованию веб-скрапинг API для парсинга миллионов подобных страниц.

Комбинация requests и Scrapingdog может помочь вам масштабировать свой парсер🔥. Вы получите более 99% успешных результатов при парсинге Amazon с помощью Scrapingdog.

Надеюсь, вам понравилось это небольшое руководство, и если да, то, пожалуйста, не забудьте поделиться им с друзьями и в социальных сетях❤️.

Дополнительные ресурсы

Вот несколько дополнительных ресурсов, которые могут быть полезными во время вашего путешествия по парсингу веб-страниц: