此文章继上一篇《scrapy爬虫框架的介绍,实战》,通过爬虫实战,进一步理解,学习scrapy爬虫框架。本文就以知名的技术博客Jobbole为例,主要说一下和上一篇爬虫实战的有别之处。
目标
爬取Jobbole网站的所有文章,并对信息进行处理保存。
分析
打开网页http://blog.jobbole.com/all-posts/,分析网页内容。
在文章列表页面我们需要抓取红框内的信息,并对文章详细页面进一步爬取,是的,这里也要对图片进行一个下载操作。
在文章详细页面,我们要提取文章的类型和文章的标签,当然,如果有需要你也可以提取更多你需要的信息。这里要注意,如下图的文章。
可能会有评论数,或者多个标签,我们就要进行一些处理,提取出我们想要的信息。至于如何定位到标签,我就不多做阐述。
开始爬虫8
先来看jobbolespider.py文件。
这里我要说一下ItemLoader对象,在之前的爬虫代码中我们使用的是response.xpath()这种方法提取的数据,那既然可以使用这种方法,为什么还要用ItemLoader方法呢。相较于前者,后者的优势在于简化了代码,更便于维护。当然,具体问题具体处理,两种方法都是可行的,在合适的地方用合适的方法才能刚好的解决问题。又扯远了,回归正题,我们继续将ItemLoader。
ItemLoader对象的基本使用
#引入模块
from scrapy.loader import ItemLoader
#实例化对象
loader=ItemLoader(item=* , response=* , selector=* )
#这里有三个重要的参数
#item 就是你定义的存储数据的item实例对象
#response 网页的response对象
#selector 这个是选择器对象
#方法
loader.add_xpath('item字段名', 'xpath规则')
loader.add_css('item字段名', 'css规则')
loader.add_value('item字段名', value值)
#通过此方法返回item对象
item=loader.load_item()
提取的数据不一定是我们最终需要的数据,我们还需要对数据进行进一步处理,而scrapy也为我们提供了解决方案。
在items.py中,我们可以看到scrapy.Field()方法中有两个参数,input_processor和output_processor,第一个参数是指定预处理方法,例如对数据进行正则运算。第二个参数是指定输出方法,items的默认存储方式是list,你可以使用内置的函数TakeFirst()方法以非list方式输出。这里说一下MapCompose()方法,他的参数是不确定的,就是说你可以指定多个处理方法。
这里注意一下,指定的方法有一个value参数,这个就是提取的数据。
如果每个字段都需要用到一个方法处理,那么一一去指定就太麻烦了。我们看一下ItemLoader类中有这么几行
我们是可以指定默认参数的,我们需要写一类继承ItemLoader类。
这时我们就不需要一一制定参数了,而当某一个字段不需要此方法处理时,另行指定output_processorc参数就行。
我们再来说说如何下载图片,scrapy为我们提供了一个叫ImagesPipeline的类,我们需要在settings.py中进行如下设置。
设置完成后scrapy就会自动为我们下载图片。但是我们不仅要下载图片,还要获取图片路径信息,所以我们要换一种方式。我们需要在pipeline.py中声明一个类并继承ImagesPipeline类,在该类中重写item_completed这个方法。直接看代码
相应的在settings.py中的也要开启此类
这里需要特别提一下,在jobbolespider.py中解析时,我们是对两类不同的页面进行解析,相应的我们就要写两个解析函数。但是两个页面爬取的内容我们是需要放入同一个item对象里的,这里就需要将parse方法中实例化的Itemloader对象parse_detail方法中,在此方法的最后再yield item。
最后,就是对数据进行存储至数据库了。基本的存储方法我就吧说了,这里我要说的是以异步方式将数据存至数据库。之前一篇文章中,存入数据库是同步的,需要等待数据存储完成才能继续爬取数据,而爬虫中,数据的爬取速度往往是大于存入数据库的速度的,使用异步方式则大大提升了爬虫的效率。
我们先来导入我们需要的模块
再来就是先将数据库信息写入settings,py文件中,方便之后的操作
既然将到这里就顺带提一下,scrapy的内置方法from_settings,但你在类中声明了这个方法,他就会先于__init__调用此方法,其中一个参数settings,你可以通过字典的方式进行查询,直接获取字段的值,而cls参数,即你的自定义类对象。
然后我们继续来看,首先我们要通过adbapi.ConnectionPool方法实例化对象。先来看一下他的参数
第一个参数就是你需要使用的操作数据库的模块名称,而后面的参数就是数据库的了解信息,以字典方法传入
实例化对象后就可以对数据进行插入操作了
同样的还是在process_item方法中进行实现
这样我们就完成爬虫,来看一下结果
好的,今天就这样8,明天也要加油?