Введение в веб-парсинг на Python.
Сслыка на статью
Содержание:
- Ваш первый веб-скрапер
- Извлекаем файлы из HTML методами String объекта
- HTML парсер на Python
- Использование объекта BeautifulSoup. Методы:
- Взаимодействие с HTML формами
- Взаимодействие с сайтом в реальном времени
- Заключение
Веб-скарпинг - это автоматизированный процесс сбора данных с сайта.
Интернет – является центром всей информации на Земле, к сожалению, многая информация не является правдивой. Множество дисциплин, таких как : data science, business intelligence стараются искать истинную информацию и получать из неё пользу для бизнеса.
В данном гайде мы научимся:
- Парсить веб-сайт используя string методы и обычные выражения
- Парсить используя HTML parser
- Взаимодействовать с формами и другими компонентами сайта
Сбор информации с веб-сайта
Повторим ещё раз, веб-скрапинг - это автоматизированный сбор данных с сайтов. Но некоторые сайты запрещают парсить их данные при помощи того инструмента, который мы разработаем с вами в нынешнем гайде. Сайты могут запрещать парсить свои данные по след. Причинам:
- Количество запросов. Сайт может просто не справиться и затормозить.
- Важная информация.
Ваш первый Web scraper
Первый пакет, который мы используем, называется urlib. Он поможет нам работать с url. Данный модуль содержит urlopen() его нужно импортировать.
from urllib.request import urlopen
Далее присваиваем переменной url адрес в формате String.
url = "http://olympus.realpython.org/profiles/aphrodite"
Для того чтобы открыть данный сайт в python:
page = urlopen(url)
urlopen() возвращает нам объект типа HTTPResponse
>>> page <http.client.HTTPResponse object at 0x105fef820>
Для того чтобы прочитать объект HTTPResponse нужно воспользоваться методом .read() далее декодировать файл при помощи .decode():
>>> html_bytes = page.read() >>> html = html_bytes.decode("utf-8")
Теперь вы можете вывести данные переменной, чтобы увидеть контент сайта.
print(html) <html> <head> <title>Profile: Aphrodite</title> </head> <body bgcolor="yellow"> <center> <br><br> <img src="/static/aphrodite.gif" /> <h2>Name: Aphrodite</h2> <br><br> Favorite animal: Dove <br><br> Favorite color: Red <br><br> Hometown: Mount Olympus </center> </body> </html>
И когда у вас есть HTML как текст, вы можете извлечь информацию из него разными способами.
Извлекаем файлы из HTML методами String объекта
Одним из методов извлечения информации HTML файла могут быть string методы. Например, .find() для поиска через текст .
.fing() возвращает индекс первого входа нужного нам символа/тега. Покажем на примере "<title>" методом .find().
>>> title_index = html.find("<title>") >>> title_index 14
Для того чтобы найти начало заголовка нам нужно к индексу добавить длину тега "<title>".
>>> start_index = title_index + len("<title>") >>> start_index 21
Также можем найти место где заканчивается "<title>":
>>> end_index = html.find("</title>") >>> end_index 39
Наконец, мы можем извлечь всё что находится в "<title>", зная первый и последний индекс:
>>> title = html[start_index:end_index] >>> title 'Profile: Aphrodite'
На самом деле, HTML файл может быть намного менее предсказуемым, чем на Aphrodite странице. Поэтому далее мы вам покажем другой способ, который может решить эту задачу.
Регулярные выражения
Регулярные выражения - это паттерны, которые используются для поиска внутри текста типа string. Для этого нам нужна библиотека re.
Мы импортируем модуль re.
>>> import re
Регулярные выражения используют специальные метасимволы для определения разных паттернов. Например символ "*" разрешает вводить любые символы после себя.
Покажем на примере .findall() мы будем искать все совпадения с требуемым для нас выражением (первый элемент - то что мы ищем, второй - в каком тексте).
>>> re.findall("ab*c", "ac") ['ac']
Используя параметр re.IGNORECASE позволяет методу не учитывать регистр.
>>> re.findall("ab*c", "ABC") [] >>> re.findall("ab*c", "ABC", re.IGNORECASE) ['ABC']
Метод .replace() - заменяет все символы в тексте на требуемые нам символы.
Метод .sub() - "<.*>" для замены всего что находится между < и >.
Давайте взглянем ближе на регулярные выражения:
- <title*?> - отмечает открытие тега "title"
- *? - отмечает весь текст после открытие тега "<title>"
- </title*?> - отмечает элемент, который закрывает тег.
HTML парсер на Python
Ладно, хватит играться и развлекаться пора использовать серьёзные вещи для парсинг. К нашему счастью, в библиотеках Python есть множество инструментов, которые созданы для разных задач. Для парсинга нам подойдет Beautiful soup.
Скачиваем Beautiful soup
Воспользуемся терминалом:
$ python3 -m pip install beautifulsoup4
Теперь, вернёмся в едитор.
Создание объекта типа BeautifulSoup
from bs4 import BeautifulSoup from urllib.request import urlopen url = "http://olympus.realpython.org/profiles/dionysus" page = urlopen(url) html = page.read().decode("utf-8") soup = BeautifulSoup(html, "html.parser")
Наша программа совершит 3 действия:
- Откроет URL
- Прочитает элементы и переведёт их в String
- Присвоит это объекту типа BeautifulSoup
При создании переменной "soup" мы передаём два аргумента, первый это сайт, который мы парсим, второй - какой парсер использовать.
Использование объекта BeautifulSoup. Методы:
>>> print(soup.get_text()) Profile: Dionysus Name: Dionysus Hometown: Mount Olympus Favorite animal: Leopard Favorite Color: Wine
Как можно заметить, есть много пустых строк, это результат появления символов новой строки в тексте HTML. Их можно убрать используя метод .replace() .
.find()
Если вам нужно что то найти, используйте .find()
>>> soup.find_all("img") [<img src="/static/dionysus.jpg"/>, <img src="/static/grapes.png"/>]
Данная команда возвращает все теги <img>.
Tag
Каждый объект становится тегом, поэтому можно использовать методы.
.name
>>> image1.name 'img'
Даст нам имя переменной
["src"]
Этот метод даст нам путь к файлу, например:
>>> image1["src"] '/static/dionysus.jpg' >>> image2["src"] '/static/grapes.png'
.title
Можем увидеть что находится в заголовке
>>> soup.title <title>Profile: Dionysus</title>
.string
Этот метод убирает теги, покажем на примере title:
>>> soup.title.string 'Profile: Dionysus'
Взаимодействие с HTML формами
Библиотека urllib идеально подходит для сбора информации с сайта, но иногда нам приходится взаимодействовать с сайтом, заполнять формы, нажать на кнопку. В этом нам поможет модуль MechanicalSoup.
Устанавливаем модуль
$ python3 -m pip install MechanicalSoup
Создаём объект типа Browser
>>> import mechanicalsoup >>> browser = mechanicalsoup.Browser()
Можем запросить url
>>> url = "http://olympus.realpython.org/login" >>> page = browser.get(url)
Если мы проверим "page" , то нам вернётся 200 - это значит что с сайтом всё в порядке. Если вернётся 404 или 500, то есть ошибка со стороны сайта/сервера.
.soup
Показывает нам структуру HTML
>>> page.soup <html> <head> <title>Log In</title> </head> <body bgcolor="yellow"> <center> <br/><br/> <h2>Please log in to access Mount Olympus:</h2> <br/><br/> <form action="/login" method="post" name="login"> Username: <input name="user" type="text"/><br/> Password: <input name="pwd" type="password"/><br/><br/> <input type="submit" value="Submit"/> </form> </center> </body> </html>
Взаимодействие с сайтом в реальном времени
Иногда, нужно получать информацию с сайта в реальном времени. К примеру, нажимать кнопку "Обновить", что не было самым приятным, но теперь всё изменилось.
Теперь мы можем использовать .get() объекта Browser.
Во-первых, нужно определить какой элемент требует обновления, скорее всего нужно просто найти id.
<h2 id="result">4</h2>
Давайте на примере разберёмся.
import mechanicalsoup browser = mechanicalsoup.Browser() page = browser.get("http://olympus.realpython.org/dice") tag = page.soup.select("#result")[0] result = tag.text print(f"The result of your dice roll is: {result}")
В этом примере, метод .select() ищет элемент с id=result(#result) .
Прежде всего, советуем установить промежуток, чтобы сайт успевал перезагружаться. Используйте time.sleep(5) - 5 секунд.
Полный вариант:
import time import mechanicalsoup browser = mechanicalsoup.Browser() for i in range(4): page = browser.get("http://olympus.realpython.org/dice") tag = page.soup.select("#result")[0] result = tag.text print(f"The result of your dice roll is: {result}") time.sleep(10)
Когда вы запустите программу, вы сразу увидите первый результат, который будет выведен на консоль. Далее будет перерыв в 10 секунд и всё повторится.
После 4 циклов программа остановится.
Используя такую технику, вы сможете собирать данные сайта в реальном времени, но будьте осторожны, слишком частые запросы буду подозрительны для сайта. Иначе ваш ip будет заблокирован и не будет возможности зайти на него.
Так же возможно сломать сервер, на котором хостится сайт, поэтому советуем читать "Правила пользования" (Terms of use)
Заключение
Python уникальный инструмент для множества задач. В данном уроке мы научились собирать информацию с сайта и переводить его в текст.
Только не забывайте, не все хотят делиться информацией в интернете. Всегда читайте Правила пользования, уважайте других контент-мейкеров.