Веб-скрапинг с Python

0
7523
views

web scraping

Данные это ядро предсказательного моделирования, визуализации и анализа. К сожалению, нужные данные не всегда легко доступны пользователю, чаще всего они неструктурированны. Самым большим источником данных является Интернет. С помощью программирования мы можем извлекать и обрабатывать данные, найденные в Интернете, для наших целей — это называется веб-скрапинг (Web scraping). Веб-скрапинг позволяет нам извлекать данные из вебсайтов и делать с ними все что захотим. В этой статье мы покажем как скрапить вебсайт с помощью всего лишь нескольких строк кода на Python.

Веб-скрапинг с Python

Даже несмотря на то что есть популярные фреймворки и сервисы для скрапинга (Scrapy, Scrapinghub, etc.), иногда их изучение может быть довольно сложным или они могут быть излишни для решения текущих задач. Научиться делать это с простыми библиотеками Python даст вам более глубокое понимание как эти фреймворки работают, если вы когда-либо захотите ими воспользоваться.

Чтобы скрапить вебсайт, нам нужно как-то сообщаться по Интернету (HTTP), для чего мы будем использовать популярную библиотеку Python под названием Requests. Когда мы будем извлекать данные, нам нужно будет выделить их из HTML, для чего мы воспользуемся lxml (популярная альтернатива Beautiful Soup).

import requests
from lxml import html

url = 'https://www.datawhatnow.com'

def get_parsed_page(url):
 """Return the content of the website on the given url in
 a parsed lxml format that is easy to query."""
 
 response = requests.get(url)
 parsed_page = html.fromstring(response.content)
 return parsed_page

parsed_page = get_parsed_page(url)

# Print the website's title
parsed_page.xpath('//h1/a/text()')  # ['Data, what now?']

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

веб-скрапинг

Все примеры скрапинга в этой статье будут сделаны на вебсайте datawhatnow.com. Название этого сайта это текст между тегами <a>, имеющими родительский тег <h1>. Чтобы получить этот текст, мы запускаем запрос ‘//h1/a/text()’. Это читается как «Начиная с корня, найди тег <h1>, затем найди его «ребенка» — тег <a> и извлеки текст внутри него». Использование “//” позволяет нам писать более короткие запросы, так как нам не приходится указывать все узлы пути.

xpath

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

# Print post names
parsed_page.xpath('//h2/a/text()')

# Output
# ['SimHash for question deduplication',
#  'Feature importance and why it’s important']

Краулинг

Веб-скрапинг это акт извлечения информации из сайта. Иногда программе приходится переходить от одной ссылки к другой чтобы собрать всю необходимую информацию — это называется краулинг (crawling). Мы найдем интересующие нас URL и обработаем их как раньше (запрос и поиск).

Давайте попробуем извлечь названия параграфов из постов блога на datawhatnow.com. Мы должны найти ссылки на посты, запросить их HTML-код и проанализировать их. Пока мы только извлекали текст из тегов, а теперь нам нужно извлечь ссылку из атрибута “href” тега <a>. К счастью для нас, это легко: вместо того чтобы писать “text()”, как мы делали раньше, мы просто должны написать “@attribute_name” (в нашем случае – “@href”).

# Getting paragraph titles in blog posts
post_urls = parsed_page.xpath('//h2//a/@href')

for post_url in post_urls:
    print('Post url:', post_url)
    
    parsed_post_page = get_parsed_page(post_url)
    paragraph_titles = parsed_post_page.xpath('//h3/text()')
    paragraph_titles = map(lambda x: ' \n  ' + x, paragraph_titles)
    print(''.join(paragraph_titles) + '\n')

# Output
# Post url: https://datawhatnow.com/simhash-question-deduplicatoin/
# 
#  SimHash 
#  Features 
#  Model performance 
#  Conclusion 
#  References 
#  Leave a Reply  
#  GitHub 
#  Newsletter 
#  Recent Posts 
#  Archives
#
# Post url: https://datawhatnow.com/feature-importance/
# 
#  Data exploration 
#  Feature engineering 
#  Baseline model performance 
#  Feature importance 
#  Model performance with feature importance analysis 
#  Conclusion 
#  Leave a Reply  
#  GitHub 
#  Newsletter 
#  Recent Posts 
#  Archives

Очевидно, что-то не так: мы извлекли названия параграфов, но мы также собрали и другие тексты из тегов <h3> («Leave a Reply», «GitHub», «Newsletter» и т.д.). Наш запрос Xpath недостаточно конкретен. Проверка ссылок в посте блога показывает, что их родительский тег – <div> с атрибутом “class=»entry-content»”. Мы можем воспользоваться этой информацией для написания более точного запроса (‘//div[@class=”entry-content”]/h3/text()’).

for post_url in post_urls:
    print('Post url:', post_url)
    
    parsed_post_page = get_parsed_page(post_url)
    paragraph_title_xpath = '//div[@class="entry-content"]/h3/text()'
    paragraph_titles = parsed_post_page.xpath(paragraph_title_xpath)
    paragraph_titles = map(lambda x: ' \n  ' + x, paragraph_titles)
    print(''.join(paragraph_titles) + '\n')

# Post url: https://datawhatnow.com/simhash-question-deduplicatoin/
# 
#  SimHash 
#  Features 
#  Model performance 
#  Conclusion 
#  References
#
# Post url: https://datawhatnow.com/feature-importance/
#
#  Data exploration 
#  Feature engineering 
#  Baseline model performance 
#  Feature importance 
#  Model performance with feature importance analysis 
#  Conclusion

Теперь выводятся только заголовки параграфов.

Роботы

Веб-краулинг это мощная вещь, но с большими возможностями приходит и большая ответственность. Когда вы скрапите чей-то вебсайт, вы должны воздержаться от того чтобы посылать слишком много запросов. На большинстве сайтов есть “robots.txt”, показывающий правила, которым ваш веб-скрапер должен подчиняться (какие URL можно скрапить, какие – нет, количество запросов, которые вы можете посылать и т. д.). Вы можете посмотреть пример здесь или, например, файлы от Hacker News or DataTau.

Заключение

Использование Python с lxml и Requests позволяет нам относительно легко заниматься веб-скрапингом, и обычно это требует лишь нескольких строк кода. Опираясь на это вы можете выполнять базовый веб-скрапинг, а когда почувствуете себя увереннее, можете ппробовать другие фреймворки и библиотеки. Для следующего шага можно рекомендовать Scrapy в силу его относительной простоты и гибкости при достаточных возможностях.

Удачного скрапинга!

***
Подписывайтесь на наш канал в Telegram!


python logo

Хочешь знать больше о Python?

Подпишись на наш канал о Python в Telegram!

×

ОСТАВЬТЕ ОТВЕТ

Please enter your comment!
Please enter your name here