Scrapy用到的相关东西之间的区别
MongoDB与Redis
Redis和MongoDB,Redis一般称之为缓存、MongoDB一般称之为数据库。
Redis主要把数据存储在内存中,其“缓存”的性质远大于其“数据存储“的性质,其中数据的增删改查也只是像变量操作一样简单;
MongoDB却是一个“存储数据”的系统,增删改查可以添加很多条件,就像SQL数据库一样灵活
Splash与Selenium
Splash支持异步处理,同时可以获取多个爬取结果;Selenium中每个页面渲染下载是在Download Middleware里完成的,整个过程是阻塞式的
所以,Splash的爬取效率要高于Selenium
Spider
spider继承自scrapy.spiders.Spider。它是最基本的spider类,其他spider必须继承这个类
运行流程
- 以初始的URL初始化Request,并设置回调函数(默认使用parse)。当该Request成功请求并返回时,Response生成并作为参数传给该回调函数
- 在回调函数内分析返回的网页内容。返回结果有两种形式。一种是解析到有效结果返回字典或者Item对象,他们经过处理后保存。另一种是解析得到下一个链接(如下一页),可以利用此链接构造Request并设置新的回调函数,返回Request等待后续调度
- 如果返回的是字典或者Item对象,可以通过Feed Exports等组件将结果存入文件。如果设置了Pipline的话,可以使用Pipline的处理过程
- 如果返回的是Request,那么Request执行成功得到Response后,Response会被传递到Request中定义的回调函数,在回调函数中再次使用选择器来分析新得到的网页内容,并分析数据生成Item或字典
Item Pipeline
Item Pipeline是项目管道,他的调度发生在spider生成Item之后。当spider解析完Response后,Item就会传递到Item Pipeline,被定义的Item Pipeline会被依次执行,完成一系列的处理过程。
核心方法
- process_item(item,spider)
必须要实现的方法,被定义的Item Pipline会默认调用这个方法对Item进行处理。
如果返回的是Item对象,那么此Item会被优先级低的Item Pipline的process_item()方法处理,直到所有方法被调用完毕
如果返回的是DropItem异常,那么此Item会被丢弃,不再进行处理 - open_spider(self,spider)
在spider开启时被调用 - close_spider(spider)
在spider关闭时调用 - from_crawler(cls,crawler)
类方法,用@classmethod标识,是一种依赖注入的方式。通过crawler对象,可以拿到Scrapy的所有核心组件,如全局配置的信息,之后创建一个Pipeline实例。参数cls是class,最后返回class实例
当有多个Item Pipline时,可修改setting,设置优先级
ITEN_PIPELINES={
‘-----.pipelines.----’:300,
‘----.pipelines.----’:301,
}
数字越小,优先级越高
Image Pipeline
Scrapy提供了专门用来下载的Pipeline,包括文件和图片下载。原理与页面抓取相同,支持同步和异步。
- 首先定义存储路径,在settings.py中添加:IMAGES_STORE=’./images’,这样下载的图片会保存到本项目的images文件中。
- 内置的ImagesPipeline会默认读取Item的image_urls字段,并认为该字段是一个列表形式,它会遍历Item的image_urls字段,然后取出每个URL进行图片下载。
- 如果取出的图片链接不是image_urls字段存储,也不是列表形式,则需要重新定义。
- 重新定义需要继承自ImagesPipeline,并重写几个方法
from scrapy import Requset
from scrapy.exceptions import DropItem
from scrapy.pipelines.images import ImagesPipeline
class Image_DownloadPipeline(ImagesPipeline):
def file_path(self,request,response=None,info=None):
url = request.url
file_name = url.spilt('/')[-1]
return file_name
def item_completed(self,results,itme,info):
image_path = [x['path'] for ok ,x in results if ok]
if not image_path:
raise DropItem('Image Download Failed')
return item
def get_media_requests(self,item,info):
yield Request(item['url'])
get_media_requests()
第一个参数item是爬取生成的Item对象。取出其中的url字段,生成Request对象并加入到调度队列,等待被调度,执行下载
file_path()
该方法用来返回保存的文件名
item_completed()
当单个Item完成下载时调用此方法进行处理。results参数是该item对应的下载结果,它是一个列表形式,列表每一个元素是一个元组,其中包含了下载成功和失败的信息。