Основы веб-скрейпинга: как извлечь данные с веб-сайта на языке Python

В науке о данных мы всегда говорим «мусор в мусоре». Если у вас нет качественных и количественных данных, скорее всего, вы не сможете извлечь из них много полезной информации. Веб-скрейпинг – один из важных методов автоматического получения сторонних данных.

Что такое веб-скрейпинг

Web Scraping — это автоматический способ получения неструктурированных данных с веб-сайта и хранение их в структурированном формате.

С каких веб-сайтов можно извлекать данные?

Скрейпинг увеличивает трафик сайта и может привести к сбою сервера. Поэтому не все сайты разрешают извлекать с них данные. Как узнать, какие сайты разрешены, а какие нет? Можно посмотреть на файл ‘robots.txt’ сайта. Для этого необходимо добавить robots.txt после URL сайта, с которого нужно извлечь данные, и откроется информация о том, разрешает ли хостер сайта извлекать с него данные.

Ниже показан пример с сайта Google.com

Google не разрешает веб-скрейпинг для многих подсайтов. Однако он разрешает определенные пути, такие как ‘/m/finance’, и поэтому, если поставлена задача собрать информацию о финансах, то сайт Google отлично для этого подойдет.

Как работает веб-скрейпинг?

Веб-скрейпинг работает как бот, который просматривает различные страницы сайта и копирует их содержимое. Когда запускается код, он отправляет запрос на сервер, который в ответ возвращает нужные данные. Затем уже аналитик извлекает необходимые сведения из полученного ответа.

Как настроить веб-скрейпинг?

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

Процесс получения данных:

  1. Открыть интересующий HTML-файл веб-сайта.
  2. Получить доступ к URL веб-сайта с помощью кода и загрузить все содержимое HTML на странице.
  3. Отформатировать загруженное содержимое в удобочитаемый формат.
  4. Извлечь полезную информацию и сохранить ее в структурированном формате.
  5. Для информации, отображаемой на нескольких страницах сайта, может потребоваться повторить шаги 2-4, чтобы получить полную информацию.

Подход 2: Если сайт хранит данные в API и запрашивает API каждый раз, когда пользователь посещает сайт, можно имитировать запрос и напрямую запрашивать данные из API.

Процесс извлечения:

  1. Посмотреть сетевой раздел XHR URL-адреса.
  2. Определить запрос-ответ, который предоставляет нужные данные.
  3. В зависимости от типа запроса (post или get), а также заголовка запроса и полезной нагрузки, необходимо смоделировать запрос в своем коде и получить данные из API. Обычно данные, полученные из API, имеют довольно аккуратный формат.
  4. Извлечь полезную информацию.
  5. Для API с ограничением на размер запроса, придется использовать «цикл for» для многократного получения всех данных.

Различные инструменты и библиотеки для веб-скрейпинга

Наиболее часто используемыми библиотеками для веб-скрейпинга на Python являются Beautiful Soup, Requests и Selenium.

Beautiful Soup помогает разбирать HTML или XML документы в удобочитаемый формат. Она позволяет искать различные элементы в документах и помогает быстрее получить необходимую информацию.

Requests: Это модуль Python, с помощью которого вы можете отправлять HTTP-запросы для получения содержимого сайта. Он помогает получить доступ к HTML-содержимому сайта или API, отправляя запросы Get или Post.

Selenium широко используется для тестирования веб-сайтов и позволяет автоматизировать различные события (нажатие, прокрутка и т.д.)

Аналитик может использовать либо Requests + Beautiful Soup, либо Selenium для веб-скрейпинга. Selenium предпочтителен, если нужно взаимодействовать с сайтом (события JavaScript), а если нет, то стоит отдать предпочтение Requests + Beautiful Soup, потому что этот подход быстрее и проще.

Пример:

Задача: Узнать о местном рынке масок для лица. Интересуют онлайн цены на маски для лица, скидки, рейтинги, продаваемое количество и т.д.

Пример подхода 1 (скачать HTML для всех страниц) на базе сайта Lazada

Шаг 1: Начать необходимо с проверки веб-сайта (если используется Chrome, нужно щелкнуть правой кнопкой мыши и выбрать пункт «Проверить»).

Проверка сайта Lazada в Chrome

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

Шаг 2: Получить доступ к URL-адресу сайта с помощью кода и загрузить все HTML содержимое, доступное на странице

# import library
from bs4 import BeautifulSoup
import requests

# Request to website and download HTML contents
url=’https://www.lazada.sg/catalog/?_keyori=ss&from=input&q=mask’
req=requests.get(url)
content=req.text

В результате будет получен неструктурированный текст.

Шаг 3: Форматирование загруженного содержимого в удобный для чтения формат

soup=BeautifulSoup(content)

Этот шаг очень прост, нужно разобрать текст на Beautiful Soup. Результат будет выглядеть так:

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

Шаг 4: Извлечение полезной информации и сохранение ее в структурированном формате

В случае с Lazada они хранятся в разделе Script в формате JSON.

raw=soup.findAll(‘script’)[3].text
page=pd.read_json(raw.split(«window.pageData=»)[1],orient=’records’)
#Store data
for item in page.loc[‘listItems’,’mods’]:
brand_name.append(item[‘brandName’])
price.append(item[‘price’])
location.append(item[‘location’])
description.append(ifnull(item[‘description’],0))
rating_score.append(ifnull(item[‘ratingScore’],0))

В примере ниже 5 различных списков для хранения различных полей данных:

#save data into an output
output=pd.DataFrame({‘brandName’:brand_name,’price’:price,’location’:location,’description’:description,’rating score’:rating_score})

Шаг 5: Для информации, отображаемой на нескольких страницах сайта, может потребоваться повторить шаги 2-4.

Сначала необходимо узнать общее количество продавцов. Затем следует перебрать страницы, передавая номера страниц по возрастанию, используя полезную нагрузку URL.

for i in range(1,50):
time.sleep(max(random.gauss(5,1),2))
print(‘page’+str(i))
payload[‘page’]=i
req=requests.get(url,params=payload)
content=req.text
soup=BeautifulSoup(content)
raw=soup.findAll(‘script’)[3].text
page=pd.read_json(raw.split(«window.pageData=»)[1],orient=’records’)
for item in page.loc[‘listItems’,’mods’]:
brand_name.append(item[‘brandName’])
price.append(item[‘price’])
location.append(item[‘location’])
description.append(ifnull(item[‘description’],0))
rating_score.append(ifnull(item[‘ratingScore’],0))

Пример подхода 2 (Запрос данных непосредственно из API) на примере Ezbuy

Шаг 1: Извлечь сетевую секцию XHR URL-адреса, который нужно просмотреть, и найти запрос-ответ, который дает нужные данные

Вся информация о продукте перечислена в этом API под названием «List Product by Condition».

Шаг 2: В зависимости от типа запроса (post или get), а также заголовка запроса и полезной нагрузки, сздать запрос и получить данные из API. Обычно данные, полученные от API, имеют довольно аккуратный формат.

s=requests.session()#Define API url
url_search=’https://sg-en-web-api.ezbuy.sg/api/EzCategory/ListProductsByCondition’#Define header for the post request
headers={‘user-agent’:’Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36′}#Define payload for the request form
data={
«searchCondition»:
{«categoryId»:0,»freeShippingType»:0,»filter: [],»keyWords»:»mask»},
«limit»:100,
«offset»:0,
«language»:»en»,
«dataType»:»new»
}req=s.post(url_search,headers=headers,json=data)

Шаг 3: извлечение полезной информации

#read the data back as json file
j=req.json()# Store data into the fields
for item in j[‘products’]:
price.append(item[‘price’])
location.append(item[‘originCode’])
name.append(item[‘name’])
ratingScore.append(item[‘leftView’][‘rateScore’])
quantity.append(item[‘rightView’][‘text’].split(‘ Sold’)[0]#Combine all the columns together
output=pd.DataFrame({‘Name’:name,’price’:price,’location’:location,’Rating Score’:ratingScore,’Quantity Sold’:quantity})

Данные из API обычно довольно аккуратные и структурированные, как показано в примере ниже:

Шаг 4: Для API с ограничением на размер запроса необходимо использовать «цикл for» для многократного получения всех данных.

#Define API url
url_search=’https://sg-en-web-api.ezbuy.sg/api/EzCategory/ListProductsByCondition’#Define header for the post request
headers={‘user-agent’:’Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36′}for i in range(0,14000,100):
time.sleep(max(random.gauss(3,1),2))
print(i)
data={
«searchCondition»:
{«categoryId»:0,»freeShippingType»:0,»filters»:
[],»keyWords»:»mask»},
«limit»:100,
«offset»:i,
«language»:»en»,
«dataType»:»new»
}
req=s.post(url_search,headers=headers,json=data)
j=req.json()
for item in j[‘products’]:
price.append(item[‘price’])
location.append(item[‘originCode’])
name.append(item[‘name’])
ratingScore.append(item[‘leftView’][‘rateScore’])
quantity.append(item[‘rightView’][‘text’].split(‘ Sold’)[0])#Combine all the columns together
output=pd.DataFrame({‘Name’:name,’price’:price,’location’:location,’Rating Score’:ratingScore,’Quantity Sold’:quantity})

Совет

Если вы хотите использовать веб-скрейпинг, нужно сначала проверить наличие API в разделе сети с помощью inspect. Также можно использовать запросы или Selenium для загрузки HTML-контента и Beautiful Soup для форматирования данных. Наконец, нужно использовать таймаут, чтобы избежать слишком частых посещений сайта или API. Это поможет уменьшить трафик на благо сайта.

Стоимость услуг

Наименование услугиСтоимость работВремя выполнения
Сбор данных (парсинг)от 20.000 Рот 5 дней

Записаться на консультацию

Остались вопросы? Разберем бесплатно простую задачу или проведем консультацию

Посмотреть пример

Поделится:

Добавить комментарий

Ваш адрес email не будет опубликован.

Вам также может быть интересно: