Время прочтения: 7 мин.
Перед группой программистов была поставлена задача создать сервис для накопления информации об упоминании публичных персон в новостных интернет-порталах (далее сервис):
Что должен видеть пользователь сервиса: интернет ресурс, на котором можно запустить «Просмотр общей статистики».
В результате запуска отображается информация в виде таблицы с полями: «Имя персоны», «Количество упоминаний», «Название статей, Даты статьи».
На основе полученного задания было решено реализовать сервис, состоящий из следующих компонент:
Также пользователь может запустить просмотр /поиск статистики по конкретной персоне.
Таким образом, если информация по запросу на поиск пользователя уже имеется в базе данных, то ответ будет сформирован сразу и выведен в составе «Просмотра общей статистики», если же информация по запросу в базе данных отсутствует, то будет сформировано задание для crawler, обработанная информация с которого будет занесена в базу данных, откуда и будет сформирован ответ пользователю.
[1] crawler (обходчик) — служба, которая по определенному расписанию, или принудительно, обращается к сайтам в интернете. Анализирует их на наличие новых страниц. Загружает новые страницы, после чего обрабатывает контент новой страницы. Результаты обработки и ссылку на новую страницу записывает в Базу Данных. Результатом обработки является количество упоминаний имен политиков на странице сайта.
Наша группа разделилась на 2 большие подгруппы:
- программирование сервиса на Java;
- программирование сервиса на Python.
Далее внутри групп было произведено деление по программированию компонент.
Группе, в которую попал и я, была поручена разработка crawler на Python и пробный новостной сайт “lenta.ru”.
Для поиска данных на html страницах web сайтов можно использовать различные библиотеки Python, например: Scrapy, Selenium, Beautiful Soup.
Scrapy — это готовая платформа для поиска данных с веб-сайтов, которая работает без блокировки отправленных запросов, самая быстрая и надежная, особенно при создании сложных проектов.
Selenium используется для тестирования веб-приложений.
Beautiful Soup — быстро извлекает данные из скачанных (локальных или в память компьютера) файлов HTML и XML.
Выбрана была библиотека Beautiful Soup вследствие не высокой сложности нашего проекта.
Установим Beautiful Soup на компьютер:
pip3 install bs4 - для Windows;
sudo pip3 install bs4 – для Ubuntu, Centos.
В отличии от Scrappy, Beautiful Soup не может напрямую просматривать страницы Web сайтов, поэтому еще необходимо поставить библиотеку requests, которая работает с http – запросами:
pip3 install requests - для Windows;
sudo pip3 install requests – для Ubuntu, Centos.
По заданию на вход crawler должны быть поданы следующие параметры: персона, дата статей, на выходе название статей, количество упоминаний персоны. По входным и выходным данным в базу будут произведены записи: дата найденных статей, персона, название статей, количество упоминаний персоны.
Разделим наше задание на несколько этапов:
- Определение страниц/разделов в lenta.ru, в которых будет производится поиск статей;
- Открытие указанных страниц/разделов в lenta.ru за конкретную дату;
- Получение данных с указанных страниц/разделов в lenta.ru;
- Формализация данных поиска (персоны и даты);
- Поиск персоны в статьях с указанных страниц/разделов в lenta.ru за конкретную дату;
- Передача данных в базу данных сервиса в json — формате {‘гиперссылка на статью’: Количество упоминаний}.
Определение страниц/разделов в lenta.ru, в которых будет производится поиск статей.
Любой серьезный сайт публикует карту своего сайта в файле robots.txt, для того чтобы было видно куда разрешено роботам спокойно заходить и смотреть страницы и/или указать файл карты сайта. Обычно это sitemap.xml или sitemap.xml.gz
У новостного сайта lenta.ru карта сайта описана в файле https://lenta.ru/sitemap.xml.gz
Проведя анализ данного файла, был сделан вывод: основные папки статей: news, articles.
Открытие указанных страниц/разделов в lenta.ru за конкретную дату
Пример кода открытия страницы с помощью requests:
import requests
year = “2018”
may = “06”
day = “28”
main_url = 'https://lenta.ru'
them = 'news'
url = "%s/%s/%s/%s/%s/" % (main_url, them, year, may, day)
r = requests.get(url)
page = r.text
print(page)
(в блоках добавлена функция print (), чтобы можно было увидеть результат работы кода)
Так как страниц/разделов может быть несколько, немного модифицируем наш код (этот код используйте только в составе класса[1])
import requests
year = “2018”
may = “06”
day = “28”
main_url = 'https://lenta.ru'
thems = ('news', 'articles')
for them in thems:
url = "%s/%s/%s/%s/%s/" % (main_url, them, year, may, day)
r = requests.get(url)
page = r.text
print(page)
Получение данных с указанных страниц/разделов в lenta.ru
Для получения данных о статьях необходимо определить в каких тегах они закреплены.
Проведя анализ полученной страницы, можно сделать вывод:
— статьи на этой странице ограничены тегами:
div class=”row”; div class=”titles”.
На основании этих ограничений прочитаем выгруженную страницу с помощью Beautyful Soup и сохраним все гиперссылки на статьи в список.
import requests
from bs4 import BeautifulSoup
#…….. здесь предыдущий код
newlinks = []
soup = BeautifulSoup(page, 'lxml')
link_block = soup.find_all('div', class_='row')
for blocks in link_block:
if blocks.find_all('div', class_='titles'):
for block in blocks.find_all('div', class_='titles'):
newlinks.append("%s%s" % (main_url, block.find('a').get('href')))
print(newlinks)
Так выглядит список статей:
Формализация данных поиска (персоны и даты)
У нас есть список статей и осталось провести поиск искомой персоны. Имеется немало разных библиотек, с помощью которых можно задать правильный поиск по Фамилии Имени Отчеству.
Немного упростим задачу, будем искать только по фамилии персоны, для этого напишем следующий код:
name = 'Меркель'
if (name[-2:] == 'ая' or name[-2:] == 'яя' or name[-2:] == 'ий' or name[-2:] == 'ой' \
or name[-2:] == 'ый' or name[-2:] == 'ая') and len(name) > 4:
newname = name[:-2]
elif name[-1:] == 'а' or name[-1:] == 'ь' or name[-1:] == 'й' and len(name) > 4:
newname = name[:-1]
else:
newname = name
print(newname)
Если вы заметили, то дата в коде написана в виде
url = "%s/%s/%s/%s/%s/" % (main_url, them, year, may, day)..
То есть необходимо распарсить входящую дату, что будет сделано с помощью кода:
date = "26.06.2018"
year = date.split(".")[2]
may = date.split(".")[1]
day = date.split(".")[0]
И необходимо вставить эти 2 фрагмента кода выше блока «Открытие указанных страниц/разделов в lenta.ru за конкретную дату».
Поиск персоны в статьях с указанных страниц/разделов в lenta.ru за конкретную дату
С помощью requests открываем статьи, указанные в списке newlinks, будем искать и считать количество упоминаний нашей персоны в каждой статье с помощью Beautyful Soup.
pages_name ={}
for url in newlinks:
page = requests.get(url)
soup = BeautifulSoup(page.text, 'lxml')
link_block = soup.find_all('div', class_='b-topic__content')
page_count = str(link_block).count(newname)
if page_count > 0:
pages_name[url] = page_count
print(pages_name)
Передача данных в базу данных сервиса в json — формате {‘гиперссылка на статью’: Количество упоминаний}
На выходе:
{‘https://lenta.ru/articles/2018/06/25/merkel_i_ee_problemi/’: 21}
Была найдена 1 статья с 21 упоминанием персоны Меркель.
Вот и всё. Как видите ничего сложного. Весь указанный код, объединенный в класс, выложен на https://github.com/IldarVS/crawler
Что можно почитать по парсингу сайтов:
1. Python: Scrapy, Selenium, Beautiful Soup что лучше для парсинга веб сайтов