创建scrapy项目的命令在此不在赘述了,如果不清楚的小伙伴可以看下:Scrapy框架快速入门,以糗事百科为例进行说明【python爬虫入门进阶】(16)通过如下命令创建了一个名为bba_img_demo的scrapy项目,并创建一个名为bba3的spider。
scrapystartprojectbba_img_democdbba_img_demoscrapygenspiderbba3"car.autohome.com.cn"爬取图片bba3Spider这里还是采用xpath来爬取页面元素。在bba3Spider中爬取页面元素得到imgDemoItem,并返回给Pipelines。
在bbaImgDemoPipeline中通过接收bba3Spider返回的imgDemoItem。并将图片保存到bba_img_demo项目的images目录下。并且在images目录下以类别来保存各个类别下的图片数据。
这个方法可以实现我们想要的效果。但是,还不够优雅,没有用到多线程,不够简洁。scrapy为下载item包含的文件(比如在爬取到产品时,同时也想保存对应的图片)提供了一个可重用的itempipelines。这些pipeline有共同的方法和结构(我们称之为mediapipelines)。一般来说你会使用FilesPipeline或者ImagesPipeline
当使用ImagePipeline下载文件的时候,按照以下步骤来完成:
下面我们就使用ImagePipeline来实现下这个功能,详细的步骤如下:
classbbaImgDemoItem(scrapy.Item):category=scrapy.Field()image_urls=scrapy.Field()images=scrapy.Field()在bbaImgDemoItem类中定义image_urls和images两个属性。
pipinstallPillow经过上面五步之后就可以正确的运行了。运行之后的结果是:
可以看出所有的图片都被保存到了images目录下的full文件夹下了。这显然也不是我们期望的结果。所以我们还是需要继承ImagesPipeline类,然后,重写其保存逻辑。查看ImagesPipeline源代码可以得知将图片保存到full文件夹的方法是file_path。所以我们只需要重写这个方法返回我们想要的路径即可。
在pipelines.py文件中自定义一个名为bbaImagesPipeline的类,让该类继承自ImagesPipeline。
defget_media_requests(self,item,info):urls=ItemAdapter(item).get(self.images_urls_field,[])return[Request(u)foruinurls]重写后的get_media_requests方法。首先调用父类的image_urls方法,然后将item设置到request_obj中。
defget_media_requests(self,item,info):request_objs=super(bbaImagesPipeline,self).get_media_requests(item,info)forrequest_objinrequest_objs:request_obj.item=itemreturnrequest_objs2.重写file_path方法父类的file_path方法主要就两步,第一步是将图片链接的地址做hash运算得到图片的名称,接着返回图片存储的相对路径full/{image_guid}.jpg。
这里自定义了一个名为bba3Spider类,该类继承自CrawlSpider。