Оболочка 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 заблокирован оболочкой. Однако после того, как вы покинете шелл, паук продолжит ползать с того места, где он остановился, как показано выше.