在使用scrapy过程中总结了一些小技巧,在此分享出来供大家参考。
用 LinkExtractor 收取链接
以 http://www.hao123.com/sitemap 为例子:
在shell中运行
scrapy shell http://www.hao123.com/sitemap
进入shell调试模式,我们来看看使用linkextractors的效果
>>> from scrapy.linkextractors import LinkExtractor
>>> links = LinkExtractor(allow=(), restrict_xpaths=('//a[@class="link"]')).extract_links(response)
>>> len(links)
113
>>> for link in links[:10]:
... print(link.text.replace('\n',''),':',link.url)
...
天气 : http://tianqi.hao123.com/
万年历 : http://www.hao123.com/rili
地图 : http://www.hao123.com/map
查询 : http://life.hao123.com/info
生活 : http://www.hao123.com/shenghuo
hao到家 : http://life.hao123.com/
美食菜谱 : http://www.hao123.com/menu
特价 : http://tejia.hao123.com/?tn=kztj
购物 : http://gouwu.hao123.com/
团购 : https://www.nuomi.com/?utm_source=hao123&utm_medium=channel_midright&cid=001606
利用Xpath,可以很方便的获取到链接的文本和URL
命令行调试代码
from scrapy.shell import inspect_response
inspect_response(response, self)
在需要调试的地方插入此代码,程序运行过程中会停在该处,如:
2018-05-28 10:29:14 [scrapy.core.engine] INFO: Spider opened
2018-05-28 10:29:14 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
[s] Available Scrapy objects:
>>> [s] scrapy scrapy module (contains scrapy.Request, scrapy.Selector, etc)
[s] crawler
[s] item {}
[s] request
[s] response <200 https://movie.douban.com/chart>
[s] settings
[s] spider
[s] Useful shortcuts:
[s] shelp() Shell help (print this help)
[s] view(response) View response in a browser
>>>
此时可以针对返回的response
进行调试工作。
重写 start_requests 方法
我们知道在编写spider的时候都有一个初始URL列表,也即start_urls
,如下:
import scrapy
class StackOverflowSpider(scrapy.Spider):
name = 'stackoverflow'
start_urls = ['http://stackoverflow.com/questions?sort=votes']
def parse(self, response):
for href in response.css('.question-summary h3 a::attr(href)'):
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()[0],
'votes': response.css('.question .vote-count-post::text').extract()[0],
'body': response.css('.question .post-text').extract()[0],
'tags': response.css('.question .post-tag::text').extract(),
'link': response.url,
}
但有时我们希望灵活的把初始URL分配给不同的回调函数,这时我们可以重写Spider
类的start_requests
方法:
def start_requests(self):
ershoufang = "https://nj.5i5j.com/ershoufang/o6/"
zufang = "https://nj.5i5j.com/zufang/o6/"
yield Request(ershoufang, callback=self.parse_ershoufang,dont_filter = True)
yield Request(zufang, callback=self.parse_zufang,dont_filter = True)
当然你还可以基于这个方法做一个URL和parse的映射,这样就可以在一个爬虫下处理不同类型的页面。
Request.meta 特殊键
Request.meta
属性可以包含任何任意数据,也就意味着除了Scrapy
及其内置扩展的一些特殊键,我们可以自定义一些对我们有用的键用于在请求和响应间传递,拿官方示例的 cookiejar
来说。
Scrapy通过使用 cookiejar Request meta key来支持单spider追踪多cookie session。 默认情况下其使用一个cookie jar(session),不过您可以传递一个标示符来使用多个。
例如:
for i, url in enumerate(urls):
yield scrapy.Request("http://www.example.com", meta={'cookiejar': i},
callback=self.parse_page)
需要注意的是 cookiejar meta key不是”黏性的(sticky)”。 您需要在之后的request请求中接着传递。例如:
def parse_page(self, response):
# do some processing
return scrapy.Request("http://www.example.com/otherpage",
meta={'cookiejar': response.meta['cookiejar']},
callback=self.parse_other_page)
具体如何使用,就看你的想象力啦。
给请求添加代理(中间件)
爬虫不可避免的需要使用代理,我们通过下载器中间件,截获发出的请求把代理信息添加进去。
以阿布云为例,首先我们需要编辑项目下的middlewares.py
文件,新建一个代理中间件类:
import base64
# 代理服务器
proxyServer = "http://http-dyn.abuyun.com:9020"
# 代理隧道验证信息
proxyUser = "H01234567890123D"
proxyPass = "0123456789012345"
# for Python2
# proxyAuth = "Basic " + base64.b64encode(proxyUser + ":" + proxyPass)
# for Python3
proxyAuth = "Basic " + base64.urlsafe_b64encode(bytes((proxyUser + ":" + proxyPass), "ascii")).decode("utf-8")
class ProxyMiddleware(object):
def process_request(self, request, spider):
request.meta["proxy"] = proxyServer
request.headers["Proxy-Authorization"] = proxyAuth
在重写的process_request
方法中,我们将必要的信息添加给即将发出的request。
然后我们还需要在 settings.py
文件中使能我们自定义的代理中间件:
# Enable or disable downloader middlewares
# See http://scrapy.readthedocs.org/en/latest/topics/downloader-middleware.html
DOWNLOADER_MIDDLEWARES = {
'myproject.middlewares.ProxyMiddleware': 543,
}
这样我们发出的请求scrapy就会自动为我们添加代理信息了。
Scrapy 动态调试和启动多爬虫
参见我之前的一篇文章