scrapy实用技巧

在使用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 动态调试和启动多爬虫

参见我之前的一篇文章

... ...

你可能感兴趣的:(scrapy实用技巧)