Оболочка Scrapy

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

Оболочка используется для тестирования выражений XPath или CSS, чтобы увидеть, как они работают и какие данные извлекают с веб-страниц, которые вы пытаетесь сканировать. Это позволяет вам в интерактивном режиме проверять свои выражения, пока вы пишете своего паука, без необходимости запускать паука для проверки каждого изменения.

Как только вы познакомитесь с оболочкой Scrapy, вы увидите, что это бесценный инструмент для разработки и отладки ваших пауков.

Настройка оболочки

Если у вас установлен IPython, оболочка Scrapy будет использовать его (вместо стандартной консоли Python). Консоль IPython намного мощнее и, помимо прочего, обеспечивает интеллектуальное автозаполнение и цветной вывод.

Мы настоятельно рекомендуем вам установить IPython, особенно если вы работаете в системах Unix (где IPython лучше всего). См. IPython руководство установки для получения дополнительной информации.

Scrapy также поддерживает bpython и попытается использовать его там, где IPython недоступен.

С помощью настроек Scrapy вы можете настроить его для использования любой из ipython, bpython или стандартной оболочки python, независимо от того, какие из них установлены. Это делается путём установки переменной окружения SCRAPY_PYTHON_SHELL; или определив его в вашем scrapy.cfg:

[settings]
shell = bpython

Запускаем оболочку

Чтобы запустить оболочку Scrapy, вы можете использовать команду shell, подобную этой:

scrapy shell <url>

Где <url> — это URL-адрес, который нужно сканировать.

shell также работает с локальными файлами. Это может быть удобно, если вы хотите поиграть с локальной копией веб-страницы. shell понимает следующие синтаксисы для локальных файлов:

# UNIX-style
scrapy shell ./path/to/file.html
scrapy shell ../other/path/to/file.html
scrapy shell /absolute/path/to/file.html

# File URI
scrapy shell file:///absolute/path/to/file.html

Примечание

При использовании относительных путей к файлам укажите их явно и добавить к ним ./ (или ../, если необходимо). scrapy shell index.html не будет работать так, как можно было бы ожидать (и это намеренно, а не ошибка).

Поскольку shell предпочитает URL-адреса HTTP вместо URI файлов, а index.html синтаксически похож на example.com, shell будет рассматривать index.html как имя домена и вызывать ошибку поиска DNS:

$ scrapy shell index.html
[ ... scrapy shell starts ... ]
[ ... traceback ... ]
twisted.internet.error.DNSLookupError: DNS lookup failed:
address 'index.html' not found: [Errno -5] No address associated with hostname.

shell не будет предварительно проверять, существует ли в текущем каталоге файл с именем index.html. Опять же, будьте осторожны.

Использование оболочки

Оболочка Scrapy — это обычная консоль Python (или консоль IPython, если она у вас есть), которая предоставляет некоторые дополнительные функции ярлыков для удобства.

Доступные ярлыки

  • shelp() — распечатать справку со списком доступных объектов и ярлыков

  • fetch(url[, redirect=True]) — получить новый ответ с заданного URL-адреса и соответствующим образом обновить все связанные объекты. При желании вы можете попросить, чтобы перенаправления HTTP 3xx не сопровождались передачей redirect=False

  • fetch(request) — получить новый ответ на данный запрос и соответствующим образом обновить все связанные объекты.

  • view(response) — открыть данный ответ в локальном веб-браузере для проверки. Это добавит <base> tag в тело ответа, чтобы внешние ссылки (например, изображения и таблицы стилей) отображались правильно. Обратите внимание, однако, что на вашем компьютере будет создан временный файл, который не будет удален автоматически.

Наличие Scrapy объектов

Оболочка Scrapy автоматически создаёт некоторые удобные объекты из загруженной страницы, такие как объект Response и объекты Selector (для содержимого как HTML, так и XML).

Данные объекты следующие:

  • crawler — текущий объект Crawler.

  • spider — паук, который, как известно, обрабатывает URL-адрес, или объект Spider, если для текущего URL-адреса не обнаружен паук

  • request — объект Request последней выбранной страницы. Вы можете изменить данный запрос с помощью replace() или получить новый запрос (не выходя из оболочки) с помощью ярлыка fetch.

  • response — объект Response, содержащий последнюю загруженную страницу

  • settings — текущая Scrapy настройка

Пример сеанса оболочки

Вот пример типичного сеанса оболочки, в котором мы начинаем с извлечения данных с домашней страницы scrapy, а затем переходим к сканированию страницы reddit. Наконец, мы модифицируем метод запроса (Reddit) на POST и повторно загружаем его, получая ошибку. Завершаем сеанс, набирая Ctrl-D (в системах Unix) или Ctrl-Z в Windows.

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

Сначала запускаем оболочку:

scrapy shell 'https://scrapy.org' --nolog

Примечание

Не забывайте всегда заключать URL-адреса в кавычки при запуске оболочки Scrapy из командной строки, иначе URL-адреса, содержащие аргументы (например, символ &), работать не будут.

В Windows используйте вместо этого двойные кавычки:

scrapy shell "https://scrapy.org" --nolog

Затем оболочка получает URL-адрес (с помощью загрузчика Scrapy) и распечатывает список доступных объектов и полезных ярлыков (вы заметите, что все данные строки начинаются с префикса [s]):

[s] Available Scrapy objects:
[s]   scrapy     scrapy module (contains scrapy.Request, scrapy.Selector, etc)
[s]   crawler    <scrapy.crawler.Crawler object at 0x7f07395dd690>
[s]   item       {}
[s]   request    <GET https://scrapy.org>
[s]   response   <200 https://scrapy.org/>
[s]   settings   <scrapy.settings.Settings object at 0x7f07395dd710>
[s]   spider     <DefaultSpider 'default' at 0x7f0735891690>
[s] Useful shortcuts:
[s]   fetch(url[, redirect=True]) Fetch URL and update local objects (by default, redirects are followed)
[s]   fetch(req)                  Fetch a scrapy.Request and update local objects
[s]   shelp()           Shell help (print this help)
[s]   view(response)    View response in a browser

>>>

После этого мы можем начать играть с объектами:

>>> response.xpath('//title/text()').get()
'Scrapy | A Fast and Powerful Scraping and Web Crawling Framework'
>>> fetch("https://old.reddit.com/")
>>> response.xpath('//title/text()').get()
'reddit: the front page of the internet'
>>> request = request.replace(method="POST")
>>> fetch(request)
>>> response.status
404
>>> from pprint import pprint
>>> pprint(response.headers)
{'Accept-Ranges': ['bytes'],
 'Cache-Control': ['max-age=0, must-revalidate'],
 'Content-Type': ['text/html; charset=UTF-8'],
 'Date': ['Thu, 08 Dec 2016 16:21:19 GMT'],
 'Server': ['snooserv'],
 'Set-Cookie': ['loid=KqNLou0V9SKMX4qb4n; Domain=reddit.com; Max-Age=63071999; Path=/; expires=Sat, 08-Dec-2018 16:21:19 GMT; secure',
                'loidcreated=2016-12-08T16%3A21%3A19.445Z; Domain=reddit.com; Max-Age=63071999; Path=/; expires=Sat, 08-Dec-2018 16:21:19 GMT; secure',
                'loid=vi0ZVe4NkxNWdlH7r7; Domain=reddit.com; Max-Age=63071999; Path=/; expires=Sat, 08-Dec-2018 16:21:19 GMT; secure',
                'loidcreated=2016-12-08T16%3A21%3A19.459Z; Domain=reddit.com; Max-Age=63071999; Path=/; expires=Sat, 08-Dec-2018 16:21:19 GMT; secure'],
 'Vary': ['accept-encoding'],
 'Via': ['1.1 varnish'],
 'X-Cache': ['MISS'],
 'X-Cache-Hits': ['0'],
 'X-Content-Type-Options': ['nosniff'],
 'X-Frame-Options': ['SAMEORIGIN'],
 'X-Moose': ['majestic'],
 'X-Served-By': ['cache-cdg8730-CDG'],
 'X-Timer': ['S1481214079.394283,VS0,VE159'],
 'X-Ua-Compatible': ['IE=edge'],
 'X-Xss-Protection': ['1; mode=block']}

Вызов оболочки от пауков для проверки ответов

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

Этого можно добиться с помощью функции scrapy.shell.inspect_response.

Вот пример того, как вы бы назвали это через своего паука:

import scrapy


class MySpider(scrapy.Spider):
    name = "myspider"
    start_urls = [
        "http://example.com",
        "http://example.org",
        "http://example.net",
    ]

    def parse(self, response):
        # We want to inspect one specific response.
        if ".org" in response.url:
            from scrapy.shell import inspect_response
            inspect_response(response, self)

        # Rest of parsing code.

Когда вы запустить паука, вы получить нечто похожее на это:

2014-01-23 17:48:31-0400 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://example.com> (referer: None)
2014-01-23 17:48:31-0400 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://example.org> (referer: None)
[s] Available Scrapy objects:
[s]   crawler    <scrapy.crawler.Crawler object at 0x1e16b50>
...

>>> response.url
'http://example.org'

Затем вы можете проверить, работает ли код извлечения:

>>> response.xpath('//h1[@class="fn"]')
[]

Нет, это не так. Таким образом, вы можете открыть ответ в своём веб-браузере и посмотреть, ожидали ли вы этого ответа:

>>> view(response)
True

Наконец, вы нажимаете Ctrl-D (или Ctrl-Z в Windows), чтобы выйти из оболочки и возобновить сканирование:

>>> ^D
2014-01-23 17:50:03-0400 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://example.net> (referer: None)
...

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