我们在 Scrapy 的 shell 中展示如何从网页提取数据:
scrapy shell "http://quotes.toscrape.com/page/1/"
注意:windows 系统下 url 需要用双引号。
你会看到这样的输出:
2017-06-14 21:26:03 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://quotes.toscrape.com/page/1/> (referer: None)
[s] Available Scrapy objects:
[s] scrapy scrapy module (contains scrapy.Request, scrapy.Selector, etc)
[s] crawler <scrapy.crawler.Crawler object at 0x01047E90>
[s] item {}
[s] request <GET http://quotes.toscrape.com/page/1/>
[s] response <200 http://quotes.toscrape.com/page/1/>
[s] settings <scrapy.settings.Settings object at 0x0427C310>
[s] spider <DefaultSpider 'default' at 0x4e43af0>
[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
>>>
下面我们在 shell 里面利用 css 选择器来提取网页的数据:
>>> response.css('title')
[<Selector xpath='descendant-or-self::title' data='<title>Quotes to Scrape</title>'>]
执行上述命令将会返回一个类似列表的对象:SelectorList
;这是由选择器根据提取规则提取出来的 XML/HTML 元素,你可以对它进一步细分或提取。
要提取 <title>
标签里面的内容,可以这样:
>>> response.css('title::text').extract()
['Quotes to Scrape']
在 css 选择器表达式中使用 ::text
,可以提取标签的内容,如果不使用,结果如下:
>>> response.css('title').extract()
['<title>Quotes to Scrape</title>']
.extract()
方法会根据 SelectorList 内容返回一个列表,如果我们只需要返回列表中第一个元素,或者知道列表中只存在一个元素,可以这样写:
>>> response.css('title::text').extract_first()
'Quotes to Scrape'
又或者,可以用列表切片的方式:
>>> response.css('title::text')[0].extract()
'Quotes to Scrape'
但我们还是建议采用 .extract_first()
,这样可以避免要提取的元素为空的时候发生 IndexError
。
除了上述方法外,我们还可以用正则表达式提取元素,用 re()
方法即可:
>>> response.css('title::text').re(r'Quotes.*')
['Quotes to Scrape']
>>> response.css('title::text').re(r'Q\w+')
['Quotes']
>>> response.css('title::text').re(r'(\w+) to (\w+)')
['Quotes', 'Scrape']
Scrapy 还能用 Xpath
来提取内容:
>>> response.xpath('//title')
[<Selector xpath='//title' data='<title>Quotes to Scrape</title>'>]
>>> response.xpath('//title/text()').extract_first()
'Quotes to Scrape'