Или как собрать данные с любого веб-сайта с помощью Python

Для образовательного проекта по компьютерному зрению, использующего Deep Learning, над которым я работал, мне нужно было найти много изображений одежды. Когда я говорю «лоты», я имею в виду не менее 300 тысяч. Буквально.

На самом деле у меня были две основные проблемы при создании хорошего и расширенного набора данных для моего проекта:

  • Мне нужны были конкретные данные для конкретного случая использования
  • Такие данные в структурированной форме не существовали ни на одной платформе, такой как Kaggle или около того.

«Данные о тканях? Используйте ImageNet, набор данных Fashion MNIST или даже DeepFashion2! » вы могли подумать. Нет, я не мог использовать наборы данных ImageNet или Fashion MNIST, поскольку идея алгоритма заключалась в том, чтобы распознавать ткань с любого положения и ориентации света, будь то полностью осыпавшаяся на кровати или поношенная на модели. И в этих типах наборов данных хорошо позиционируются ткани и т. Д.

Более того, как и для любого проекта глубокого обучения, объем необходимых данных был просто огромным. Фазы сбора данных в Data Science или, точнее, в проекте машинного обучения невозможно избежать, и сделать это правильно - это обязательное условие. Однако иногда бывает намного сложнее, чем вы думаете, найти данные, которые конкретно подходят вашим потребностям.

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

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

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

В те дни умение выполнять парсинг можно было считать суперспособностью:

  • может быть спасением для специалистов по данным / инженеров по машинному обучению, которым нужны данные
  • Предпринимателям и стартапам он может понадобиться, чтобы лучше узнать своих конкурентов, провести бизнес-анализ или даже получить все отзывы своих социальных сетей, собранные в файле Excel.

А поскольку это теперь законно, почему бы и нет?

В этой статье я постараюсь дать вам представление о его силе на примерах H&M и Vinted, а также о том, как попробовать его дома.

TL; DR Для быстрого примера простого парсера на Python вы можете найти полный код, описанный в этом руководстве, на Github

Что тебе нужно ?

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

  • Scrapy
  • Beautifulsoup
  • Селен
  • Запросы

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

Почему Scrapy? Потому что его использование идеально адаптировано к тому, что мы хотим делать:

  • Scrapy: позволяет делать определенные запросы по URL-адресу, исследуя HTML / JSON / XML-код файла. Scrapy - это мощный и быстрый инструмент, так как он может запускать несколько потоков параллельно, что значительно ускоряет сканирование.
  • Beautifulsoup: один из самых популярных, он делает то же самое, что и Scrapy, но итеративно, а не параллельно.
  • Selenium: полезен для взаимодействия с целевым веб-сайтом, запуска CTA, нажатия на кнопки и т. Д. (Например, см. Проект Facebook Autotagger здесь, на Github).
  • Запросы: используются реже, чем предыдущие библиотеки

Давайте установим Scrapy с помощью диспетчера пакетов Python в каталоге вашего проекта:

pip install scrapy

После установки у вас должны быть аналогичный каталог и файлы:

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

Изучите цель

«Тот, кто знает другого и знает себя, может провести сотню битв, не подвергаясь опасности. Тот, кто не знает другого, но знает себя, для каждой победы будет знать поражение. Тот, кто не знает ни другого, ни самого себя, неизбежно проиграет каждую битву. »Сунь Цзы

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

Отсюда необходимость тщательного изучения скелета и мускулов (т. Е. Структуры и поведения) сети, с которой вы собираетесь соскабливать.

Чтобы изучить веб-сайт, вы можете щелкнуть правой кнопкой мыши в любом месте страницы и выбрать «Исследовать элемент», чтобы увидеть, что находится под капотом (совет: Ctrl + Shift + J - это ярлык):

Щелкните правой кнопкой мыши в любом месте и выберите «Проверить элемент», чтобы проверить код.

Настал момент взглянуть на способ получения новых данных на веб-сайте и задать себе этот важный вопрос:

ЕСТЬ ЯВНЫЙ ВЫЗОВ API , КОТОРЫЙ ВОССТАНАВЛИВАЕТ НОВЫЕ ДАННЫЕ?

Если на веб-сайте есть кнопки «Назад» и «Далее» или если URL-адреса разных страниц, которые вы посещаете, различаются (например, «/ page / 2» и «/ page / 3 »), перейдите в раздел Очистка HTML.

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

Очистка HTML

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

Но некоторые веб-сайты по-прежнему используют CTA для перехода на следующую страницу (например, кнопки «Назад» и «Далее») и отображения следующих элементов без явного обращения к стороннему API. В таких случаях старый добрый HTML-парсинг веб-страниц полезен, прост и эффективен.

1. Изучите элементы HTML, которые вы ищете.

Чтобы изучить веб-сайт, вы можете щелкнуть правой кнопкой мыши в любом месте страницы и выбрать «Исследовать элемент», чтобы увидеть, что находится под капотом (совет: Ctrl + Shift + J - это ярлык)

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

Щелкните правой кнопкой мыши в любом месте, чтобы открыть Инструменты разработчика.

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

  • Интересующий элемент: class="product-item", похоже, представляет предмет из ткани и, кажется, содержит всю информацию, на которой мы хотим сосредоточиться, поэтому это будет HTML-элемент, на который мы будем ориентироваться.

Затем мы можем продолжить и настроить таргетинг на элементы HTML, которые мы хотим удалить для каждого элемента (т.е. здесь каждый элемент <li class="product-item">):

  • Тип ткани: чтобы непосредственно пометить изображения в готовом к использованию наборе данных, нам нужен тип ткани для каждого изображения, которое мы отбрасываем. После расследования мы понимаем, что сможем использовать class="link" и извлечь text часть

  • Цена: class="price regular" - это класс позиции с ценой.
  • Picture1: srcof class="item-image" содержит href с изображением надетой модели в формате URL.
  • Picture1_Colour: благодаря первому class="swatch" элементу HTML в class="list-swatches" у нас есть цвет ткани на 1-м изображении. Эту информацию можно будет использовать позже, например, если мы хотим научить нашу нейронную сеть распознавать цвет ткани.
  • Picture2: data-altimageof class="item-image"содержит href с изображением неношеной ткани в формате URL.

2. Разберитесь в нумерации страниц.

Чтобы постоянно получать данные с веб-сайта, нам нужно понимать, как получить доступ к новым элементам и перебрать их.

В случае H&M, призыв к действию (CTA) заставляет веб-страницу запрашивать новые данные путем изменения URL-адреса (https: / /www2.hm.com/en_gb/men/new-arrivals/view-all.html?sort=stock&image-size=small&image=model&**offset=0&page-size=72** ).

После анализа мы понимаем, что каждый новый запрос приносит 38 новых элементов, и учитывая общее количество элементов для категории мужчины (1623) в « Просмотреть все Раздел, мы введем этот номер в наш start_url, чтобы запросить страницу со всей мужской одеждой и выбросить ее:

start_url = ['<https://www2.hm.com/en_gb/men/shop-by-product/view-all.html?sort=stock&image-size=small&image=model&offset=0&page-size=1623>']

3. Определите схему своих данных.

Чтобы упростить очистку и иметь возможность более легко обрабатывать полученные данные, соглашение состоит в том, чтобы определить «схему», простой шаблон, в который Scrapy сможет помещать данные при каждом извлечении элементов.

В items.py мы определяем нашу ClothItem схему:

Примечание: здесь наша схема находится в структуре данных dict, но у Scrapy есть и другие возможные формы в магазине. Нажмите здесь, чтобы узнать больше о предметах Scrapy.

3. Создайте и адаптируйте своего HTML-паука.

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

В каталоге «пауков» (YOUR_PROJECT_DIR / webscrapping / spiders) создайте новый файл, который будет содержать вашего паука. Назовем это scraper.py здесь.

В scraper.py импортируйте библиотеки, которые потребуются нашему пауку для запуска. Затем мы создадим экземпляр паука, создав класс, присвоив ему name и start_url (то есть URL-адрес, с которого следует начать очистку):

После этого идет большая часть, функция parse:

Некоторые пояснения здесь:

  • SELECTORS: мы определяем селекторы для нацеливания на определенные элементы HTML, которые мы перечислили ранее, и чтобы указать, где информация, которую мы хотим получить, находится внутри элемента (это *** * text, @attribute и т. Д.)

Примечание: некоторые из них - xpath селекторы, другие - css, чтобы показать разницу в синтаксисе между ними. Обратите внимание, что с xpath немного сложнее, но как только вы его поймете, вы заметите, что он намного точнее, чем cssselectors (см. Селекторы CSS и Синтаксис Xpath для получения дополнительной информации).

  • SET_SELECTOR: мы настраиваем здесь упомянутый ранее интересующий элемент, чтобы перебирать каждый аналогичный элемент в for цикле (т.е. извлекать данные из каждого элемента с таким именем)
  • item = ClothItem(): проблеск силы Scrapy. Благодаря схеме, которую мы определили ранее, мы можем просто импортировать ее и yield ее в желаемом формате в конце каждой итерации.

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

4. Выберите формат структурированных данных.

В Scrapy есть эта замечательная функция, которая позволяет вам выбирать практически любой выходной формат для ваших данных в «файле экспорта» (обычно называемом «поток экспорта»).

Чтобы сериализовать очищенные данные, Scrapy сделал его удобным для распространенных форматов:

  • JSON
  • CSV
  • XML

Чтобы выбрать один из них, просто используйте флаг -o в вашем скрипте при вызове scrapy в вашем терминале (для более подробной настройки параметров вы можете погрузиться в feed exports систему через документацию scrapy).

ВАЖНО: Scrapy настолько мощен, что вы даже можете напрямую подключить своего паука к размещенной на нем базе данных SQL. Чтобы узнать, Как подключить ваш Web Scraper к базе данных PostgreSQL, нажмите здесь.

5. В лом (безопасно)!

Вот и мы: мы тщательно проанализировали целевой веб-сайт, поняли его разбивку на страницы, адаптировали структуру нашего фида экспорта следовательно, и инициировал все это в нашем пауке. Теперь мы готовы запустить записку **. **

Чтобы узнать, как запустить финальную команду и начать парсинг, см. Ниже.

Очистка API

Мы видели весь процесс очистки HTML-элементов внутри веб-страницы. Но, как упоминалось ранее, этот метод применим только в том случае, если вы не можете найти ни одного вызова API в «дикой природе». Чтобы быть исчерпывающим в отношении методов очистки веб-страниц, я хотел охватить тему очистки API (именно API-интерфейсы JSON. Действительно, API-интерфейсы очистки могут быть довольно быстрыми и менее сложными для использования, поэтому давайте начнем с Винтированный API.

1. Ищем вызов API

Нажав на вкладку Сеть в консоли инструментов разработчика (здесь цена, тип ткани, размер, бренд, изображение), мы должны определить момент, когда интерфейсное веб-приложение вызывает обратный вызов. -end API для получения следующей партии элементов.

Получив URL-адрес API, мы должны понять его механизм.

2. Изучите элементы JSON, которые вы ищете.

Как только вы получите доступ к API и после некоторого тестирования, чтобы попытаться найти нужные каталоги, сначала мы исследуем структуру формата JSON:

<https://www.vinted.fr/api/v2/items?catalog_ids=5&page=2&per_page=100&time=1617455110&search_session_id=d92b0753-cdbf-4a10-976e-11ae1c91671c>
  • Тип ткани: чтобы непосредственно пометить изображения в готовом к использованию наборе данных, нам нужен тип ткани для каждого изображения, которое мы отбрасываем. После расследования мы понимаем, что сможем использовать path и посмотреть на href-часть: href=/women/casual-dresses/....., например
  • Цена: атрибут price в формате JSON для каждого товара даст нам цену.
  • Размер: size тоже довольно явный.
  • Бренд: brand (сказал вам, что это было легко)
  • Цвет: здесь нам поможет color1
  • Изображение: photos/0/full_size_url содержит основное изображение с высоким разрешением.

3. Понимание «пакетного» механизма

Очень часто API блокирует запросы, пытающиеся получить доступ ко всему набору данных. Обычно он принимает запросы в «пакетной» форме, например, последовательный вызов.

В случае с Vinted, после настройки вызова API и сравнения полученных данных мы легко понимаем, как это работает:

  • https://www.vinted.fr/api/v2/catalogs: этот URL-адрес извлекает с помощью метода GET список и id каждого доступного каталога, который будет полезен («мужчины»: 5; «женщины»: 1904; «дети»: 1193).
  • https://www.vinted.fr/api/v2/items?catalog_ids=5&page=2&per_page=96: этот вызов API позволяет нам получить максимум 96 элементов (число, найденное после некоторых тестов и настроек) и для повторения над страницами благодаря SQL-запросу page=

4. Создайте своего JSON-паука.

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

В том же файле scraper.py создайте нового паука:

Основное отличие от очистки HTML заключается в селекторах. Поскольку мы получаем файл JSON с json.loads(response.text), путь для доступа к каждому элементу должен быть записан в запросе JSON.

Здесь [i] будет перебирать номера элементов внутри каталога "items" JSON благодаря циклу for, а затем мы продолжаем следовать по пути JSON для извлечения данных, которые нам нужны, с тем же синтаксисом jsonresponse["items"][NUMBER_OF_CURRENT_ITEM]["PATH"]["TO"]["FOLLOW"]

Что касается пакетного механизма, мы просто просим Scrapy запрашивать следующую страницу, используя z в качестве current page number, и увеличивая его после каждого раунда.

5. Выберите формат структурированных данных.

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

ВАЖНО: Scrapy настолько мощен, что вы даже можете напрямую подключить своего паука к размещенной на нем базе данных SQL. Чтобы узнать, Как подключить ваш Web Scraper к базе данных PostgreSQL, нажмите здесь.

Последний приказ

Вы тщательно выполнили все шаги и подготовились к запуску парсинга. Пришло время вернуть свои данные.

Для этого у вас есть 2 основных варианта: удалить, используя имя паука, или удалить, используя имя файла. Первый метод представлен здесь для простоты. Вот команда терминала для ввода в каталог вашего проекта:

scrapy crawl hm_spider -o hm_men_cloths.json

Как мы видели ранее, «hm_spider» - это имя, которое мы дали нашему пауку, в то время как флаг -o, за которым следуют имя и расширение канала экспорта, определяет формат вывода.

ВАЖНОЕ примечание. Обычно веб-сайты не любят царапать. Даже если такая практика не заслуживает осуждения, некоторые попытаются заблокировать вас несколькими препятствиями, другие - любыми средствами. Фактически, некоторые попытаются пометить вас как «БОТ», если вы начнете сканировать сотни страниц. Идея состоит в том, чтобы не быть отмеченными как BOT при парсинге, а также действовать честно с ними. Вот несколько советов, как обойти некоторые проблемы, которые следует удалить, настроив settings.py файл:

  • Ответственное сканирование: укажите серверу, кто вы, и играйте честно, указав себя в пользовательском агенте.
USER_AGENT = 'webscrapping (+http://www.yourdomain.com)'
  • Вы можете следовать правилам, установленным файлом robots.txt, или нет, переключая его в настройках.
ROBOTSTXT_OBEY = True
  • Чтобы избежать блокировки вашего IP-адреса и не беспокоить серверы, вы можете настроить частоту параллельных запросов к серверу.
# Configure a delay for requests for the same website (default: 0)
# Seehttps://docs.scrapy.org/en/latest/topics/settings.html#download-delay
# See also autothrottle settings and docs
DOWNLOAD_DELAY = 5
# The download delay setting will honor only one of:
CONCURRENT_REQUESTS_PER_DOMAIN = 16
CONCURRENT_REQUESTS_PER_IP = 20

Заключение

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

Подводя итог тому, что мы узнали сегодня:

  • Что такое парсинг веб-страниц
  • Как его можно использовать для построения структуры для специалистов по данным, инженеров машинного обучения или даже предпринимателей и стартапов?
  • HTML метод
  • Метод JSON API
  • Как запустить лом

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