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