Python LanguageВеб-скребок с Python

Вступление

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

замечания

Полезные пакеты Python для веб-соскабливания (в алфавитном порядке)

Выполнение запросов и сбор данных

requests

Простой, но мощный пакет для создания HTTP-запросов.

requests-cache

Кэширование requests ; данные кэширования очень полезны. В разработке это означает, что вы можете без необходимости удалять сайт. При запуске реальной коллекции это означает, что если ваш скребок сработает по какой-то причине (возможно, вы не обрабатывали какой-то необычный контент на сайте ...? Возможно, сайт опустился ...?), Вы можете очень быстро повторить сбор откуда вы остановились.

scrapy

Полезно для создания веб-сканеров, где вам нужно что-то более мощное, чем использование requests и итерация по страницам.

selenium

Python для Selenium WebDriver для автоматизации браузера. Использование requests для прямого HTTP-запроса часто бывает проще для получения веб-страниц. Однако это остается полезным инструментом, когда невозможно воспроизвести желаемое поведение сайта с использованием только requests , особенно когда JavaScript требуется для отображения элементов на странице.

Разбор HTML

BeautifulSoup

Запросить HTML и XML-документы, используя ряд различных парсеров (встроенный HTML-анализатор html5lib , lxml , lxml или lxml.html )

lxml

Процессы HTML и XML. Может использоваться для запроса и выбора содержимого из HTML-документов с помощью селекторов CSS и XPath.

Основной пример использования запросов и lxml для очистки некоторых данных

# For Python 2 compatibility.
from __future__ import print_function

import lxml.html
import requests


def main():
    r = requests.get("https://httpbin.org")
    html_source = r.text
    root_element = lxml.html.fromstring(html_source)
    # Note root_element.xpath() gives a *list* of results.
    # XPath specifies a path to the element we want.
    page_title = root_element.xpath('/html/head/title/text()')[0]
    print(page_title)

if __name__ == '__main__':
    main()

Ведение сеанса веб-очистки с запросами

Рекомендуется сохранять сеанс веб-очистки для сохранения файлов cookie и других параметров. Кроме того, это может привести в повышению производительности , так как requests.Session повторно использует ТСР - соединение с узлом:

import requests

with requests.Session() as session:
    # all requests through session now have User-Agent header set
    session.headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'}

    # set cookies
    session.get('http://httpbin.org/cookies/set?key=value')

    # get cookies
    response = session.get('http://httpbin.org/cookies')
    print(response.text)

Скребок с использованием схемы Scrapy

Сначала вам нужно создать новый проект Scrapy. Введите каталог, в котором вы хотите сохранить код и выполните его:

scrapy startproject projectName

Чтобы очистить, нам нужен паук. Пауки определяют, как будет очищаться определенный сайт. Вот код для паука, который следует за ссылками на верхние голосовые вопросы по StackOverflow и сбрасывает некоторые данные с каждой страницы ( источник ):

import scrapy

class StackOverflowSpider(scrapy.Spider):
    name = 'stackoverflow'  # each spider has a unique name
    start_urls = ['http://stackoverflow.com/questions?sort=votes']  # the parsing starts from a specific set of urls

    def parse(self, response):  # for each request this generator yields, its response is sent to parse_question
        for href in response.css('.question-summary h3 a::attr(href)'):  # do some scraping stuff using css selectors to find question urls 
            full_url = response.urljoin(href.extract())
            yield scrapy.Request(full_url, callback=self.parse_question)

    def parse_question(self, response): 
        yield {
            'title': response.css('h1 a::text').extract_first(),
            'votes': response.css('.question .vote-count-post::text').extract_first(),
            'body': response.css('.question .post-text').extract_first(),
            'tags': response.css('.question .post-tag::text').extract(),
            'link': response.url,
        }

Сохраните свои классы projectName\spiders каталоге projectName\spiders . В этом случае - projectName\spiders\stackoverflow_spider.py .

Теперь вы можете использовать своего паука. Например, попробуйте запустить (в каталоге проекта):

scrapy crawl stackoverflow

Изменить пользовательский агент Scrapy

Иногда пользовательский агент "Scrapy/VERSION (+http://scrapy.org)" по умолчанию ( "Scrapy/VERSION (+http://scrapy.org)" ) блокируется хостом. Чтобы изменить пользовательский агент по умолчанию, откройте settings.py , раскомментируйте и отредактируйте следующую строку, что бы вы ни пожелали.

#USER_AGENT = 'projectName (+http://www.yourdomain.com)'

Например

USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'

Скребок с использованием BeautifulSoup4

from bs4 import BeautifulSoup
import requests

# Use the requests module to obtain a page
res = requests.get('https://www.codechef.com/problems/easy')

# Create a BeautifulSoup object
page = BeautifulSoup(res.text, 'lxml')   # the text field contains the source of the page

# Now use a CSS selector in order to get the table containing the list of problems
datatable_tags = page.select('table.dataTable')  # The problems are in the <table> tag,
                                                 # with class "dataTable"
# We extract the first tag from the list, since that's what we desire
datatable = datatable_tags[0]
# Now since we want problem names, they are contained in <b> tags, which are
# directly nested under <a> tags
prob_tags = datatable.select('a > b')
prob_names = [tag.getText().strip() for tag in prob_tags]

print prob_names

Скребок с использованием Selenium WebDriver

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

from selenium import webdriver

browser = webdriver.Firefox()  # launch firefox browser

browser.get('http://stackoverflow.com/questions?sort=votes')  # load url

title = browser.find_element_by_css_selector('h1').text  # page title (first h1 element)

questions = browser.find_elements_by_css_selector('.question-summary')  # question list

for question in questions:  # iterate over questions
    question_title = question.find_element_by_css_selector('.summary h3 a').text
    question_excerpt = question.find_element_by_css_selector('.summary .excerpt').text
    question_vote = question.find_element_by_css_selector('.stats .vote .votes .vote-count-post').text
    
    print "%s\n%s\n%s votes\n-----------\n" % (question_title, question_excerpt, question_vote) 

Селен может сделать гораздо больше. Он может изменять файлы cookie браузера, заполнять формы, имитировать щелчки мыши, делать скриншоты веб-страниц и запускать собственный JavaScript.

Простая загрузка веб-контента с помощью urllib.request

Стандартный библиотечный модуль urllib.request можно использовать для загрузки веб-контента:

from urllib.request import urlopen

response = urlopen('http://stackoverflow.com/questions?sort=votes')    
data = response.read()

# The received bytes should usually be decoded according the response's character set
encoding = response.info().get_content_charset()
html = data.decode(encoding)

Аналогичный модуль также доступен в Python 2 .

Скребок с завитом

импорт:

from subprocess import Popen, PIPE
from lxml import etree
from io import StringIO

Загрузка:

user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36'
url = 'http://stackoverflow.com'
get = Popen(['curl', '-s', '-A', user_agent, url], stdout=PIPE)
result = get.stdout.read().decode('utf8')

-s : silent скачать

-A : флаг агента пользователя

Синтаксический:

tree = etree.parse(StringIO(result), etree.HTMLParser())
divs = tree.xpath('//div')