欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-23 10:25:11
...

前言

需求:用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下载图片如何保持原图片名称呢?