scrapy 中如何自定义 pipeline 下载图片

Posted zishu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了scrapy 中如何自定义 pipeline 下载图片相关的知识,希望对你有一定的参考价值。

这里以一个很简单的小爬虫为例,爬取 壹心理 网站的阅读页面第一页的所有文章及其对应的图片,文章页面如下:

技术图片

创建项目

首先新建一个 scrapy 项目,安装好相关依赖(步骤可参考:scrapy 安装及新建爬虫项目并运行)。

新建一个爬虫:

scrapy genspider xinli001 www.xinli001.com/info

此时项目工程目录与新建的爬虫如下:

技术图片

爬取信息并编写图片自动下载逻辑

本次主要是记录自定义 pipeline 来爬取图片,所以只是简单的选取一些信息来爬取,包括文章标题、图片、发布时间和作者。

1.通过 xpath 提取出文章模块,就是下图中方框中的:

技术图片

上图右边便是对应的代码位置,下面将先使用 xpath 提取所有 item 模组,之后在对所有 item 组块遍历分别提取其对应的相关信息。

提取 item

post_nodes = response.xpath(//*[@id="articleListM"]//div[@class="item"])
2.遍历 post_nodes 并从中提取出相关信息:

下面给出第一个 item 中的网页结构:

技术图片

对照上面结构提取相关信息:

# 图片
image_url= post_node.xpath(a/img/@src).extract_first()
# 标题
title = post_node.xpath(div[@class="right"]/a/text()).extract_first()
# 发布时间
create_date = post_node.xpath(div[@class="right"]/div[@class="info"]/span/text()).extract_first()
# 作者
writer = post_node.xpath(div[@class="right"]/div[@class="info"]/a[1]/span/text()).extract_first()
3.定义 Xinli001Item

item.py 文件中添加 xinli001 爬虫对应的 item:

class Xinli001SpiderItem(scrapy.Item):
    title = scrapy.Field()
    image_url = scrapy.Field()
    writer = scrapy.Field()
    create_date = scrapy.Field()
4.提交 item 实例
# -*- coding: utf-8 -*-
import scrapy
from scrapy.http import Request
from urllib import parse
from Xinli001Spider.items import Xinli001SpiderItem
?
?
class Xinli001Spider(scrapy.Spider):
    name = xinli001
    allowed_domains = [www.xinli001.com]
    start_urls = ["https://www.xinli001.com/info/"]
?
    def parse(self, response):
        # 提取文章 model
        post_nodes = response.xpath(//*[@id="articleListM"]//div[@class="item"])
        for post_node in post_nodes:
            # 创建 item 实例
            article_item = Xinli001SpiderItem()
?
            # 图片
            image_url= post_node.xpath(a/img/@src).extract_first()
            # 标题
            title = post_node.xpath(div[@class="right"]/a/text()).extract_first()
            # 发布时间
            create_date = post_node.xpath(div[@class="right"]/div[@class="info"]/span/text()).extract_first()
            # 作者
            writer = post_node.xpath(div[@class="right"]/div[@class="info"]/a[1]/span/text()).extract_first()
?
            article_item[image_url] = [image_url]
            article_item[title] = title
            article_item[create_date] = create_date
            article_item[writer] = writer
?
            # 提交 item 实例给 pipeline 处理
            yield article_item
5.配置图片下载相关参数:
# 实现自动的图片下载的相关配置
IMAGES_URLS_FIELD = "image_url"     # 图片
project_dir = os.path.abspath(os.path.dirname(__file__))    # 获取当前路径
IMAGES_STORE = os.path.join(project_dir, images)  # 将图片保存到当前项目路径下的 images 文件夹下

将上面的代码加入到 settings.pyConfigure item pipelines 相关代码的下方。

6.启用 scrapy 的图片下载

在第5步之后,需要在 settings.py 中开启图片下载的服务:

技术图片

7.再次运行爬虫,便可实现图片的自动下载

技术图片

获取图片存放路径

图片下载之后,若要想访问图片,则需要获得图片的存放路径,此时我们便可对上面的 ImagePipeline 实现自定义来将获取图片存放路径的逻辑填充进代码中。

1-首先,添加 ArticleImagePipeline 类:
# 自定义 ImagePipeline ,继承自 ImagesPipeline,并添加相关自定义操作
class ArticleImagePipeline(ImagesPipeline):
    # 重写 item_completed 方法
    def item_completed(self, results, item, info):
        # 默认传过来的 result 是一个list
        # ok 表示返回是否成功,value是一个dict,存放了图片保存的路径
        for ok, value in results:
            image_file_path = value["path"]
        # 将获得的文件存放路径填充到 item 中
        item["front_image_path"] = image_file_path
?
        # 返回item
        return item
2-将 ArticleImagePipeline 配置到 settings.py 文件中:
# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = 
   Xinli001Spider.pipelines.Xinli001SpiderPipeline: 300,
   # ‘Xinli001Spider.pipelines.ImagesPipeline‘: 1,
   Xinli001Spider.pipelines.ArticleImagePipeline: 1,

注意上面之前使用的 ImagesPipeline 不需要了,要注释掉。

3-添加相关 item 属性

Xinli001SpiderItem 中添加一个 front_image_path 属性来存储图片存放路径:

技术图片

4-查看返回的图片路径

第二步中我们配置了两个 Pipeline ,一个顺序在前(ArticleImagePipeline:1),一个在后(Xinli001SpiderPipeline:300),我们可以在后面的 Pipeline 处理函数处打个断点,然后启动调试功能来运行。

打断点:

技术图片

debug 一下:

技术图片

可以看到执行到断点处时,已经提取到了图片存放路径:

 技术图片

 

以上是关于scrapy 中如何自定义 pipeline 下载图片的主要内容,如果未能解决你的问题,请参考以下文章

scrapy中如何处理大文件下载?

爬虫框架Scrapy 之 --- scrapy文件

python---scrapy之MySQL同步存储

通过scrapy内置的ImagePipeline下载图片到本地

Scrapy框架中的Pipeline组件

scrapy中的Pipeline