Scrapy从入门到精通系列前四篇已经讲了从网页中获取信息的方法,除此之外,爬虫也可以从网页中下载图片、视频、word、pdf、压缩包等
FilesPipeline和ImagePipeline
Scarpy框架内部提供了这两个Item Pipeline专门用来下载文件和图片
可以将它们视为特殊下载器,给他们url,就会自动下载到本地,并将下载结果存入item的另一个特殊字段,以便用户在导出文件中查阅
FilesPipeline
例子
<html>
<body>
<a href='/book/sg.pdf'>下载《三国》a>
<a href='/book/sg.pdf'>下载《水浒》a>
<a href='/book/sg.pdf'>下载《红楼》a>
<a href='/book/sg.pdf'>下载《西游》a>
body>
html>
- 在配置文件settings.py中启用FilesPipeline,通常将其置于首位
ITEM_PIPELINES = {'scrapy.pipelines.files.FilesPipeline':1}
- 在配置文件settings.py中指定下载目录
FILES_STORE = '/home/liushuo/Download/scrapy'
3.在Spider解析一个包含文件下载链接的页面, 将所有url地址收集到一个列表,赋值给item的file_urls字段(item[‘file_urls’]).
class DownloadBookSpider(scrapy.Spider):
def parse(response):
item = {}
item['file_urls'] = []
for url in response.xpath('//a/@href').extract():
download_url = response.urljoin(url)
#将url填入下载列表
item['file_urls'].append(download_url)
yield item
当FilePipeline下载完item[‘file_urls’]中所有文件中,各文件的下载结果信息收集到另一个列表,赋给item的files字段(item[‘files’]),下载结果信息包含以下
- path 文件下载到本地路径(相当于FILES_STORE的相对路径)
- Checksum 文件的校验和
URL 文件和URL地址
ImagesPipeline使用说明
图片也是文件,所以下载图片本质上也是下载文件
ImagesPipeline和FilesPiplines使用类似,只是在使用item字段和配置选项上略有差别- ImagesPipeline FilePipeline
scrapy.pipelines.ImagesPipline 2 scrapy.pipelines.files.FilesPipline
file_urls,files 2 image_urls,images
FILES_STORE 2IMAGES_STORE
ImagesPipeline在FilesPipleline的基础上针对图片增加一些特有功能:
- 为图片生成缩略图
开启该功能,在配置文件中设置IMAGES_THUMBS,他是一个字典,每一项的值是缩略图的尺寸
`IMAGES_THUMBS = {
- 'small':(50,50),
- 'big':(270,270),
- }`
- 过滤掉尺寸过小的图片
设置IMGAES_MIN_WIDTH和IMAGES_MIN_HEIGHT,
IMGAES_MIN_WIDTH = 110
IMAGES_MIN_HEIGHT = 110
项目实战:下载360图片
http://images.so.com
项目需求
爬去360图片艺术类
页面分析
滚轮向下滑动,自动加载更多的图片,用的是jQuery发送的请求,相应结果为一个json串。
复制图中的jQuery发送请求的url,使用scrapy shell 进行访问,查看相应结果的json:
$scrapy shell 'http://images.so.com/zj?ch=art&sn=90&listtype=new&temp=1'
import json
res = json.loads(response.body.decode('utf8'))
res
如图所示,相应结果(json)中的list字段是一个图片信息列表,count:列表中图片信息的数量
qhimg_url:图片的下载链接
连续滑动,获取多次jQuery请求
第一次加载:http://images.so.com/zj?ch=art&sn=30&listtype=new&temp=1
第二次加载:http://images.so.com/zj?ch=art&sn=60&listtype=new&temp=1
第三次加载:http://images.so.com/zj?ch=art&sn=90&listtype=new&temp=1
ch参数:分类标签
sn参数:从第几张图片开始加载,也是第一张图片得服务器中的编号
编码实现spider
- 创建Scrapy项目,并使用scrapy genspider命令创建spider
- 在配置文件中启用ImagesPipeline,指定下载目录
实现ImageSpider
创建Scrapy项目,并使用scrapy genspider命令创建spider
Scrapy startproject so_image
cd so_image
scrapy genspider images images.so.com
在配置文件中启用ImagesPipeline,指定下载目录
ITEM_PIPELINES = {
'scrapy.pipelines.images.ImagesPipeline':1,
}
IMAGES_STORE = 'download_images'
实现ImagesSpider
# -*- coding: utf-8 -*-
import scrapy
from scrapy import Request
import json
class ImagesSpider(scrapy.Spider):
name = 'images'
# allowed_domains = ['images.so.com']
BASE_URL = 'http://images.so.com/zj?ch=art&sn=%s&listtype=new&temp=1'
start_index = 0
# 限制最大下载数量
MAX_DOWNLOAD_NUM = 1000
start_urls = [BASE_URL % 0]
def parse(self, response):
#使用json模块解析响应结果
infos = json.loads(response.body.decode('utf-8'))
#提取所有下载url到一个列表,赋给item的‘image_urls’字段
yield {'images_urls':[info['qhimg_url']for info in infos['list']]}
#如果count字段大于0,并且下载数量不足MAX_DOWNLOAD_NUM继续获取下一页
self.start_index += infos['count']
if infos['count'] > 0 and self.start_index < self.MAX_DOWNLOAD_NUM:
yield Request(self.BASE_URL%self.start_index)
运行spider
scrapy crawl images