zg手册 之 scrapy 开发(5)-- downloader(下载器)开发
2014-04-02 05:00
351 查看
为什么需要开发下载器
定向抓取时,目标站点的数据不能单次请求获取,需要3,4次或者更多,请求之间有依赖关系,就是需要连续请求完成这个下载事物前面讲过的 js 动态页面下载
......
注意事项
下载器的不可以影响 twisted 框架本身的异步机制与 scrapy 原有的下载器调用接口一致,符合插件规范
其他插件依赖的状态要保留
下载器开发代码(我把注意的地方直接写在代码中,方便查看)
1. 新建项目# 创建项目 scrapy startproject jstest # 创建蜘蛛 scrapy genspider -t basic testSpider 'sina.com.cn'
2. 修改蜘蛛文件 testSpider.py
from scrapy.spider import Spider class 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-8 import re from time import time from cStringIO import StringIO from urlparse import urldefrag from zope.interface import implements from twisted.internet import defer, reactor, protocol from twisted.web.http_headers import Headers as TxHeaders from twisted.web.iweb import IBodyProducer from twisted.internet.error import TimeoutError from twisted.web.http import PotentialDataLoss from scrapy.xlib.tx import Agent, ProxyAgent, ResponseDone, HTTPConnectionPool, TCP4ClientEndpoint from scrapy.http import Headers from scrapy.responsetypes import responsetypes from scrapy.core.downloader.webclient import _parse from scrapy.utils.misc import load_object from scrapy.http import HtmlResponse from twisted.internet import utils class 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 phantomjs if (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
需要注意的问题
例子是下载 js 动态页面的例子。如果需要复杂些的连续下载,需要按照 scrapy 框架的 http11.py 文件修改request.meta['download_latency'] 需要赋值,这个调整下载速度的 AutoThrottle 扩展依赖这个值判定
原文链接: http://www.hopez.org/blog/9/1396376115
相关文章推荐
- zg手册 之 scrapy 开发(6)-- extensions(扩展)开发
- zg手册 之 scrapy 开发(7)-- 爬虫调试
- zg手册 之 scrapy 开发(3)-- 下载中间件
- zg手册 之 scrapy 开发(4)-- javascript 动态页面的抓取
- zg手册 之 scrapy 开发(3)-- 下载中间件
- zg手册 之 Mysql 开发(1)-- 中文全文检索插件开发
- Scrapy学习篇(十)之下载器中间件(Downloader Middleware)
- zg手册 之 twisted 开发(1)-- twisted 框架介绍
- Java开发手册笔记
- IntelliJ IDEA 14.1上JFinal开发环境搭建手册
- 《PL/SQL 语言开发参考手册》之二:PL/SQL 程序结构
- 联想智能农业移动应用开发系统用户手册
- 织梦dedeCMS二次开发文档手册 程序目录详解以及数据表结构字段
- IE开发人员工具手册
- OpenDDS开发手册---第二章(开始)3
- Node.js 入门手册:那些最流行的 Web 开发框架
- 方正BPM开发平台(FIX ES2007)帮助手册+知识库
- 喜马拉雅下载器使用手册