scrapy抓取百度图片-写给自己看爬虫系列1

前言

需求:用scrapy抓取图片
思路:scrapy抓取图片的逻辑是,用爬虫抓取图片url输出到pipeline中,然后由pipeline实施下载保存。关于pipeline的编写,可以自定义一个pipeline或者继承scrapy的imagespipeline从而实现抓取图片,本文以百度图片为例子写一个下载图片的爬虫。

百度图片爬虫-item说明
import scrapy
from scrapy import Field,Item

class PicItem(scrapy.Item):
    search_word = Field()  #搜索的关键词
    pic_name  = Field()  #图片名字
    pic_url = Field()       #图片url
百度图片爬虫-spider说明
import scrapy,json
from scrapy.http import Request
from scrapy.http import FormRequest
from pic.items import PicItem

class PicspiderSpider(scrapy.Spider):
    
    name = "picspider"
    
    allowed_domains = ["http://image.baidu.com/"]
    
    start_urls = ["http://image.baidu.com"]

    def parse(self, response):

        search_word   = '美女'    #查找词
        
        baidu_pic_url = "https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&word={0}&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&pn=60&rn=30&gsm=3c&1507915209449=".format(search_word)  #百度图片url
        
        yield Request(baidu_pic_url,meta={"search_word":search_word},callback=self.get_pic,dont_filter=True)
    
    def get_pic(self,response):
        
        item = PicItem()
 
        response_json = response.text    #返回的数据是json格式
 
        response_dict = json.loads(response_json)  #转化为字典
 
        response_dict_data = response_dict['data']  #图片的有效数据在data参数中
        
        for pic in response_dict_data:

            if pic:
                item['search_word']    = response.meta['search_word']  #搜索关键词赋值
                item['pic_url']        = pic['middleURL']  #百度图片搜索结果url            
                item['name']           = pic['fromPageTitleEnc']  #百度图片搜索结果对应的title            
                yield item

自定义pipeline写法

pipeline写法

对爬虫输出的url地址进行请求并且用with open方式存储图片,存储路径为在当前项目中的对应搜索词目录下,图片文件名以百度图片上的图片标题命名。最后在setings中设置好pipeline即可。

import requests,os, sys
from pic import settings       #从settings中导入设定的参数
from scrapy.exceptions import DropItem
from scrapy.http import Request

reload(sys)
sys.setdefaultencoding('utf-8')

 class PicPipeline(object):

     def process_item(self, item, spider):
        
         dir_path = item["search_word"]  

         if not os.path.exists(dir_path):    #检查搜索词是否已经有对应的文件夹,若没则创建一个
            
             os.makedirs(dir_path)

         pic_name = item['name']

         pic_url  = item['pic_url']

         pic_path = dir_path+'/'+pic_name+'.jpg'   #最终路径为搜索词+图片标题

         pic  = requests.get(pic_url,headers=settings.HEADER)  #对图片url发出请求

         with open(pic_path,'wb') as file:   #使用wb方式保存图片

             file.write(pic.content)

继承imagespipeline类写法

imagespipeline工作流程

1.爬取一个Item,将图片的URLs放入image_urls字段
2.从Spider返回的Item,传递到Item Pipeline
3.当Item传递到ImagePipeline,将调用Scrapy 调度器和下载器完成image_urls中的url的调度和下载。ImagePipeline会自动高优先级抓取这些url,于此同时,item会被锁定直到图片抓取完毕才被解锁。
4.图片下载成功结束后,图片下载路径、url和校验和等信息会被填充到images字段中。

setting中的常用属性
ITEM_PIPELINES = ['pic.pipelines. PicPipeline']
IMAGES_STORE = '\home\xiaoming\web_robot\project'  #保存路径
IMAGES_EXPIRES = 90   #过期天数
IMAGES_MIN_HEIGHT = 0  #图片最小的高度,小于该值会被过滤
IMAGES_MIN_WIDTH   =0   #图片最小的宽度,小于该值会被过滤
imagespipeline写法
import requests,os
from pic import settings

import sys  
from scrapy.contrib.pipeline.images import ImagesPipeline  #导入images中间件模块
from scrapy.http import Request
reload(sys)
sys.setdefaultencoding('utf-8')


class PicPipeline(ImagesPipeline): #继承imagespipeline
    
    def get_media_requests(self,item,info):
        
        url = item['pic_url']

        yield Request(url)

    def item_completed(self,results,item,info):
        # result是一个二元组列表,第一个参数为下载是否成功,第二个参数是详细信息。url,path等数据
        image_path = [ result['path'] for exist,result in results if ok ] 

参考文章
scrapy 下载图片 ImagesPipeline
Python:使用Scrapy框架的ImagesPipeline下载图片如何保持原图片名称呢?

    原文作者:wfishj
    原文地址: https://www.jianshu.com/p/a75ab32aeffd
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞