资讯专栏INFORMATION COLUMN

Python图片爬取方法总结

edagarli / 1905人阅读

摘要:当项目进入,组内的将被的调度器和下载器这意味着调度器和下载器的中间件可以复用安排下载,当优先级更高,会在其他页面被抓取前处理。这个组将包含一个字典列表,其中包括下载文件的信息,比如下载路径源抓取地址从组获得和图片的校验码。

1. 最常见爬取图片方法

对于图片爬取,最容易想到的是通过urllib库或者requests库实现。具体两种方法的实现如下:

1.1 urllib

使用urllib.request.urlretrieve方法,通过图片url和存储的名称完成下载。

"""
Signature: request.urlretrieve(url, filename=None, reporthook=None, data=None)
Docstring:
Retrieve a URL into a temporary location on disk.

Requires a URL argument. If a filename is passed, it is used as
the temporary file location. The reporthook argument should be
a callable that accepts a block number, a read size, and the
total file size of the URL target. The data argument should be
valid URL encoded data.

If a filename is passed and the URL points to a local resource,
the result is a copy from local file to new file.

Returns a tuple containing the path to the newly created
data file as well as the resulting HTTPMessage object.
File:      ~/anaconda/lib/python3.6/urllib/request.py
Type:      function
"""

参数 finename 指定了保存本地路径(如果参数未指定,urllib会生成一个临时文件保存数据。)

参数 reporthook 是一个回调函数,当连接上服务器、以及相应的数据块传输完毕时会触发该回调,我们可以利用这个回调函数来显示当前的下载进度。

参数 data 指 post 到服务器的数据,该方法返回一个包含两个元素的(filename, headers)元组,filename 表示保存到本地的路径,header 表示服务器的响应头。

使用示例:

request.urlretrieve("https://img3.doubanio.com/view/photo/photo/public/p454345512.jpg", "kids.jpg")

但很有可能返回403错误(Forbidden),如:http://www.qnong.com.cn/uploa...。Stack Overflow指出原因:This website is blocking the user-agent used by urllib, so you need to change it in your request.

给urlretrieve加上User-Agent还挺麻烦,方法如下:

import urllib

opener = request.build_opener()
headers = ("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:53.0) Gecko/20100101 Firefox/53.0")
opener.addheaders = [headers]
request.install_opener(opener)
request.urlretrieve("http://www.qnong.com.cn/uploadfile/2016/0416/20160416101815887.jpg", "./dog.jpg")
1.2 requests

使用requests.get()获取图片,但要将参数stream设为True

import requests

req = requests.get("http://www.qnong.com.cn/uploadfile/2016/0416/20160416101815887.jpg", stream=True)

with open("dog.jpg", "wb") as wr:
    for chunk in req.iter_content(chunk_size=1024):
        if chunk:
            wr.write(chunk)
            wr.flush()

requests添加User-Agent也很方便,使用headers参数即可。


2. Scrapy 支持的方法 2.1 ImagesPipeline

Scrapy 自带 ImagesPipeline 和 FilePipeline 用于图片和文件下载,最简单使用 ImagesPipeline 只需要在 settings 中配置。

# settings.py
ITEM_PIPELINES = {
    "scrapy.pipelines.images.ImagesPipeline": 500
}

IMAGES_STORE = "pictures"  # 图片存储目录
IMAGES_MIN_HEIGHT = 400  # 小于600*400的图片过滤
IMAGES_MIN_WIDTH = 600
# items.py
import scrapy

class PictureItem(scrapy.Item):
    image_urls = scrapy.Field()
# myspider.py
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule


from ..items import BeePicture

class PicSpider(CrawlSpider):
    name = "pic"
    allowed_domains = ["qnong.com.cn"]
    start_urls = ["http://www.qnong.com.cn/"]

    rules = (
        Rule(LinkExtractor(allow=r".*?", restrict_xpaths=("//a[@href]")), callback="parse_item", follow=True),
    )

    def parse_item(self, response):
        for img_url in response.xpath("//img/@src").extract():
            item = PictureItem()
            item["image_urls"] = [response.urljoin(img_url)]
            yield item
2.2 自定义 Pipeline

默认情况下,使用ImagePipeline组件下载图片的时候,图片名称是以图片URL的SHA1值进行保存的。

如:
图片URL: http://www.example.com/image.jpg
SHA1结果:3afec3b4765f8f0a07b78f98c07b83f013567a0a
则图片名称:3afec3b4765f8f0a07b78f98c07b83f013567a0a.jpg

想要以自定义图片文件名需要重写 ImagesPipeline 的file_path方法。参考:https://doc.scrapy.org/en/lat...。

# settings.py
ITEM_PIPELINES = {
    "qnong.pipelines.MyImagesPipeline": 500,
}
# items.py
import scrapy

class PictureItem(scrapy.Item):
    image_urls = scrapy.Field()
    images = scrapy.Field()
    image_paths = scrapy.Field()
# myspider.py
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule


from ..items import BeePicture

class PicSpider(CrawlSpider):
    name = "pic"
    allowed_domains = ["qnong.com.cn"]
    start_urls = ["http://www.qnong.com.cn/"]

    rules = (
        Rule(LinkExtractor(allow=r".*?", restrict_xpaths=("//a[@href]")), callback="parse_item", follow=True),
    )

    def parse_item(self, response):
        for img_url in response.xpath("//img/@src").extract():
            item = PictureItem()
            item["image_urls"] = [response.urljoin(img_url)]
            yield item
# pipelines.py
from scrapy.exceptions import DropItem
from scrapy.pipelines.images import ImagesPipeline
import scrapy

class MyImagesPipeline(ImagesPipeline):
    def get_media_requests(self, item, info):
        for img_url in item["image_urls"]:
            yield scrapy.Request(img_url)

    def item_completed(self, results, item, info):
        image_paths = [x["path"] for ok, x in results if ok]
        if not image_paths:
            raise DropItem("Item contains no images")
        item["image_paths"] = image_paths
        return item

    def file_path(self, request, response=None, info=None):
        image_guid = request.url.split("/")[-1]
        return "full/%s" % (image_guid)
2.3 FilesPipeline 和 ImagesPipeline 工作流程

FilesPipeline

在一个爬虫里,你抓取一个项目,把其中图片的URL放入 file_urls 组内。

项目从爬虫内返回,进入项目管道。

当项目进入 FilesPipeline,file_urls 组内的 URLs 将被 Scrapy 的调度器和下载器(这意味着调度器和下载器的中间件可以复用)安排下载,当优先级更高,会在其他页面被抓取前处理。项目会在这个特定的管道阶段保持“locker”的状态,直到完成文件的下载(或者由于某些原因未完成下载)。

当文件下载完后,另一个字段(files)将被更新到结构中。这个组将包含一个字典列表,其中包括下载文件的信息,比如下载路径、源抓取地址(从 file_urls 组获得)和图片的校验码(checksum)。 files 列表中的文件顺序将和源 file_urls 组保持一致。如果某个图片下载失败,将会记录下错误信息,图片也不会出现在 files 组中。

ImagesPipeline

在一个爬虫里,你抓取一个项目,把其中图片的 URL 放入 images_urls 组内。

项目从爬虫内返回,进入项目管道。

当项目进入 Imagespipeline,images_urls 组内的URLs将被Scrapy的调度器和下载器(这意味着调度器和下载器的中间件可以复用)安排下载,当优先级更高,会在其他页面被抓取前处理。项目会在这个特定的管道阶段保持“locker”的状态,直到完成文件的下载(或者由于某些原因未完成下载)。

当文件下载完后,另一个字段(images)将被更新到结构中。这个组将包含一个字典列表,其中包括下载文件的信息,比如下载路径、源抓取地址(从 images_urls 组获得)和图片的校验码(checksum)。 images 列表中的文件顺序将和源 images_urls 组保持一致。如果某个图片下载失败,将会记录下错误信息,图片也不会出现在 images 组中。

Scrapy 不仅可以下载图片,还可以生成指定大小的缩略图。
Pillow 是用来生成缩略图,并将图片归一化为 JPEG/RGB 格式,因此为了使用图片管道,你需要安装这个库。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/38687.html

相关文章

  • 首次公开,整理12年积累的博客收藏夹,零距离展示《收藏夹吃灰》系列博客

    摘要:时间永远都过得那么快,一晃从年注册,到现在已经过去了年那些被我藏在收藏夹吃灰的文章,已经太多了,是时候把他们整理一下了。那是因为收藏夹太乱,橡皮擦给设置私密了,不收拾不好看呀。 ...

    Harriet666 评论0 收藏0
  • Python 从零开始爬虫(三)——实战:requests+BeautifulSoup实现静态爬取

    摘要:前篇全片都是生硬的理论使用,今天就放个静态爬取的实例让大家体验一下的使用,了解一些背后的原理。给出网站打开右键检查第一个电影,分析源码先,发现每个标签就对应着一个电影的信息。 前篇全片都是生硬的理论使用,今天就放个静态爬取的实例让大家体验一下BeautifulSoup的使用,了解一些背后的原理。 顺便在这引入静态网页的概念——静态网页是指一次性加载所有内容的网页,爬虫一次请求便能得到所...

    Codeing_ls 评论0 收藏0
  • 爬虫 - 收藏集 - 掘金

    摘要:在这之前,还是有必要对一些概念超轻量级反爬虫方案后端掘金前言爬虫和反爬虫日益成为每家公司的标配系统。 爬虫修炼之道——从网页中提取结构化数据并保存(以爬取糗百文本板块所有糗事为例) - 后端 - 掘金欢迎大家关注我的专题:爬虫修炼之道 上篇 爬虫修炼之道——编写一个爬取多页面的网络爬虫主要讲解了如何使用python编写一个可以下载多页面的爬虫,如何将相对URL转为绝对URL,如何限速,...

    1fe1se 评论0 收藏0
  • Python爬虫之使用Fiddler+Postman+Python的requests模块爬取各国国旗

    摘要:流程作为上述过程的一个演示,我们使用的网址为页面如下在表单中输入德国,跳转后的页面如下我们可以发现,在搜索的结果中,会出现德国这个搜索结果。点击该搜索结果,跳转后的页面如下在这个页面中有我们需要的德国的国旗。 介绍   本篇博客将会介绍一个Python爬虫,用来爬取各个国家的国旗,主要的目标是为了展示如何在Python的requests模块中使用POST方法来爬取网页内容。  为了知道...

    laoLiueizo 评论0 收藏0
  • Python爬取"王者农药"英雄皮肤

    摘要:本篇就来教大家如何使用来爬取这些精美的英雄皮肤。有了英雄编号的对应关系,再找寻下英雄皮肤的链接规律。将图片保存下来,并以英雄名称皮肤序号方式命名效果展示最终的爬取效果如下图所示。 showImg(https://segmentfault.com/img/remote/1460000018627654); 0.引言 作为一款现象级游戏,王者荣耀,想必大家都玩过或听过,游戏里中各式各样的英...

    马龙驹 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<