前言
我们知道使用requests与selenium下载图片都是非常简单的,那么scrapy是怎么下载图片的呢?
下载图片
1 安装模块
pip install pillow
2 配置settings.py
# 设置请求头
DEFAULT_REQUEST_HEADERS = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'
}
3 在img.py中实现
思路:
抓取到详情页中图片的url地址,交给图片管道进行下载
import scrapy
from urllib.parse import urljoin
class ImgSpider(scrapy.Spider):
name = "img"
allowed_domains = ["抓取的网站域名"]
start_urls = ["抓取的起始网址"]
def parse(self, response, **kwargs):
# 抓取到每个详情页的url
href_list = response.xpath('//ul[@class="pic-list2 clearfix"]/li/a/@href').extract()
for href in href_list:
# 去除不要的exe的url
if href.find('exe') != -1:
continue
# 拼接url 获取到详情页的url
detail_url = urljoin("http://desk.zol.com.cn/dongman/", href)
# print(detail_url)
# 请求详情页的url
yield scrapy.Request(url=detail_url, callback=self.parse_detail)
# 解析详情返回的响应对象
def parse_detail(self, response):
# 获取详情页中不同分辨率大小的图片的url
detail_href = response.xpath('//dd[@id="tagfbl"]/a/@href').extract()
# print(detail_href)
if len(detail_href) > 1:
# 拼接大图的url
max_img_url = urljoin("http://desk.zol.com.cn/dongman/", detail_href[0])
# print(max_img_url)
# 请求大图页的url
yield scrapy.Request(url=max_img_url, callback=self.parse_max_img)
# 最后解析大图的url地址
def parse_max_img(self, response):
url = response.xpath('//img[1]/@src').extract_first()
print(url)
yield {'img_src': url}
4 配置图片管道
存储图片不能再像上篇文章一样,只用之前的管道类(pipeline),我们需要用到新的存储图片的管道类ImagesPipeline
- 导入ImagesPipeline
from scrapy.pipelines.images import ImagesPipeline
- 定义一个Images类
from itemadapter import ItemAdapter
from scrapy.pipelines.images import ImagesPipeline
import scrapy
class DeskPipeline():
def process_item(self, item, spider):
return item
class ImgPipeline(ImagesPipeline):
# 1. 发送请求(下载图片, 文件, 视频,xxx)
def get_media_requests(self, item, info):
# 获取到图片的url
url = item['img_src']
# 进行请求
yield scrapy.Request(url=url, meta={"url": url}) # 直接返回一个请求对象即可
# 2. 图片存储路径
def file_path(self, request, response=None, info=None, *, item=None):
# 当前获取请求的url的方式有2种
# 获取到当前的url 用于处理下载图片的名称
file_name = item['img_src'].split("/")[-1] # 用item拿到url
# file_name = request.meta['url'].split("/")[-1] # 用meta传参获取
return file_name
# 3. 可能需要对item进行更新
def item_completed(self, results, item, info):
# print('results', results)
for r in results:
# 获取每个图片的路径
print(r[1]['path'])
return item # 一定要return item 把数据传递给下一个管道
5 保存数据
接着我们再定义一个保存数据的函数,并设置好存储的文件名,然后存储的路径需要在设置中(setting)文件中,添加IMAGE_STORE设置好存储的路径
- 开启图片管道
settings.py
ITEM_PIPELINES = {
"desk.pipelines.DeskPipeline": 300,
"desk.pipelines.ImgPipeline": 400, # 图片下载管道
}
# 配置存储图片的路径
IMG_STORE = './imgs'
6 查看结果
总结
1.保存图片需要导入ImagesPipeline类
2.需要配置settings.py 开启管道 并设置保存路径