1.Scrapy简介
最开始看Scrapy的教程是中文版 ,这个版本是0.24,后来python模块warning的时候,去查看英文版,结果人家已经更新到1.0+了,很多import的模块已经有了一些改变,这里要注意。参与翻译scrapy的作者在他的github上说:
Scrapy的文档写得很详细,与之带来的就是文档量很大。仅仅靠我需要很多的时间。希望您能加入这个计划,让翻译更快速。
确实工作量非常大。这里也相参与翻译的工作人员致敬~
个人对Scrapy的印象是这样的:它专门为了scrapy而设计,里面有一个“半自动”化的结构,包括图1.1:
图1.1 scrapy 架构图(1)Scrapy Engine:相当于“经销商”,它负责什么时候向Spider买url,决定买多少,并卖给Scheduler;
(2)Spider:就是辛辛苦苦作劳动的机器人,它向Engine提供url以及相应的Rule,这是整个获取数据的关键,在你建立的scrapy项目下有一个文件夹叫:spider,里面放了spider的主程序,具体后面介绍。
(3)Scheduler:故名思意,就是调度,根据Engine给它的url产生各种request信息;
(4)Downloader:根据接受到的request信息进行下载,产生response对象,返还给spider处理;
(5)Item/Pipeline:spider在接受到response对象后,自动或者根据callback进行parse,然后把处理好的数据装进item或者输出到文件。
Scrapy内置了很多方法,我们要做的就是利用这种方法,告诉scrapy我要怎么做,具体谁发送request,谁接收response,item怎么传递的,那么就是由scrapy自己的逻辑实现,这个我们不用操心。但是还要明白spider里面各个method被执行的先后顺序,这样会使自己的逻辑非常清楚。不然scrapy就是一个黑箱,用的时候哪里有问题也不知道。
2.Scrapy使用方法
这里对于使用scrapy非常重要,弄清楚了各个method的功能和顺序才能有的放矢。
如果这里对于python不是很熟悉,可以找找python教材中“类”的那一章看看。
PS:本文基于linux平台,使用vim编程
(1)创建scrapy的project
在命令行输入:
cd ~/Produre #进入Podure目录下,在这个目录下建立projecy
scrapy startproject XXX #建立名为 XXX的project
此时在Proodure目录下会自动建立一个类似下面这样的文件结构:
图2:scrapy项目文件结构item.py是你要定义item的地方,item你就理解为spider后要把数据存入的地方,item就可以理解为一个字典。
pipeline可以理解为管道,当你获得的数据很多,不断产生时,用item存储的数据会被覆盖,而此时通过编写pipeline的class和method可以实现将数据源源不断的写入指定的文件类型中,后面介绍。
settings.py是存放spider的一些配置信息的,比如下载时间间隔,pipeline中类的名字,以及按照什么样的顺序进行下载。后面介绍。
spider文件夹下存放编写爬虫的主要文件。
(2)定义Item
打开item.py,然后按照你想要存储的数据,进行编写:
图3:编写item每一个定义的变量都可以在spider中作为item字典的键,不过这首先要被赋予scrapy.Field()
(3)Spider中的类和方法
定义好item后,就可以编写spider程序了,但在这之前介绍以下各种方法和类:
name:必须且唯一的spider名字,类型为string,运行该spider时输入它
allow_domains:允许方法的域名,可以是string 或者list,可选项,非必须。
start_urls: 指定要首先访问的url
方法:
start_requests(): 默认从start_urls里面获取url,并且为每一个url产生一个request,默认的 callback为parse。调度就是从这里开始执行的。这里可以改写,以便从指定的url开始访问,一般用于模拟登陆时,获取动态code的时候。获取动态code那么你可以这样:
from scrapy.http import Request,FromRequest
start_requests():
return [ Request( url, mata={'cookiejar':1}callback=login ) ] #加入meta想要获取cookie
这里的url就是你登陆的login URL,访问这个url时,server会返回你一个response,这个response里面就有下一步登陆的时候要发送的code。那么这里的callback到login这个方法的功能就是要从返回的response里面通过正则表达式或者结合xpath等得到这个code。
start_requests中将Downloader下载的response返回给callback,也就是我定义的login方法,那么在login方法中,除了要解析并获得动态code外,还可以进行模拟登陆,在login中可以加入:
def login(self,response):
code=response.xpath('//h1/text()').extract() #就是为了获得code,也可以结合re来提取
headers={} #模拟浏览器登陆的header
postdata={} #server要你post的数据,包括上面获得的code
return [FormRequest.from_response( url, headers=headers, formdata=postdata, meta={'cookiejar':response.meta['cookiejar'], callback=loged , dont_filter=x } ) ]
#注意这里postdata并没有用urlencode,且cookie用的是返回的response中的cookie,也就是上面start_requests那里记录的cookie。另外此时的url则是你真正post数据的url,一般可以通过firebug获得。其实,这里也可以这个时候才获得cookie,这样可以获得登陆以后的cookie。这个方法被调用以后,就成功登陆了,那么此时可以在loged方法中通过下面make_requests_from_url这个方法来访问登陆以后的其他页面。
#这里如果需要输入验证码,可以采用下载图片并手动输入的方式进行,在另外一片记录里可以看到。
如果该方法被重写了,那么start_urls里面的url将不会被首先访问,后面想要访问的时候则要特别的“强调“。会在后面说明。
还要注意的是,start_requests只被自动调用一次。
make_requests_from_url(url):
这个方法就是当你指定了url的时候,则通过这个方法,可以自动返回给parse。scrapy中能够自动调用parse的方法,就我目前的学习来看,只有这两个(start_requests和make_requests_from_url)。这个之所以重要,是因为要结合后面说的CrawlSpider中的rule。
可以通过make_requests_from_url()来实现访问start_urls里面的url:
def loged(self, response):
for url in start_urls:
yield make_requests_from_url(url)
parse():
scrapy中默认将response传递到的地方就是parse(),这里顾名思义是用来提取网页内容的地方,在Spider类中可以在这里实现网页内容提取,但是在CralwSpider中,parse()实现用rule中获得的link进行进一步处理,所以在CrawlSpider中不建议重写parse方法。
rule():
rule提供了如何指导Downloader获取链接的的功能,其具体实现是:
图:rule举例from scrapy.linkextractors import LinkExtractor as LKE
LinkExtractor的教程见:linkextractor
linkextractor的参数这里主要用到:
(1)allow=(这里用正则表达式写明要获取的链接)
(2)restrict_xpaths=(这里要用xpath格式写明特别要从哪个节点获取链接)
在Rule里面,特别要注意callback后面要加的是string,而不是向类中引用其他方法的self.parse_1。follow意位“跟踪”,那其实这里是有一个思考的。
rule是通过调用parse()方法来按照其里面提供的各种Rule来进行链接获取及response的返回,其逻辑是这样的:
(1)必须调用parse
(2)然后按照Rule规则,在parse中的response中寻找符合Rule指定规则的链接
(3)如果找到了相应的链接,那么请求这个链接,并把这个链接的response发送给callback,进行分析
(4)然后考虑是否跟进,如果跟进,那么以这个链接为基点再按照Rule中规则进行寻找
这里就存在两个问题,第一个发送到rule中的response,其实是没有被传给callback的;另外就是如果follow=False,那么其实......(未完待续)
网友评论