Парсинг на python что это
Перейти к содержимому

Парсинг на python что это

  • автор:

Почему стоит научиться «парсить» сайты, или как написать свой первый парсер на Python

image

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

Перейдем к этапам парсинга.

  • Поиск данных
  • Извлечение информации
  • Сохранение данных

И так, рассмотрим первый этап парсинга — Поиск данных.

Так как нужно парсить что-то полезное и интересное давайте попробуем спарсить информацию с сайта work.ua.
Для начала работы, установим 3 библиотеки Python.

pip install beautifulsoup4

Без цифры 4 вы ставите старый BS3, который работает только под Python(2.х).

pip install requests
pip install pandas

Теперь с помощью этих трех библиотек Python, можно проанализировать нашу веб-страницу.

Второй этап парсинга — Извлечение информации.

Попробуем получить структуру html-кода нашего сайта.
Давайте подключим наши новые библиотеки.

import requests from bs4 import BeautifulSoup as bs import pandas as pd 

И сделаем наш первый get-запрос.

URL_TEMPLATE = "https://www.work.ua/ru/jobs-odesa/?page=2" r = requests.get(URL_TEMPLATE) print(r.status_code) 

Статус 200 состояния HTTP — означает, что мы получили положительный ответ от сервера. Прекрасно, теперь получим код странички.

print(r.text) 

Получилось очень много, правда? Давайте попробуем получить названия вакансий на этой страничке. Для этого посмотрим в каком элементе html-кода хранится эта информация.

Комірник

У нас есть тег h2 с классом «add-bottom-sm», внутри которого содержится тег a. Отлично, теперь получим title элемента a.

soup = bs(r.text, "html.parser") vacancies_names = soup.find_all('h2', class_='add-bottom-sm') for name in vacancies_names: print(name.a['title']) 

Хорошо, мы получили названия вакансий. Давайте спарсим теперь каждую ссылку на вакансию и ее описание. Описание находится в теге p с классом overflow. Ссылка находится все в том же элементе a.

Some information about vacancy.

Получаем такой код.

vacancies_info = soup.find_all('p', class_='overflow') for name in vacancies_names: print('https://www.work.ua'+name.a['href']) for info in vacancies_info: print(info.text) 

И последний этап парсинга — Сохранение данных.

Давайте соберем всю полученную информацию по страничке и запишем в удобный формат — csv.

import requests from bs4 import BeautifulSoup as bs import pandas as pd URL_TEMPLATE = "https://www.work.ua/ru/jobs-odesa/?page=2" FILE_NAME = "test.csv" def parse(url = URL_TEMPLATE): result_list = r = requests.get(url) soup = bs(r.text, "html.parser") vacancies_names = soup.find_all('h2', class_='add-bottom-sm') vacancies_info = soup.find_all('p', class_='overflow') for name in vacancies_names: result_list['href'].append('https://www.work.ua'+name.a['href']) result_list['title'].append(name.a['title']) for info in vacancies_info: result_list['about'].append(info.text) return result_list df = pd.DataFrame(data=parse()) df.to_csv(FILE_NAME) 

После запуска появится файл test.csv — с результатами поиска.

Парсинг на Python с Beautiful Soup

Парсинг — это распространенный способ получения данных из интернета для разного типа приложений. Практически бесконечное количество информации в сети объясняет факт существования разнообразных инструментов для ее сбора. В процессе скрапинга компьютер отправляет запрос, в ответ на который получает HTML-документ. После этого начинается этап парсинга. Здесь уже можно сосредоточиться только на тех данных, которые нужны. В этом материале используем такие библиотеки, как Beautiful Soup, Ixml и Requests. Разберем их.

Установка библиотек для парсинга

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

pip install lxml pip install requests pip install beautifulsoup4

Поиск сайта для скрапинга

Для знакомства с процессом скрапинга можно воспользоваться сайтом https://quotes.toscrape.com/, который, похоже, был создан для этих целей.

сайт для скрапинга

Из него можно было бы создать, например, хранилище имен авторов, тегов или самих цитат. Но как это сделать? Сперва нужно изучить исходный код страницы. Это те данные, которые возвращаются в ответ на запрос. В современных браузерах этот код можно посмотреть, кликнув правой кнопкой на странице и нажав «Просмотр кода страницы».

Просмотр кода страницы

На экране будет выведена сырая HTML-разметка страница. Например, такая:

На этом примере можно увидеть, что разметка включает массу на первый взгляд перемешенных данных. Задача веб-скрапинга — получение доступа к тем частям страницы, которые нужны. Многие разработчики используют регулярные выражения для этого, но библиотека Beautiful Soup в Python — более дружелюбный способ извлечения необходимой информации.

Создание скрипта скрапинга

В PyCharm (или другой IDE) добавим новый файл для кода, который будет отвечать за парсинг.

 
# scraper.py
import requests
from bs4 import BeautifulSoup

url = 'https://quotes.toscrape.com/'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'lxml')

print(soup)

Отрывок выше — это лишь начало кода. В первую очередь в верхней части файла выполняется импорт библиотек requests и Beautiful Soup. Затем в переменной url сохраняется адрес страницы, с которой будет поступать информация. Эта переменная затем передается функции requests.get() . Результат присваивается переменной response . Дальше используем конструктор BeautifulSoup() , чтобы поместить текст ответа в переменную soup . В качестве формата выберем lxml . Наконец, выведем переменную. Результат должен выглядеть приблизительно вот так.

Вот что происходит: ПО заходит на сайт, считывает данные, получает исходный код — все по аналогии с ручным подходом. Единственное отличие в том, что в этот раз достаточно лишь одного клика.

Парсинг на Python с Beautiful Soup

Прохождение по структуре HTML

HTML — это HyperText Markup Language («язык гипертекстовой разметки»), который работает за счет распространения элементов документа со специальными тегами. В HTML есть много разнообразных тегов, но стандартный шаблон включает три основных: html , head и body . Они организовывают весь документ. В случае со скрапингом интерес представляет только тег body .

Написанный скрипт уже получает данные о разметке из указанного адреса. Дальше нужно сосредоточиться на конкретных интересующих данных.

Если в браузере воспользоваться инструментом «Inspect» (CTRL+SHIFT+I), то можно достаточно просто увидеть, какая из частей разметки отвечает за тот или иной элемент страницы. Достаточно навести мышью на определенный тег span , как он подсветит соответствующую информацию на странице. Можно увидеть, что каждая цитата относится к тегу span с классом text .

Парсинг на Python с Beautiful Soup

Таким образом и происходит дешифровка данных, которые требуется получить. Сперва нужно найти некий шаблон на странице, а после этого — создать код, который бы работал для него. Можете поводить мышью и увидеть, что это работает для всех элементов. Можно увидеть соотношение любой цитаты на странице с соответствующим тегом в коде.

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

Парсинг HTML-разметки

В HTML-документе хранится много информации, но благодаря Beautiful Soup проще находить нужные данные. Порой для этого требуется всего одна строка кода. Пойдем дальше и попробуем найти все теги span с классом text . Это, в свою очередь, вернет все теги. Когда нужно найти несколько одинаковых тегов, стоит использовать функцию find_all() .

 
# scraper.py
import requests
from bs4 import BeautifulSoup

url = 'https://quotes.toscrape.com/'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'lxml')
quotes = soup.find_all('span', class_='text')

print(quotes)

Этот код сработает, а переменной quotes будет присвоен список элементов span с классом text из HTML-документа. Вывод этой переменной даст следующий результат.

Парсинг HTML-разметки

Свойство text библиотеки Beautiful Soup

Возвращаемая разметка — это не совсем то, что нужно. Для получения только данных — цитат в этом случае — можно использовать свойство .text из библиотеки Beautiful Soup. Обратите внимание на код, где происходит перебор всех полученных данных с выводом только нужного содержимого.

 
# scraper.py
import requests
from bs4 import BeautifulSoup

url = 'https://quotes.toscrape.com/'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'lxml')
quotes = soup.find_all('span', class_='text')

for quote in quotes:
print(quote.text)

Это и дает вывод, который требовался с самого начала.

Парсинг на Python с Beautiful Soup

Для поиска и вывода всех авторов можно использовать следующий код. Работаем по тому же принципу — сперва нужно вручную изучить страницу. Можно обратить внимание на то, что каждый автор заключен в тег с классом author . Дальше используем функцию find_all() и сохраняем результат в переменной authors . Также стоит поменять цикл, чтобы перебирать сразу и цитаты, и авторов.

 
# scraper.py
import requests
from bs4 import BeautifulSoup

url = 'https://quotes.toscrape.com/'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'lxml')
quotes = soup.find_all('span', class_='text')

for quote in quotes:
print(quote.text)

Таким образом теперь есть и цитаты, и их авторы.

“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.” --Albert Einstein “It is our choices, Harry, that show what we truly are, far more than our abilities.” --J.K. Rowling “There are only two ways to live your life. One is as though nothing is a miracle. The other is as though everything is a miracle.” --Albert Einstein . 

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

Когда блок получен, можно опускаться ниже с помощью функции find_all для полученного подмножества. А уже дальше потребуется добавить внутренний цикл для завершения процесса.

 
# scraper.py
import requests
from bs4 import BeautifulSoup

url = 'https://quotes.toscrape.com/'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'lxml')
quotes = soup.find_all('span', class_='text')
authors = soup.find_all('small', class_='author')
tags = soup.find_all('div', class_='tags')

for i in range(0, len(quotes)):
print(quotes[i].text)
print('--' + authors[i].text)
tagsforquote = tags[i].find_all('a', class_='tag')
for tagforquote in tagsforquote:
print(tagforquote.text)
print('\n')

Этот код даст такой результат. Круто, не так ли?

“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.” --Albert Einstein change deep-thoughts thinking world “It is our choices, Harry, that show what we truly are, far more than our abilities.” --J.K. Rowling abilities choices . 

Практика парсинга с Beautiful Soup

Еще один хороший ресурс для изучения скрапинга — scrapingclub.com. Там есть множество руководств по использованию инструмента Scrapy. Также имеется несколько страниц, на которых можно попрактиковаться. Начнем с этой https://scrapingclub.com/exercise/list_basic/?page=1.

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

Практика парсинга с Beautiful Soup

После этого должен получиться следующий код.

 
# shop_scraper.py
import requests
from bs4 import BeautifulSoup

url = 'https://scrapingclub.com/exercise/list_basic/?page=1'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'lxml')
items = soup.find_all('div', class_='col-lg-4 col-md-6 mb-4')

for n, i in enumerate(items, start=1):
itemName = i.find('h4', class_='card-title').text.strip()
itemPrice = i.find('h5').text
print(f': за ')
1: $24.99 за Short Dress 2: $29.99 за Patterned Slacks 3: $49.99 за Short Chiffon Dress 4: $59.99 за Off-the-shoulder Dress . 

Скрапинг с учетом пагинации

Ссылка выше ведет на одну страницу коллекции, включающей на самом деле несколько страниц. На это указывает page=1 в адресе. Скрипт Beautiful Soup можно настроить и так, чтобы скрапинг происходил на нескольких страницах. Вот код, который будет извлекать данные со всех связанных страниц. Когда все URL захвачены, скрипт может выполнять запросы к каждой из них и парсить результаты.

 
# shop_scraper.py
# версия для понимания процессов
import requests
from bs4 import BeautifulSoup

url = 'https://scrapingclub.com/exercise/list_basic/?page=1'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'lxml')
items = soup.find_all('div', class_='col-lg-4 col-md-6 mb-4')

for n, i in enumerate(items, start=1):
itemName = i.find('h4', class_='card-title').text.strip()
itemPrice = i.find('h5').text
print(f': за ')

pages = soup.find('ul', class_='pagination')
urls = []
links = pages.find_all('a', class_='page-link')

for link in links:
pageNum = int(link.text) if link.text.isdigit() else None
if pageNum != None:
hrefval = link.get('href')
urls.append(hrefval)

for slug in urls:
newUrl = url.replace('?page=1', slug)
response = requests.get(newUrl)
soup = BeautifulSoup(response.text, 'lxml')
items = soup.find_all('div', class_='col-lg-4 col-md-6 mb-4')
for n, i in enumerate(items, start=n):
itemName = i.find('h4', class_='card-title').text.strip()
itemPrice = i.find('h5').text
print(f': за ')

Результат будет выглядеть следующим образом.

1: $24.99 за Short Dress 2: $29.99 за Patterned Slacks 3: $49.99 за Short Chiffon Dress . 52: $6.99 за T-shirt 53: $6.99 за T-shirt 54: $49.99 за Blazer

Этот код можно оптимизировать для более продвинутых читателей:

 
import requests
from bs4 import BeautifulSoup

url = 'https://scrapingclub.com/exercise/list_basic/'
params =
# задаем число больше номера первой страницы, для старта цикла
pages = 2
n = 1

while params['page'] for n, i in enumerate(items, start=n):
itemName = i.find('h4', class_='card-title').text.strip()
itemPrice = i.find('h5').text
print(f': за ')

# [-2] предпоследнее значение, потому что последнее "Next"
last_page_num = int(soup.find_all('a', class_='page-link')[-2].text)
pages = last_page_num if pages < last_page_num else pages
params['page'] += 1

Выводы

Beautiful Soup — одна из немногих библиотек для скрапинга в Python. С ней очень просто начать работать. Скрипты можно использовать для сбора и компиляции данных из интернета, а результат — как для анализа данных, так и для других сценариев.

Основы парсинга на Python: от Requests до Selenium

Бывают ситуации, когда нужно автоматизировать сбор и анализ данных из разных источников. Например, если хочется мониторить курс рубля в режиме реального времени. Для решения подобных задач применяют парсинг.

В этой статье кратко рассказываем, как парсить данные веб-сайтов с помощью Python. Пособие подойдет новичкам и продолжающим — сохраняйте статью в закладки и задавайте вопросы в комментариях. Подробности под катом!

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

Что такое парсинг?

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

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

Парсинг с помощью HTTP-запросов

Суть метода в том, чтобы отправить запрос на нужный ресурс и получить в ответ веб-страницу. Ресурсом может быть как простой лендинг, так и полноценная, например, социальная сеть. В общем, все то, что умеет «отдавать» веб-сервер в ответ на HTTP-запросы.

Чтобы сымитировать запрос от реального пользователя, вместе с ним нужно отправить на веб-сервер специальные заголовки — User-Agent, Accept, Accept-Encoding, Accept-Language, Cache-Control и Connection. Их вы можете увидеть, если откроете веб-инспектор своего браузера.

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

Подготовка заголовков

На самом деле, необязательно отправлять с запросом все заголовки. В большинстве случаев достаточно User-Agent и Accept. Первый заголовок поможет сымитировать, что мы реальный пользователь, который работает из браузера. Второй — укажет, что мы хотим получить от веб-сервера гипертекстовую разметку.

st_accept = "text/html" # говорим веб-серверу, # что хотим получить html # имитируем подключение через браузер Mozilla на macOS st_useragent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 12_3_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.4 Safari/605.1.15" # формируем хеш заголовков headers =

После формирования заголовков нужно отправить запрос и сохранить страницу из ответа веб-сервера. Это можно сделать с помощью нескольких библиотек: Requests, ScraPy или PySpider.

Requests: получаем страницу по запросу

Для начала работы будет достаточно Requests — он удобнее и проще, чем привычный модуль urllib.

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

Для примера попробуем спарсить страницу с курсами в Академии Selectel — это можно сделать за несколько действий:

# импортируем модуль import requests … # отправляем запрос с заголовками по нужному адресу req = requests.get("https://selectel.ru/blog/courses/", headers) # считываем текст HTML-документа src = req.text print(src) 

Пример: парсинг страницы с курсами в Академии Selectel.

Сервер вернет html-страницу, который можно прочитать с помощью атрибута text.

Курсы - Блог компании Селектел 

Супер — гипертекстовую разметку страницы с курсами получили. Но что делать дальше и как извлечь из этого многообразия полезные данные? Для этого нужно применить некий «парсер для выборки данных».

Beautiful Soup: извлекаем данные из HTML

Извлечь полезные данные из полученной html-страницы можно с помощью библиотеки Beautiful Soup.

Beautiful Soup — это, по сути, анализатор и конвертер содержимого html- и xml-документов. С помощью него полученную гипертекстовую разметку можно преобразовать в полноценные объекты, атрибуты которых — теги в html.

# импортируем модуль from bs4 import BeautifulSoup … # инициализируем html-код страницы soup = BeautifulSoup(src, 'lxml') # считываем заголовок страницы title = soup.title.string print(title) # Программа выведет: Курсы - Блог компании Селектел 

Готово. У нас получилось спарсить и напечатать заголовок страницы. Где это можно применить — решать только вам. Например, мы в Selecte на базе Requests и Beautiful Soup разработали парсер данных с Хабра. Он помогает собирать и анализировать статистику по выбранным хабраблогам. Подробнее о решении можно почитать в предыдущей статье.

Проблема парсинга с помощью HTTP-запросов

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

Интересен Python? Мы собрали самые интересные и популярные запросы разработчиков в одном файле! По ссылке — материалы по геймдеву, машинному обучению, программированию микроконтроллеров и графических интерфейсов.

Парсинг с помощью эмулятора

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

Настройка рабочего окружения

1. Установите ChromeDriver — именно с ним будет взаимодействовать Selenium. Если вы хотите, чтобы актуальная версия ChromeDriver подтягивалась автоматически, воспользуйтесь webdriver-manager. Далее импортируйте Selenium и необходимые зависимости.

pip3 install selenium 
from selenium import webdriver as wd 

2. Инициализируйте ChromeDriver. В качестве executable_path укажите путь до установленного драйвера.

browser = wd.Chrome("/usr/bin/chromedriver/") 

Теперь попробуем решить задачу: найдем в Академии Selectel статьи о Git.

Задача: работа с динамическим поиском

При переходе на страницу Академии встречает общая лента, в которой собраны материалы для технических специалистов. Они помогают прокачивать навыки и быть в курсе новинок из мира IT.

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

Шаг 1. Планирование

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

Теперь скопируем названия классов html-элементов и напишем скрипт!

Шаг 2. Работа с полем ввода

Работа с html-элементами сводится к нескольким пунктам: регистрации объектов и запуску действий, которые будет имитировать Selenium.

. # регистрируем кнопку "Поиск" и имитируем нажатие open_search = browser.find_element_by_class_name("header_search") open_search.click() # регистрируем текстовое поле и имитируем ввод строки "Git" search = browser.find_element_by_class_name("search-modal_input") search.send_keys("Git") 

Осталось запустить скрипт и проверить, как он отрабатывает:

Скрипт работает корректно — осталось вывести результат.

Шаг 3. Чтение ссылок и результат

Вне зависимости от того, какая у вас задача, если вы работаете с Requests и Selenium, Beautiful Soup станет серебряной пулей в обоих случаях. С помощью этой библиотеки мы извлечем полезные данные из полученной гипертекстовой разметки.

from bs4 import BeautifulSoup . # ставим на паузу, чтобы страница прогрузилась time.sleep(3) # загружаем страницу и извлекаем ссылки через атрибут rel soup = BeautifulSoup(browser.page_source, 'lxml') all_publications = \ soup.find_all('a', )[1:5] # форматируем результат for article in all_publications: print(article['href']) 

Готово — программа работает и выводит ссылки на статьи о Git. При клике по ссылкам открываются соответветствующие страницы в Академии Selectel.

Делаем парсер, чтобы массово тянуть с сайтов что угодно

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

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

После парсинга полученный текст можно передать в другие программы — например подстроить свои цены под цены конкурентов, обновить информацию на своём сайте, проанализировать текст постов или собрать бигдату для тренировки нейросетей.

Что делаем

Сегодня мы спарсим все статьи «Кода» кроме новостей и задач, причём сделаем всё так:

  1. Научимся обрабатывать одну страницу.
  2. Сделаем из этого удобную функцию для обработки.
  3. Найдём все адреса всех нужных страниц.
  4. Выберем нужные нам рубрики.
  5. Для каждой рубрики создадим отдельный файл, в который добавим всё текстовое содержимое всех статей в этой рубрике.

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

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

Выбираем страницу для отладки

Технически самый простой парсинг делается двумя командами в Python, одна из которых — подключение сторонней библиотеки. Но этот код не слишком полезен для нашей задачи, сейчас объясним.

from urllib.request import urlopen inner_html_code = str(urlopen('АДРЕС СТРАНИЦЫ').read(),'utf-8')

Когда мы заберём таким образом страницу, мы получим сырой код, в котором будет всё: метаданные, шапка, подвал и т. д. А нам нужно не только достать информацию из самой статьи (а не всей страницы), а ещё и очистить её от ненужной информации.

Чтобы скрипт научился отбрасывать ненужное, придётся ему прописать, что именно отбрасывать. А для этого нужно знать, что нам не нужно. А значит, нам нужно взять какую-то старую статью, в которой будут все ненужные элементы, и на этой одной странице всё объяснить.

Для настройки скрипта мы возьмём нашу старую статью. В ней есть всё нужное для отладки:

  • текст статьи,
  • подзаголовки,
  • боковые ссылки,
  • кат с кодом,
  • просто вставки кода в текст,
  • титры,
  • рекламный баннер.

Получаем сырой текст

Вот что мы сейчас сделаем:

  1. Подключим библиотеку urlopen для обработки адресов страниц.
  2. Подключим библиотеку BeautifulSoup для разбора исходного кода страницы на теги.
  3. Получим исходный код страницы по её адресу.
  4. Распарсим его по тегам.
  5. Выведем текстовое содержимое распарсенной страницы.

На языке Python это выглядит так:

# подключаем urlopen из модуля urllib from urllib.request import urlopen # подключаем библиотеку BeautifulSoup from bs4 import BeautifulSoup # получаем исходный код страницы inner_html_code = str(urlopen('https://thecode.media/parsing/').read(),'utf-8') # отправляем исходный код страницы на обработку в библиотеку inner_soup = BeautifulSoup(inner_html_code, "html.parser") # выводим содержимое страницы print(inner_soup.get_text())

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

Делаем парсер, чтобы массово тянуть с сайтов что угодно Делаем парсер, чтобы массово тянуть с сайтов что угодно

Чистим текст

Так как нам требуется только сама статья, найдём раздел, в котором она лежит. Для этого посмотрим исходный код страницы, нажав Ctrl+U или ⌘+⌥+U. Видно, что содержимое статьи лежит в блоке , причём такой блок на странице один.

Делаем парсер, чтобы массово тянуть с сайтов что угодно

Чтобы из всего исходного кода оставить только этот блок, используем команду find() с параметром 'div', — она найдёт нужный нам блок, у которого есть характерный признак класса.

Добавим эту команду перед выводом текста на экран:

# оставляем только блок с содержимым статьи
​​inner_soup = inner_soup.find('div', )

Делаем парсер, чтобы массово тянуть с сайтов что угодно

Стало лучше: нет мусора до и после статьи, но в тексте всё ещё много лишнего — содержимое ката с кодом, преформатированный код ( вот такой ), вставки с кодом, титры и рекламный баннер.

Чтобы избавиться и от этого, нам нужно знать, в каких тегах или блоках это лежит. Для этого нам снова понадобится заглянуть в исходный код страницы. Логика будет такая: находим фрагмент текста → смотрим код, который за него отвечает, → удаляем этот код из нашей переменной.Например, если мы хотим убрать титры, то находим блок, где они лежат, а потом в цикле удаляем его командой decompose() .

Делаем парсер, чтобы массово тянуть с сайтов что угодно

Сделаем функцию, которая очистит наш код от любых разделов и тегов, которые мы укажем в качестве параметра:

# очищаем код от выбранных элементов def delete_div(code,tag,arg): # находим все указанные теги с параметрами for div in code.find_all(tag, arg): # и удаляем их из кода div.decompose()

А теперь добавим такой код перед выводом содержимого:

# удаляем титры delete_div(inner_soup, "div", )

Делаем парсер, чтобы массово тянуть с сайтов что угодно

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

# удаляем боковые ссылки delete_div(inner_soup, "div", ) # удаляем баннеры, перебирая все их возможные индексы в цикле (потому что баннеры в коде имеют номера от 1 до 99) for i in range(99): delete_div(inner_soup, "div", ) # удаляем кат delete_div(inner_soup, "div", ) # удаляем преформатированный код delete_div(inner_soup, 'pre','') # удаляем вставки с кодом delete_div(inner_soup,'code','')

Теперь всё в порядке: у нас есть только текст статьи, без внешнего обвеса, лишнего кода и ссылок. Можно переходить к массовой обработке.

Делаем парсер, чтобы массово тянуть с сайтов что угодно

Собираем функцию

У нас есть скрипт, который берёт одну конкретную ссылку, идёт по ней, чистит контент и получает очищенный текст. Сделаем из этого функцию — на вход она будет получать адрес страницы, а на выходе будет давать обработанный и очищенный текст. Это нам пригодится на следующем шаге, когда будем обрабатывать сразу много ссылок.

Если запустить этот скрипт, получим тот же результат, что и в предыдущем разделе.

# подключаем urlopen из модуля urllib from urllib.request import urlopen # подключаем библиотеку BeautifulSout from bs4 import BeautifulSoup # очищаем код от выбранных элементов def delete_div(code,tag,arg): # находим все указанные теги с параметрами for div in code.find_all(tag, arg): # и удаляем их из кода div.decompose() # очищаем текст по указанному адресу def clear_text(url): # получаем исходный код страницы inner_html_code = str(urlopen(url).read(),'utf-8') # отправляем исходный код страницы на обработку в библиотеку inner_soup = BeautifulSoup(inner_html_code, "html.parser") # оставляем только блок с содержимым статьи inner_soup = inner_soup.find('div', ) # удаляем титры delete_div(inner_soup, "div", ) # удаляем боковые ссылки delete_div(inner_soup, "div", ) # удаляем баннеры for i in range(11): delete_div(inner_soup, "div", ) # удаляем кат delete_div(inner_soup, "div", ) # удаляем преформатированный код delete_div(inner_soup, 'pre','') # удаляем вставки с кодом delete_div(inner_soup,'code','') # возвращаем содержимое страницы return(inner_soup.get_text()) print(clear_text('https://thecode.media/parsing/'))

Получаем адреса всех страниц

Одна из самых сложных вещей в парсинге — получить список адресов всех нужных страниц. Для этого можно использовать:

  • карту сайта,
  • внутренние рубрикаторы,
  • разделы на сайте,
  • готовые страницы со всеми ссылками.

В нашем случае мы воспользуемся готовой страницей — там собраны все статьи с разбивкой по рубрикам: https://thecode.media/all. Но даже в этом случае нам нужно написать код, который обработает эту страницу и заберёт оттуда только адреса статей. Ещё нужно предусмотреть, что нам не нужны ссылки из новостей и задач.

Идём в исходный код общей страницы и видим, что все ссылки лежат внутри списка:

Делаем парсер, чтобы массово тянуть с сайтов что угодно

При этом каждая категория статей лежит в своём разделе — именно это мы и будем использовать, чтобы обработать только нужные нам категории. Например, вот как рубрика «Ахах» выглядит на странице:

Делаем парсер, чтобы массово тянуть с сайтов что угодно

А вот она же — но в исходном коде. По названию легко понять, какой блок за неё отвечает:

Делаем парсер, чтобы массово тянуть с сайтов что угодно

Чтобы найти раздел в коде по атрибуту, используем команду find() с параметром attrs — в нём мы укажем название рубрики. А чтобы найти адрес в ссылке — используем команду select(), в которой укажем, что ссылка должна лежать внутри элемента списка.

Теперь логика будет такая:

  1. Создаём список с названиями нужных нам рубрик.
  2. Делаем функцию, куда будем передавать эти названия.
  3. Внутри функции находим рубрику по атрибуту.
  4. Перебираем все элементы списка со ссылками.
  5. Находим там адреса и записываем в переменную.
  6. Для проверки — выводим переменную с адресами на экран.
def get_all_url(data_title): html_code = str(urlopen('https://thecode.media/all').read(),'utf-8') soup = BeautifulSoup(html_code, "html.parser") # находим рубрику по атрибуту s = soup.find(attrs=) # тут будут все найденные адреса url = [] # перебираем все теги ссылок, которые есть в списке for tag in s.select("li:has(a)"): # добавляем адрес ссылки в нашу общую переменную url.append(tag.find("a")["href"]) # выводим найденные адреса print(url) # названия рубрик, которые нам нужны division = ['Ахах','Не стыдно','Это баг','Это как'] # перебираем все рубрики for el in division: # и обрабатываем каждую рубрику отдельно get_all_url(el)

Делаем парсер, чтобы массово тянуть с сайтов что угодно

На выходе у нас все адреса страниц из нужных рубрик. Теперь объединим обе функции и научим их сохранять текст в файл.

Сохраняем текст в файл

Единственное, чего нам сейчас не хватает, — это сохранения в файл. Чтобы каждая рубрика хранилась в своём файле, привяжем имя файла к названию рубрики. Дальше логика будет такая:

  1. Берём функцию get_all_url(), которая формирует список всех адресов для каждой рубрики.
  2. В конец этой функции добавляем команду создания файла с нужным названием.
  3. Открываем файл для записи.
  4. Перебираем в цикле все найденные адреса и тут же отправляем каждый адрес в функцию clear_text().
  5. Результат работы этой функции — готовый контент — записываем в файл и переходим к следующему.

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

# подключаем urlopen из модуля urllib from urllib.request import urlopen # подключаем библиотеку BeautifulSout from bs4 import BeautifulSoup # очищаем код от выбранных элементов def delete_div(code,tag,arg): # находим все указанные теги с параметрами for div in code.find_all(tag, arg): # и удаляем их из кода div.decompose() # очищаем текст по указанному адресу def clear_text(url): # получаем исходный код страницы inner_html_code = str(urlopen(url).read(),'utf-8') # отправляем исходный код страницы на обработку в библиотеку inner_soup = BeautifulSoup(inner_html_code, "html.parser") # оставляем только блок с содержимым статьи inner_soup = inner_soup.find('div', ) # удаляем титры delete_div(inner_soup, "div", ) # удаляем боковые ссылки delete_div(inner_soup, "div", ) # удаляем баннеры for i in range(11): delete_div(inner_soup, "div", ) # удаляем кат delete_div(inner_soup, "div", ) # удаляем преформатированный код delete_div(inner_soup, 'pre','') # удаляем вставки с кодом delete_div(inner_soup,'code','') # возвращаем содержимое страницы return(inner_soup.get_text()) # формируем список адресов для указанной рубрики def get_all_url(data_title): # считываем страницу со всеми адресами html_code = str(urlopen('https://thecode.media/all').read(),'utf-8') # отправляем исходный код страницы на обработку в библиотеку soup = BeautifulSoup(html_code, "html.parser") # находим рубрику по атрибуту s = soup.find(attrs=) # тут будут все найденные адреса url = [] # перебираем все теги ссылок, которые есть в списке for tag in s.select("li:has(a)"): # добавляем адрес ссылки в нашу общую переменную url.append(tag.find("a")["href"]) # имя файла для содержимого каждой рубрики content_file_name = data_title + '_content.txt' # открываем файл и стираем всё, что там было file = open(content_file_name, "w") # перебираем все адреса из списка for x in url: # сохраняем обработанный текст в файле и переносим курсор на новую строку file.write(clear_text(x) + '\n') # закрываем файл file.close() # названия рубрик, которые нам нужны division = ['Ахах','Не стыдно','Это баг','Это как'] # перебираем все рубрики for el in division: # и обрабатываем каждую рубрику отдельно get_all_url(el)

Делаем парсер, чтобы массово тянуть с сайтов что угодно

Что дальше

Теперь у нас есть все тексты всех статей. Как-нибудь проанализируем частотность слов в них (как в проекте с текстами Льва Толстого) или научим нейросеть писать новые статьи на основе старых.

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *