博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
zg手册 之 scrapy 开发(5)-- downloader(下载器)开发
阅读量:6857 次
发布时间:2019-06-26

本文共 4995 字,大约阅读时间需要 16 分钟。

  hot3.png

为什么需要开发下载器

  1. 定向抓取时,目标站点的数据不能单次请求获取,需要3,4次或者更多,请求之间有依赖关系,就是需要连续请求完成这个下载事物

  2. 前面讲过的 js 动态页面下载

  3. ......

注意事项

  1. 下载器的不可以影响 twisted 框架本身的异步机制

  2. 与 scrapy 原有的下载器调用接口一致,符合插件规范

  3. 其他插件依赖的状态要保留

下载器开发代码(我把注意的地方直接写在代码中,方便查看)

1. 新建项目

# 创建项目scrapy startproject jstest# 创建蜘蛛scrapy genspider -t basic testSpider 'sina.com.cn'

2. 修改蜘蛛文件 testSpider.py

from scrapy.spider import Spiderclass TestspiderSpider(Spider):    name = "testSpider"    allowed_domains = ["sina.com.cn"]    start_urls = (        'http://www.sina.com.cn/',        )    def parse(self, response):        print response.body        print 'download_latency:', response.meta['download_latency']

3. 创建 jstest/handler 目录,新建文件 mydownloader.py

参照 /usr/local/lib/python2.7/dist-packages/scrapy/core/downloader/handlers/http11.py 文件

#!/usr/bin/env python# encoding: utf-8import refrom time import timefrom cStringIO import StringIOfrom urlparse import urldefragfrom zope.interface import implementsfrom twisted.internet import defer, reactor, protocolfrom twisted.web.http_headers import Headers as TxHeadersfrom twisted.web.iweb import IBodyProducerfrom twisted.internet.error import TimeoutErrorfrom twisted.web.http import PotentialDataLossfrom scrapy.xlib.tx import Agent, ProxyAgent, ResponseDone, HTTPConnectionPool, TCP4ClientEndpointfrom scrapy.http import Headersfrom scrapy.responsetypes import responsetypesfrom scrapy.core.downloader.webclient import _parsefrom scrapy.utils.misc import load_objectfrom scrapy.http import HtmlResponsefrom twisted.internet import utilsclass MyLogicDownloader(object):    '''    定制下载逻辑    '''    def __init__(self, agent=None):        '''agent: 异步下载代理'''        self._agent = agent    def download(self, request):        '''        需要异步返回,不可以阻塞,本例子的演示直接调用 phantomjs的一个简单包装脚本	'''        begintime = time()        d = self._download(request)        d.addCallback(self.parseData, request, begintime)        print '证明我是异步的'        return d    def _download(self, request):        '''使用twsited 的函数创建异步进程调用'''        d = utils.getProcessOutput('scrapyweb.js', args=(request.url, '24000'), reactor=reactor)        def getOutput(result):            return result        d.addCallback(getOutput)        return d    def parseData(self, htmldoc, request, begintime):        '''解析函数,当请求完成后被调用'''        # 这个下载时间在调整下载速度的扩展 AutoThrottle 中被使用        request.meta['download_latency'] = time() - begintime        return HtmlResponse(request.url, body=htmldoc + '\n证明我被解析过', request=request)class MyDownloadHandler(object):    '''    下载接口, 被上层所调用    '''    def __init__(self, settings):        self._pool = HTTPConnectionPool(reactor, persistent=True)        self._pool.maxPersistentPerHost = settings.getint('CONCURRENT_REQUESTS_PER_DOMAIN')        self._pool._factory.noisy = False        self._contextFactoryClass = load_object(settings['DOWNLOADER_CLIENTCONTEXTFACTORY'])        self._contextFactory = self._contextFactoryClass()    def download_request(self, request, spider):        '''下载的主要被调用接口(异步),返回 deferred (twisted 的延迟回调对象)'''        myDownloader = MyLogicDownloader()        return myDownloader.download(request)    def close(self):        return self._pool.closeCachedConnections()

4. 添加配置到 settings.py

DOWNLOAD_HANDLERS = {                'http': 'jstest.handler.mydownloader.MyDownloadHandler'                }

5. 在系统目录下新建一个 phantomjs 包装脚本 scrapyweb.js,并添加可执行权限

#!/usr/bin/env phantomjsif (phantom.args.length >= 1){        var url = phantom.args[0];        var timeOut = 10000;        if (phantom.args.length == 2){                timeOut = Math.min(30000, Math.max(0, phantom.args[1]));        }        var page = require('webpage').create();        page.customHeaders = {                'Accept-Language': 'zh-CN,zh;q=0.8',                'Connection': 'keep-alive',                'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',                'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',                'DNT': '1'        };        page.settings.userAgent = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36';        page.open(encodeURI(url),                        function(status){                                if (status != 'success'){                                        console.log('Err, status=' + status);                                        phantom.exit(1);                                }                                console.log(page.content);                                phantom.exit();                        });        setTimeout(function(){                console.log(page.content);                phantom.exit();        }, timeOut);}else {        console.log('Usage:');        console.log('\tphantomjs scrapyweb.js url timeout');        phantom.exit(1);}

6. 运行

scrapy crawl testSpider

需要注意的问题

  1. 例子是下载 js 动态页面的例子。如果需要复杂些的连续下载,需要按照 scrapy 框架的 http11.py 文件修改

  2. request.meta['download_latency'] 需要赋值,这个调整下载速度的 AutoThrottle 扩展依赖这个值判定

原文链接:

转载于:https://my.oschina.net/hopez/blog/215303

你可能感兴趣的文章
分布式系统理论基础 - CAP
查看>>
跨站脚本功攻击,xss,一个简单的例子让你知道什么是xss攻击
查看>>
win 停止tomcat
查看>>
Laravel-mix 中文文档
查看>>
Eureka核心知识点
查看>>
Sword STL迭代器prev,next相关函数
查看>>
小学生坐马桶上都看得懂的加密与通讯
查看>>
MS CRM 2011 如何从外部连接CRM 二
查看>>
Eclipse构建路径
查看>>
10条不可不知的手机礼仪 看看你犯过哪几项?
查看>>
:c#的remoting里,CallContext.GetData获得的对象老是空的?该怎么处理
查看>>
.NET设计模式(2): 工厂方法模式
查看>>
appium 自动化测试之知乎Android客户端
查看>>
如何使用Log4j?
查看>>
发送一个记录数据包
查看>>
开发资源汇聚 - jQuery (持续更新中)
查看>>
界面演示
查看>>
使用SQL Database Migration Wizard把SQL Server 2008迁移到Windows Azure SQL Database
查看>>
给线程发送消息让它执行不同的处理
查看>>
Bitcoin Cash到底是一种协议、还是一种产品?
查看>>