Парсинг сайтов c помощью Python


Веб-скрапинг - неотъемлемая часть исследователя и программиста, заключающаяся в извлечении данных из веб-ресурса, синтаксического разбора и преобразование в определенный формат (txt, csv, json). На основе этих данных можно проводить определенные исследования, проводить анализ данных и визуализацию - на примере разработчика одного российского ПО: 
Извлекаются данные из социальных сетей определенных людей, с кем они дружат, в каких группах состоят, что чаще комментируют и лайкают. На основе этих данных, используя различные алгоритмы и машинное обучения удается выявлять и предотвращать экстремизм и радикализм, также выявлять группы социальных рисков.   

Самыми популярными инструментами для парсинга данных в Python являются:
  • Beautiful Soup
  • Scrapy
Сравним эти два модуля:

Beautiful Soup

+Легко использовать

-При большом парсинге данных, может просесть перформанс 
-Нужно использовать сторонние компоненты (requests, logging)

Scrapy

+Все в одном модуле, после установки готов к работе
+Тонкая настройка (Proxy, User-agent, HTTP заголовки итд)
+Хорошее Логгирование

-Сложный в понимании
-Много зависимостей, которые могут вызвать проблемы при установке
-Работает отдельным модулем, из-за этого при разработке нельзя использовать отладку (breakpoint)
-При конфигурировании настроек начинаются танцы с бубном



Пример BS: Получим курс валют с сайта нац. банка РФ

from bs4 import BeautifulSoup
import requests


corp_proxy_1 = "http://user:pass@host:port"
corp_proxy_2 = "https://user:pass@host:port"

proxyDict = {"http"  : corp_proxy_1,
             "https" : corp_proxy_2
                } 

#*****Используем user agent заголовок*****************************
user_agent = {'User-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.117 Safari/537.36'}

#*****Отключаем HTTPS warnings*****************************


import urllib3
urllib3.disable_warnings()


#Отправляем запрос с заголовками


try:
    r = requests.get('http://www.cbr.ru', headers = user_agent, proxies=proxyDict, )
except:
    pass

if r.status_code == 200: #Если все хорошо
    try:
            #Готовим суп
            b = BeautifulSoup(r.content,'html.parser')

            #Находим нужный слой -> талица -> все row

            tr = b.find('div', {'id':'widget_exchange'}).find('table').find_all('tr')

            #Извлекаем нужные данные
            US =   tr[1].get_text().strip().split(' ')[2].replace('\n', '').replace(u'\xa0', u' ')


            #Избавляемся от ненужных символов
            today = (US.split(' ')[1]).replace('руб.','')
            yes =  (US.split(' ')[2])[1:]

            print(yes)
            print(today)

            #Если что-то пошло не так
    except Exception as e:

        print('Parsing error {0}'.format(e))





Курс валют на 11.11.2018














Пример c Scrapy:

Создадим новый проект в папке Project:

> scrapy startproject FinSpider E:\Project

Перейдем в папку E:\Project\FinSpider\Spiders и создадим файл: FinSpider.py




Сам проект и файлы выглядят так:



Добавим код в FinSpider.py:

import scrapy

#Наследуем класс от spider
class FinSpider(scrapy.Spider):
    name = "FinSpider"   #Название нашего паука
    start_urls = [       #Список урлов для обхода пауком  
        'http://www.cbr.ru',
    ]

    #
    def parse(self, response):
        page = response.xpath('//div[@id="widget_exchange"]//table//tr//td//text()')
        US = page.extract() #Извлекаем данные

        #Убираем все лишнее
        US = ''.join([b.replace('\r\n', '').replace(' ''') for b in US]).split()

        #Оставляем первые 7 знаков используя срезы, ох уж этот мусор в тексте
        Yes  =  str(US[1])[:7]     
        Today = str(US[2])[1:7]

        print(Yes)
        print(Today)



Запустим:

>scrapy crawl FinSpider --nolog   *(--nolog без вывода отладочной информации)



Кода на BS вышло больше, ввиду того что запросы нужно реализовать самому. Для предотвращения блокировки робота рекомендуется использовать несколько прокси, указывать HTTP заголовки (некоторые сайты отказываются отдавать контент без user-agent или referrer) и не сильно нагружать сервер.







Комментарии