Автор оригинала: Gareth Dwyer.
Примечание: этот учебник является выдержкой из Код с Reply.it: Проекты на Python для начинающих , книга и набор учебных пособий для начинающих, чтобы получить практический опыт программирования на Python.
В этом руководстве мы рассмотрим, как автоматически захватывать данные с веб-сайтов. Большинство веб – сайтов создаются с учетом человеческой аудитории-вы используете поисковую систему или вводите URL-адрес в свой веб-браузер и видите информацию, отображаемую на странице. Иногда мы можем захотеть автоматически извлекать и обрабатывать эти данные, и именно здесь веб-скребок может спасти нас от скучного повторяющегося труда. Мы можем создать специальную компьютерную программу для посещения веб-сайтов, извлечения определенных данных и обработки этих данных определенным образом.
Мы будем извлекать новые данные из bbc.com новостной сайт, но вы должны быть в состоянии адаптировать его для извлечения информации с любого веб-сайта, который вы хотите, с небольшим количеством проб и ошибок.
Есть много причин, по которым вы можете использовать веб-скребок. Например, вам может понадобиться:
- извлеките цифры из отчета, который выходит еженедельно и публикуется в Интернете
- захватите расписание для вашей любимой спортивной команды, как только оно будет выпущено
- найдите даты выхода предстоящих фильмов в вашем любимом жанре
- получать автоматическое уведомление при изменении веб-сайта
Существует много других вариантов использования веб-скребка. Однако вы также должны отметить, что закон об авторском праве и законы о веб-скребке сложны и различаются в зависимости от страны. До тех пор, пока вы не будете откровенно копировать их контент или делать веб-скребок для коммерческой выгоды, люди, как правило, не возражают против веб-скейпинга. Однако было несколько судебных дел, связанных с соскабливанием данных из LinkedIn и вниманием СМИ из соскабливанием данных из OkCupid . Веб – скребок может нарушать закон, идти вразрез с условиями обслуживания конкретного веб-сайта или нарушать этические принципы-поэтому будьте осторожны с тем, где вы применяете этот навык.
С отказом от ответственности покончено, давайте научимся скрести!
Обзор и требования
В частности, в этом уроке мы рассмотрим:
- Что такое веб-сайт на самом деле и как работает HTML
- Просмотр HTML-кода в вашем веб-браузере
- Использование Python для загрузки веб-страниц
- Использование BeautifulSoup для извлечения частей очищенных данных
Мы будем использовать онлайн-среду программирования Reply.it таким образом, вам не нужно будет устанавливать какое-либо программное обеспечение локально, чтобы следовать шаг за шагом. Если вы хотите адаптировать это руководство к своим собственным потребностям, вам следует создать бесплатную учетную запись, перейдя по ссылке reply.it и следить за их процессом регистрации.
Было бы полезно, если бы у вас было базовое знакомство с Python или другим языком программирования высокого уровня, но мы будем подробно объяснять каждую строку кода, которую мы пишем, так что вы должны быть в состоянии идти в ногу или, по крайней мере, копировать результат, даже если вы этого не делаете.
Веб-страницы: красавица и чудовище
Вы, без сомнения, посещали веб-страницы с помощью веб-браузера раньше. Веб-сайты существуют в двух формах:
- Тот, к которому вы привыкли, где вы можете видеть текст, изображения и другие носители. Различные шрифты, размеры и цвета используются для отображения информации полезным и (как правило) эстетическим способом.
- “Источник” веб – страницы. Это компьютерный код, который сообщает вашему веб-браузеру (например, Mozilla Firefox или Google Chrome), что и как отображать.
Веб-сайты создаются с помощью комбинации трех компьютерных языков: HTML, CSS и JavaScript. Это само по себе огромная и сложная область с запутанной историей, но иметь базовое понимание того, как некоторые из них работают, необходимо для эффективной автоматизации очистки веб-страниц. Если вы откроете любой веб-сайт в своем браузере и щелкните правой кнопкой мыши где-нибудь на странице, вы увидите меню, которое должно включать опцию “просмотр источника страницы” – чтобы проверить кодовую форму веб-сайта, прежде чем ваш веб-браузер интерпретирует его.
Это показано на рисунке ниже: обычная веб-страница слева, с открытым меню (отображается при щелчке правой кнопкой мыши на странице). Нажатие кнопки “Просмотр источника страницы” в этом меню приводит к результату справа-мы видим код, содержащий все данные и вспомогательную информацию, необходимую веб-браузеру для отображения полной страницы. В то время как страница слева легко читается, используется и выглядит хорошо, та, что справа, – это чудовище. Требуется некоторое усилие и опыт, чтобы понять это, но это возможно и необходимо, если мы хотим написать пользовательские веб-скребки.
Навигация по исходному коду с помощью функции Поиска
Первое, что нужно сделать, – это выяснить, как соотносятся две страницы: какие части обычно отображаемого веб-сайта соответствуют каким частям кода. Вы можете использовать “найти” Ctrl + F) в представлении исходного кода, чтобы найти определенные фрагменты текста, которые видны в обычном представлении, чтобы помочь в этом. На веб – странице слева мы видим, что история начинается с фразы “Получение работы на телевидении”. Если мы ищем эту фразу в представлении кода, мы можем найти соответствующий текст внутри кода, в строке 805.
непосредственно перед выделенным разделом находится HTML-код, указывающий, что абзац (
в HTML) начинается здесь и что это особый вид абзаца (введение в историю). Абзац продолжается до символа
. Вам не нужно беспокоиться о полном понимании HTML, но вы должны знать, что он содержит как текстовые данные, составляющие новостную статью, так и дополнительные данные о том, как ее отображать.
Большая часть веб-скрейпинга-это просмотр таких страниц, чтобы а) идентифицировать интересующие нас данные и б) отделить их от разметки и другого кода, с которым они смешиваются. Даже до того, как мы начнем писать свой собственный код, все еще может быть сложно сначала понять чужой.
На большинстве страниц есть много кода для определения структуры, макета, интерактивности и других функциональных возможностей веб-страницы, и относительно мало того, что содержит фактический текст и изображения, которые мы обычно просматриваем. Для особо сложных страниц бывает довольно сложно, даже с помощью функции find, найти код, отвечающий за ту или иную часть страницы. По этой причине большинство веб-браузеров поставляются с так называемыми “инструментами разработчика”, которые предназначены в первую очередь для программистов, чтобы помочь в создании и обслуживании веб-сайтов, хотя эти инструменты также удобны для выполнения веб-скребка.
Навигация по исходному коду с помощью инструментов разработчика
Вы можете открыть инструменты разработчика для вашего браузера из главного меню, с Google Chrome, показанным слева, и Mozilla Firefox справа ниже. Если вы используете другой веб-браузер, вы должны быть в состоянии найти аналогичную настройку.
Активация инструмента открывает новую панель в вашем веб-браузере, обычно внизу или справа. Инструмент содержит панель “Инспектор” и инструмент селектора, который можно выбрать, нажав на значок, выделенный красным цветом ниже. Как только инструмент селектора активен, вы можете щелкнуть по частям веб-страницы, чтобы просмотреть соответствующий исходный код. На изображении ниже мы выбрали тот же самый первый абзац в обычном представлении, и мы снова видим код на панели ниже.
Инструменты разработчика значительно мощнее, чем простой инструмент поиска, но они также более сложны. Вы должны выбрать метод, основанный на вашем опыте и сложности страницы, которую вы пытаетесь проанализировать.
Загрузка веб-страницы с помощью Python
Теперь, когда мы немного больше узнали о том, как строятся веб-страницы в нашем браузере, мы можем начать извлекать их и манипулировать ими с помощью Python. Поскольку Python не является веб-браузером, мы сможем только извлекать и манипулировать исходным кодом HTML, а не просматривать “нормальное” представление веб-страницы.
Мы сделаем это через Python Repl, используя библиотеку requests
. Открыть reply.it и выберите создать новый Python Repl.
Это приведет вас к рабочей среде кодирования Python, где вы можете писать и запускать код Python. Для начала мы загрузим контент с главной страницы BBC News и распечатаем первые 1000 символов исходного кода HTML.
Вы можете сделать это со следующими четырьмя строками Python:
import requests url = "https://bbc.com/news" response = requests.get(url) print(response.text[:1000])
Поместите этот код в main.py
файл, который Ответ автоматически создает для вас, и нажмите кнопку “Выполнить”. После небольшой задержки вы должны увидеть вывод в области вывода – начало исходного кода HTML, аналогичного тому, что мы видели в нашем веб-браузере выше.
Давайте разберем каждую из этих линий.
- В строке 1 мы импортируем библиотеку Python
requests
, которая позволяет нам делать веб-запросы. - В строке 3 мы определяем переменную, содержащую URL-адрес основного новостного сайта BBC. Вы можете посетить этот URL-адрес в своем веб-браузере, чтобы увидеть домашнюю страницу BBC News.
- В строке 4 мы передаем URL-адрес, который мы определили, функции
requests.get
, которая посетит веб-страницу, на которую указывает URL-адрес, и получит исходный код HTML. Мы загружаем это в новую переменную под названиемresponse
. - В строке 5 мы получаем доступ к атрибуту
text
нашего объектаresponse
, который содержит весь исходный код HTML. Мы берем только первые 1000 символов этого текста и передаем их функцииprint
, которая просто сбрасывает полученный текст в нашу панель вывода.
Теперь мы автоматически извлекли веб-страницу и можем отображать часть содержимого. Нас вряд ли заинтересует полный дамп исходного кода веб-страницы (если только мы не храним его по архивным причинам), поэтому давайте извлекем некоторые интересные части страницы, а не только первые 1000 символов.
Использование BeautifulSoup для извлечения всех URL-адресов
Всемирная паутина построена из страниц, которые ссылаются друг на друга с помощью гиперссылок, ссылок или URL-адресов. (Все эти термины используются более или менее взаимозаменяемо).
Предположим, что мы хотим найти все новостные статьи на главной странице BBC News и получить их URL-адреса. Если мы посмотрим на главную страницу ниже, то увидим, что на главной странице есть куча историй. Наведя указатель мыши на любой из заголовков с помощью инструмента “проверить”, мы можем увидеть, что каждый из них имеет уникальный URL-адрес, который приводит нас к этой новости. Например, наведение курсора на основную историю “США и Канада договорились о новой торговой сделке” на изображении ниже является ссылкой на https://www.bbc.com/news/business-45702609.
Если мы проверим этот элемент с помощью инструментов разработчика браузера, то увидим, что это элемент , который является HTML для ссылки, с компонентом
, который указывает на URL. Обратите внимание, что раздел
href
переходит только к последней части URL-адреса, опуская https://www.bbc.com часть. Поскольку мы уже находимся на BBC, сайт может использовать относительные URL-адреса вместо абсолютных URL-адресов . Это означает, что когда вы нажмете на ссылку, ваш браузер поймет, что URL-адрес не является полным, и добавит к нему https://www.bbc.com. Если вы посмотрите вокруг исходного кода главной страницы BBC, вы найдете как относительные, так и абсолютные URL-адреса, что уже затрудняет очистку всех URL-адресов на странице.
Мы могли бы попытаться использовать встроенные функции текстового поиска Python, такие как find()
или регулярные выражения, чтобы извлечь все URL-адреса со страницы BBC, но на самом деле это невозможно сделать надежно. HTML-это сложный язык, который позволяет веб-разработчикам делать много необычных вещей. Забавный взгляд на то, почему мы должны избегать “наивного” метода поиска ссылок, см. в этом очень известном вопросе StackOverflow и первом ответе.
К счастью, существует мощная и простая в использовании библиотека синтаксического анализа HTML под названием BeautifulSoup , которая поможет нам извлечь все ссылки из данного фрагмента HTML. Мы можем использовать его, изменив код в нашем ответе, чтобы он выглядел следующим образом.
import requests from bs4 import BeautifulSoup url = "https://bbc.com/news" response = requests.get(url) html = response.text soup = BeautifulSoup(html, "html.parser") links = soup.findAll("a") for link in links: print(link.get("href"))
Если вы запустите этот код, вы увидите, что он выводит десятки URL-адресов, по одному на строку. Вы, вероятно, заметите, что теперь код выполняется гораздо дольше, чем раньше-BeautifulSoup не встроен в Python, это сторонний модуль. Это означает, что перед запуском кода Reply должен пойти и принести эту библиотеку и установить ее для вас. Последующие запуски будут быстрее.
Код похож на тот, что был у нас раньше, с несколькими дополнениями.
- В строке 2 мы импортируем библиотеку BeautifulSoup, которая используется для синтаксического анализа и обработки HTML.
- Одна строка 9, мы превращаем наш HTML в “суп”. Это красивое представление веб-страницы, которое содержит кучу полезных программных функций для поиска и изменения данных на странице. Мы используем опцию “html.parser” для разбора HTML, которая включена по умолчанию-BeautifulSoup также позволяет вам указать здесь пользовательский HTML-парсер. Например, вы можете установить и указать более быстрый парсер, который может быть полезен, если вам нужно обработать много HTML-данных.
- В строке 10 мы находим все элементы
a
в нашем HTML-файле и извлекаем их в список. Помните, когда мы просматривали URL-адреса с помощью нашего веб-браузера (рис. 7), мы заметили, что элементв HTML используется для определения ссылок, а атрибут
href
используется для указания того, куда должна идти ссылка. Эта строка находит все элементы HTML.
- В строке 11 мы перебираем все имеющиеся у нас ссылки, а в строке 12 выводим раздел
href
.
Эти последние две строки показывают, почему BeautifulSoup полезен. Попытаться найти и извлечь эти элементы без него было бы удивительно трудно, но теперь мы можем сделать это в двух строках читаемого кода!
Если мы посмотрим на URL-адреса в области вывода, то увидим довольно смешанный набор результатов. У нас есть абсолютные URL-адреса (начинающиеся с “http”) и относительные (начинающиеся с “/”). Большинство из них идут на общие страницы, а не на конкретные новостные статьи. Нам нужно найти шаблон в интересующих нас ссылках (которые идут на новостные статьи), чтобы мы могли извлечь только их.
Опять же, метод проб и ошибок-лучший способ сделать это. Если мы перейдем на главную страницу BBC News и с помощью инструментов разработчика проверим ссылки на новостные статьи, то обнаружим, что все они имеют одинаковую структуру. Это относительные URL-адреса, которые начинаются с “/news” и заканчиваются длинным номером, например /news/newsbeat-45705989
Мы можем внести небольшое изменение в наш код, чтобы выводить только те URL-адреса, которые соответствуют этому шаблону. Замените последние две строки нашего кода Python следующими четырьмя строками:
for link in links: href = link.get("href") if href.startswith("/news") and href[-1].isdigit(): print(href)
Здесь мы все еще перебираем все ссылки, которые BeautifulSoup нашел для нас, но теперь мы извлекаем href
в свою собственную переменную сразу после этого. Затем мы проверяем эту переменную, чтобы убедиться, что она соответствует нашим условиям (начинается с “/news” и заканчивается цифрой), и только если это так, то мы распечатываем ее.
Извлечение всех статей с главной страницы
Теперь, когда у нас есть ссылка на каждую статью на главной странице BBC News, мы можем получить данные для каждой из этих отдельных статей. В качестве игрушечного проекта давайте извлекем имена собственные (люди, места и т. Д.) Из каждой статьи и распечатаем наиболее распространенные, чтобы понять, о чем сегодня говорят.
Адаптируйте свой код так, чтобы он выглядел следующим образом:
import requests import string from collections import Counter from bs4 import BeautifulSoup url = "https://bbc.com/news" response = requests.get(url) html = response.text soup = BeautifulSoup(html, "html.parser") links = soup.findAll("a") news_urls = [] for link in links: href = link.get("href") if href.startswith("/news") and href[-1].isdigit(): news_url = "https://bbc.com" + href news_urls.append(news_url) all_nouns = [] for url in news_urls[:10]: print("Fetching {}".format(url)) response = requests.get(url) html = response.text soup = BeautifulSoup(html, "html.parser") words = soup.text.split() nouns = [word for word in words if word.isalpha() and word[0] in string.ascii_uppercase] all_nouns += nouns print(Counter(all_nouns).most_common(100))
Этот код довольно сложен, чем то, что мы писали ранее, поэтому не волнуйтесь, если вы не понимаете всего этого. Основные изменения заключаются в следующем:
- В верхней части мы добавляем два новых импорта в дополнение к библиотеке
requests
. Первый новый модуль-это модуль дляstring
, который является стандартным модулем Python, содержащим некоторые полезные сочетания слов и букв. Мы будем использовать его, чтобы идентифицировать все заглавные буквы в нашем алфавите. Второй модуль-этоСчетчик
, который является частью встроенногомодуля коллекций
. Это позволит нам найти наиболее распространенные существительные в списке, как только мы построим список всех существительных. - Мы добавили
new_urls = []
в верхней части первого циклаfor
. Вместо того, чтобы распечатывать каждый URL-адрес, как только мы определили его как “новостной URL-адрес”, мы добавляем его в этот список, чтобы мы могли загрузить каждую страницу позже. Внутри цикла for двумя строками ниже мы объединяем корневой домен (“http://bbc.com”) с каждым атрибутом href, а затем добавьте полный URL-адрес в наш списокnews_urls
. - Затем мы переходим в другой цикл for, где перебираем первые 10 новостных URL-адресов (если у вас есть больше времени, вы можете удалить часть
[:10]
, чтобы перебрать все новостные страницы, но для эффективности мы просто продемонстрируем первые 10). - Мы распечатываем URL-адрес, который мы получаем (поскольку загрузка каждой страницы занимает около секунды, приятно показать некоторую обратную связь, чтобы мы могли видеть, что программа работает).
- Затем мы берем страницу и превращаем ее в суп, как делали это раньше.
- С помощью
words.text.split()
мы извлекаем весь текст со страницы и разбиваем получившийся большой объем текста на отдельные слова. Функция Pythonsplit()
разбивается на пустое пространство, что является грубым способом извлечения слов из фрагмента текста, но пока она будет служить нашей цели. - Следующая строка проходит через все слова в данной статье и сохраняет только те, которые состоят из числовых символов и начинаются с заглавной буквы (
string.ascii_uppercase
– это просто заглавный алфавит). Это также чрезвычайно грубый способ извлечения существительных, и мы получим много слов (например, в начале предложений), которые на самом деле не являются собственными существительными, но опять же это достаточно хорошее приближение на данный момент. - Затем мы добавляем все слова, которые выглядят как существительные, в наш список
all_nouns
и переходим к следующей статье, чтобы сделать то же самое. - Наконец, как только мы загрузили все страницы, мы распечатываем 100 наиболее распространенных существительных вместе с подсчетом того, как часто они появлялись, используя удобный объект Python
Counter
.
Вы должны увидеть результат, похожий на тот, что показан на рисунке ниже (хотя ваши слова будут отличаться, так как новости меняются каждые несколько часов). У нас есть наиболее распространенные “существительные”, за которыми следует подсчет того, как часто это существительное появлялось во всех 10 статьях, которые мы рассматривали.
Facebook и Facebook появляются в большинстве статей из-за ссылок на социальные сети в нижней части каждой статьи, поэтому их присутствие не означает, что Facebook и Twitter сами по себе находятся в новостях сегодня. Точно так же такие слова, как “От”, не являются существительными, и другие слова, такие как “Би-би-си” и “Бизнес”, также включены, потому что они появляются на каждой странице вне основного текста статьи.
Куда дальше?
Мы завершили основы веб-скребка и рассмотрели, как работает веб, как извлекать информацию из веб-страниц и как делать некоторые очень простые извлечения текста. Вы, вероятно, захотите сделать что-то еще, кроме извлечения слов из Би-би-си! Вы можете раскошелиться на этот ответ от https://repl.it/@GarethDwyer1/beginnerwebscraping и измените его, чтобы изменить, какой сайт он очищает и какой контент извлекает. Вы также можете присоединиться к серверу Repl Discord , чтобы общаться с другими разработчиками, которые работают над аналогичными проектами и которые с радостью обменяются с вами идеями или помогут, если вы застряли.
Мы прошли через очень гибкий метод соскабливания паутины, но это “быстрый и грязный” способ. Если Би-би-си обновит свой веб-сайт и некоторые из наших предположений (например, что новостные URL-адреса будут заканчиваться цифрой) сломаются, наш веб-скребок тоже сломается.
Как только вы немного поскребете паутину, вы заметите, что одни и те же шаблоны и проблемы возникают снова и снова. Из-за этого существует множество фреймворков и других инструментов, которые решают эти общие проблемы (поиск всех URL-адресов на странице, извлечение текста из другого кода, работа с изменяющимися веб-сайтами и т. Д.), И для любого большого проекта веб-скребка вы определенно захотите использовать их вместо того, чтобы начинать с нуля.
Некоторые из лучших инструментов веб-скребка Python:
- Scrapy : Фреймворк, используемый людьми, которые хотят очистить миллионы или даже миллиарды веб-страниц. Scrapy позволяет создавать “пауков” – программных роботов, которые перемещаются по Сети с высокой скоростью, собирая данные на основе заданных вами правил.
- Газета : мы коснулись того, как трудно отделить основной текст новостной онлайн-статьи от всего остального контента на странице (колонтитулы, объявления и т. Д.). Эта проблема невероятно трудна для решения. Газета использует комбинацию вручную заданных правил и некоторых хитроумных алгоритмов для удаления “шаблонного” или непрофильного текста из каждой статьи.
- Selenium : мы очистили некоторые базовые материалы без использования веб-браузера, и это прекрасно работает для изображений и текста. Однако многие части современного Интернета динамичны-например, они загружаются только тогда, когда вы прокручиваете страницу вниз достаточно далеко или нажимаете на кнопку, чтобы открыть больше контента. Эти динамические сайты сложно очистить, но Selenium позволяет вам запускать реальный веб-браузер и управлять им так же, как человек (но автоматически), и это позволяет вам получить доступ к такому динамическому контенту.
Нет недостатка в других инструментах, и многое можно сделать, просто используя их в сочетании друг с другом. Веб-скребок-это огромный мир, которого мы только что коснулись , но в следующем уроке мы рассмотрим еще несколько вариантов использования веб-скребка, в частности, создание облаков новостных слов.