爬虫 Scrapy 学习系列十七:Debugging Spiders

前言

这是 Scrapy 系列学习文章之一,本章主要介绍 Debugging Spiders 的相关的内容;

本文为作者的原创作品,转载需注明出处;

简介

本博文将归纳出相关的技术用来调试我们的 Spiders,假设,我们有如下的一个 Spider 的模板样例,看看,我们将会有什么样的手段来对这些 Spider 进行调试;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import scrapy
from myproject.items import MyItem

class MySpider(scrapy.Spider):
name = 'myspider'
start_urls = (
'http://example.com/page1',
'http://example.com/page2',
)

def parse(self, response):
# collect `item_urls`
for item_url in item_urls:
yield scrapy.Request(item_url, self.parse_item)

def parse_item(self, response):
item = MyItem()
# populate `item` fields
# and extract item_details_url
yield scrapy.Request(item_details_url, self.parse_details, meta={'item': item})

def parse_details(self, response):
item = response.meta['item']
# populate more `item` fields
return item

注意,该 Spider 并不是一个完整的 Spider,里面通过模拟对 start_urls 进行爬取;从 parse_item() 初步解析得到了相关的 Item,然后通过 meta 将该 Item 作为参数传递给 parse_details() 参数进一步爬取并解析;

Parse Command

用来检测 spider 输出的最基本方法是使用 parse 命令;它允许在方法级别去检测 spider 不同部分的行为;但是它不允许对方法内部的代码进行调试;注意,该命令主要是用来检测 spider 输出的;看下面的描述,

查看从特定的 url 中所爬取得到的 item 信息;

1
2
3
4
5
6
7
8
9
$ scrapy parse --spider=myspider -c parse_item -d 2 <item_url>
[ ... scrapy log lines crawling example.com spider ... ]

>>> STATUS DEPTH LEVEL 2 <<<
# Scraped Items ------------------------------------------------------------
[{'url': <item_url>}]

# Requests -----------------------------------------------------------------
[]

上述演示的只是一个模拟的调用输出,可以看到,通过参数 -d 2 表示的是显示爬取所得到的第二层的相关信息;

通过使用--verbose或者-v选项,我们可以看到每一层的信息,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ scrapy parse --spider=myspider -c parse_item -d 2 -v <item_url>
[ ... scrapy log lines crawling example.com spider ... ]

>>> DEPTH LEVEL: 1 <<<
# Scraped Items ------------------------------------------------------------
[]

# Requests -----------------------------------------------------------------
[<GET item_details_url>]


>>> DEPTH LEVEL: 2 <<<
# Scraped Items ------------------------------------------------------------
[{'url': <item_url>}]

# Requests -----------------------------------------------------------------
[]

检测从一个单独的 start_url 所爬去得到的 items,可以使用如下的方式,

1
$ scrapy parse --spider=myspider -d 3 'http://example.com/page1'

Scrapy Shell

通过 Parse Command 可以检测到 parse 方法的解析输出,但是,怎样去深入调试 parse 方法中的某一个分支呢?比如说,解析的时候,有时候并没有数据返回的情况?

1
2
3
4
5
6
7
8
9
from scrapy.shell import inspect_response

def parse_details(self, response):
item = response.meta.get('item', None)
if item:
# populate more `item` fields
return item
else:
inspect_response(response, self)

具体的测试用例参考从 Spider 中启动 Scrapy Shell 来检查 response

Open in browser

有时候想用 web browser 来可视化的查看 response,可以使用open_in_browser方法;

1
2
3
4
5
from scrapy.utils.response import open_in_browser

def parse_details(self, response):
if "item name" not in response.body:
open_in_browser(response)

open_in_browser will open a browser with the response received by Scrapy at that point, adjusting the base tag so that images and styles are displayed properly.

Logging

1
2
3
4
5
6
7
def parse_details(self, response):
item = response.meta.get('item', None)
if item:
# populate more `item` fields
return item
else:
self.logger.warning('No item received for %s', response.url)

TODO

写一个真是的用例来验证本章的内容;