返回介绍

10.3 图片下载和翻页的另一种方法

发布于 2025-04-21 19:15:29 字数 3579 浏览 0 评论 0 收藏

10.3.1 Scrapy 图片下载简介

深层网页的爬取

如果想把我爱我家二手房房源对应经纪人的图片下载下来,就需要首先了解 Scrapy 下载及处理图片的方法。

在爬取项目时,如果同时也想保存对应的图片或者下载文件,Scrapy 提供了一个可重用的 item pipelines,一般称为 Images Pipeline 和 Files Pipeline。

这两种 pipeline 都实现了以下特性:避免重新下载最近已经下载过的数据;指定存储文件路径。

Images Pipeline 还有一些专门处理图片的功能:将所有下载的图片转换成通用的格式(jpg)和模式(RGB);生成缩略图;检测图像的宽/高,确保它们满足最小限制。

另外,Scrapy 处理图片需要使用 Pillow 这个库来生成缩略图,并将图片归一化为 jpeg/rgb 格式,因此为了使用图片管道,需要安装 Pillow 库。在命令行中使用 pip 安装即可。

>pip install pillow 

下面用我爱我家爬虫实例演示如何用 Scrapy 下载图片。

10.3.2 我爱我家房源图片下载

这里在上节爬虫代码基础上,增加下载我爱我家二手房房源经纪人图片的功能。

第一步,修改 Item,增加图片和 URL 字段。

import scrapy
class Pachong2Item(scrapy.Item): 
    ...#这里省略之前定义的代码 
    image_urls = scrapy.Field() 
images=scrapy.Field() 

第二步,在设置中启用 Images Pipeline。为了启用 Images Pipeline,需要在项目设置文件 settings.py 中添加 ITEM_PIPELINES。对于 Images Pipeline,在项目的 settings.py 文件中添加如下代码。

ITEM_PIPELINES = {'scrapy.pipelines.images.ImagesPipeline': 1}

第三步,设置存储图片的文件夹。

这里为爬取的图片设置一个有效的文件夹,用来存储下载的图片。如果没有设置,图片下载管道将保持禁用状态。在项目设置文件 settings.py 中添加如下代码。

IMAGES_STORE='D:\\pics' 

这里配置保存图片的位置为 D 盘下的 pics 文件夹。图片存储使用它们 URL 的 SHA1 hash 值作为文件名。

第四步,修改 spider。从解析函数中解析图片 URL 并添加到 Item,这里在上节代码基础上,只需修改解析房源详情页面的 parse_detail 方法,添加解析经纪人图片的 URL。

def parse_detail(self, response):
    item = response.meta['item'] 
    item['agent'] = response.xpath('//*[@class="daikansty"]/ul/li[2]' 
                                   '/h3/a/text()').extract_first() 
    item['image_urls'] = response.xpath('//*[@class="daikansty"]/ul' 
                                        ' /li[1]/a/img/@src').extract() 
yield item 

请注意,这里 Images Pipeline 用到的是图片的 URL 列表,代码中不需要使用 extract_first() 或者列表切片方法。

这样就完成了下载经纪人图片的代码修改。

10.3.3 翻页的另一种方法

上节的翻页是通过在 start_urls 里面直接构造 URL 列表完成的,这一节来看看翻页的另一种方法,就是在 parse 解析函数中解析下一页的 URL,然后再继续请求这个 URL。使用这种翻页方法,start_urls 只需要设置为第一页即可。

start_urls = ['http://bj.5i5j.com/exchange/n1'] 

下面打开我爱我家二手房房源列表第一页,拉右侧滚动条到翻页位置(见图 10-3),分析一下如何获取下一页的 URL。

图 10-3 我爱我家二手房房源列表第一页

这里的“下一页”按钮指向的 URL 正是第二页的 URL,可以提取“下一页”这个元素指向的 URL,然后继续请求这个 URL,以完成翻页。假如翻到最后一页,页面里没有“下一页”这个元素,返回值就是 None,为了让爬虫能够停止请求,只需在请求下一页 URL 之前做一个判断,只要下一页 URL 不为 None 值,就可以继续请求翻页。

这里仅需修改 parse 函数,其他代码与上节完全相同,不再重复演示。在 parse 函数后面增加 3 行代码,实现解析下页 URL,判断其是否为 None,不为 None 的情况下请求这个 URL。

def parse(self, response):
    ... 
    yield scrapy.Request(detail_url, meta={'item':item},  
                         callback=self.parse_detail) 
    #增加下面 3 行代码,解析下一页的 URL 
    next_url = response.xpath( 
               '//div[@class="pageSty rf"]/a[1]/@href').extract_first() 
    if next_url:    #如果有下一页 
        next_url = response.urljoin(next_url)  
        #使用 callback 指定 parse 为回调函数 
        yield scrapy.Request(next_url, callback=self.parse)

看到这里使用了两次 yield,第一次 yield 请求详情页并设置 parse_detail 为解析函数;第二次 yield 请求列表页下一页的 URL,并设置 parse 函数为回调函数,也就是说请求下一个列表页后继续使用 parse 函数来解析。对解析 next_url,这使用了 extract_first() 这个序列化的方法,这样如果没有下一页,就会返回 None 值,然后用 if 做判断;如果有下一页,就继续请求。

从上面翻页的例子中可以看到,在同一个方法中可以多次使用 yield 返回数据,这在使用 Scrapy 编写爬虫过程中,经常用到;还要注意网页中解析出的 URL 经常是不完整的相对路径 URL,不要忘记使用 response.urljoin 方法将其转换为绝对路径的 URL。

之所以要讲解第二种翻页方法是因为在一些场景下,可能不能事先了解一个网站的总页数,这时候,第二种翻页方法就能把全部数据爬取下来。当然了,在学习了下一章 CrawlSpider 后,读者会发现使用 CrawlSpider 爬取,代码会更简洁。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。