Scrapy学习第七课
Posted helenandyoyo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scrapy学习第七课相关的知识,希望对你有一定的参考价值。
python爬虫框架scrapy学习第七课
目标:爬取网页图片并保存
爬取网页中的图片,将图片下载到本地。
执行:爬取简书7日热门文章的图片
目标网页:简书7日热门文章图片
图片管道ImagesPipeline
爬虫结果基于管道pipeline进行处理,针对爬取的图片数据,scrapy提供图片管道ImagesPipeline进行处理。
1.其特性如下:
- 将所有下载的图片转换成通用的格式(JPG)和模式(RGB)
- 避免重新下载最近已经下载过的图片
- 缩略图生成
- 检测图像的宽/高,确保它们满足最小限制
这个管道也会为那些当前安排好要下载的图片保留一个内部队列,并将那些到达的包含相同图片的项目连接到那个队列中。 这可以避免多次下载几个项目共享的同一个图片。
2.工作流如下:
- 在一个爬虫(自定义的爬虫类/文件),你抓取一个项目,把其中图片的URL放入 image_urls 组内(items文件定义)。
- 项目从爬虫内返回,进入项目管道(pipeline文件)。
- 当项目进入 ImagesPipeline,image_urls组内的URLs将被Scrapy的调度器和下载器(这意味着调度器和下载器的中间件可以复用)安排下载,当优先级更高,会在其他页面被抓取前处理。项目会在这个特定的管道阶段保持“locker”的状态,直到完成图片的下载(或者由于某些原因未完成下载)。
- 当图片下载完,另一个组(images)将被更新到结构中。这个组将包含一个字典列表,其中包括下载图片的信息,比如下载路径、源抓取地址(从image_urls 组获得)和图片的校验码。 images 列表中的图片顺序将和源 image_urls组保持一致。如果某个图片下载失败,将会记录下错误信息,图片也不会出现在 images 组中。
图片存储
图片存储主要在settints.py文件中设置2个字段IMAGES_STORE和IMAGES_THUMBS。
- 当设置了IMAGES_STORE的值后,图片自动保存路径如下。其中,3afec3b4765f8f0a07b78f98c07b83f013567a0a为图片的URL的 SHA1 hash 值。
<IMAGES_STORE>/full/3afec3b4765f8f0a07b78f98c07b83f013567a0a.jpg
- 当设置了IMAGES_THUMBS的值之后,生成图片的缩略图。该字典值设置方式如下:
IMAGES_THUMBS =
‘small’: (50, 50),
‘big’: (270, 270),
- 当生成缩略图时,需使用Pillow类库,将图片归一化为JPEG/RGB格式。执行如下命令安装。若没有提前安装,则在进行爬取保存图片时报“ ModuleNotFoundError: No module named ‘PIL’”错误。
pip install pillow
图片管道关键函数get_media_requests和item_completed
1.get_media_requests(self, item, info)
在工作流程中可以看到,管道会得到图片的URL并从项目中下载。当它们完成下载后,结果将以2-元素的元组列表形式传送到 item_completed() 方法。
2.2-元素的元组列表形式
[(True,
'checksum': '2b00042f7481c7b056c4b410d28f33cf',
'path': 'full/7d97e98f8af710c7e7fe703abc8f639e0ee507c4.jpg',
'url': 'http://www.example.com/images/product1.jpg'),
(True,
'checksum': 'b9628c4ab9b595f72f280b90c4fd093d',
'path': 'full/1ca5879492b8fd606df1964ea3c1e2f4520f076f.jpg',
'url': 'http://www.example.com/images/product2.jpg'),
(False,
Failure(...))]
- success 是一个布尔值,当图片成功下载时为
True
,因为某个原因下载失败为False
- image_info_or_error 是一个包含下列关键字的字典(如果成功为 True )或者出问题时为 Twisted Failure。
- url - 图片下载的url。这是从 get_media_requests() 方法返回请求的url。
- path - 图片存储的路径(类似 IMAGES_STORE)。
- checksum - 图片内容的 MD5 hash。
3.item_completed(self, results, item, info)
接收的元组列表与 get_media_requests() 方法返回请求的顺序相一致。results即为上述返回的2-元组列表。
示例
# -*- coding: utf-8 -*-
import scrapy
from jiandan.items import JiandanItem
class JianSpider(scrapy.Spider):
name = 'jian'
allowed_domains = ['jianshu.com']
start_urls = ['https://www.jianshu.com/trending/weekly?utm_medium=index-banner-s&utm_source=desktop']
def parse(self, response):
item = JiandanItem()
#提取图片链接
item['image_urls'] = response.xpath('//img//@src').extract()
yield item
import scrapy
class JiandanItem(scrapy.Item):
image_urls = scrapy.Field()
images = scrapy.Field()
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 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36",
....
ITEM_PIPELINES =
'jiandan.pipelines.JiandanPipeline': 300,
IMAGES_STORE = 'D:\\SunWork\\python\\jiandan'
IMAGES_THUMBS =
'small': (50, 50),
'big': (200, 200)
import scrapy
from scrapy.exceptions import DropItem
from scrapy.pipelines.images import ImagesPipeline
class JiandanPipeline(ImagesPipeline):
#重定义
def get_media_requests(self, item, info):
for image_url in item['image_urls']:
image_url = "http://" + image_url
yield scrapy.Request(image_url)
#重定义
def item_completed(self, results, item, info):
images_paths = [x['path'] for ok, x in results if ok]
if not images_paths:
raise DropItem("Item contains no images")
return item
其中
images_paths = [x['path'] for ok, x in results if ok]
的写法可以看做是如下写法的简写,参考https://www.python.org/dev/peps/pep-0202/ 的示例。
for ok, x in results:
if ok:
print(x['path'])
结果:图片保存结果展示
以上是关于Scrapy学习第七课的主要内容,如果未能解决你的问题,请参考以下文章