​Python爬虫 --- 2.5 Scrapy之汽车之家爬虫实践

原文链接:https://www.fkomm.cn/article/2018/8/7/32.html

目的

Scrapy框架为文件和图片的下载专门提供了两个Item Pipeline 它们分别是:

  • FilePipeline
  • ImagesPipeline

这里主要介绍ImagesPipeline!!

目标分析:

这次我们要爬的是汽车之家:car.autohome.com.cn。最近喜欢吉利博越,所以看了不少这款车的资料。

我们就点开博越汽车的图片网站:

https://car.autohome.com.cn/pic/series/3788.html

pic1.png

传统的Scrapy框架图片下载

Scrapy 框架的实施:

1.创建scrapy项目和爬虫:

$ scrapy startproject Geely
 $ cd Geely
 $ scrapy genspider BoYue car.autohome.com.cn

2.编写items.py:

import scrapy

 class GeelyItem(scrapy.Item):
     # define the fields for your item here like:
     # name = scrapy.Field()

     # 存储图片分类
     catagory = scrapy.Field()

     # 存储图片地址
     image_urls = scrapy.Field()

     # ImagesPipeline 
     images = scrapy.Field()

3.编写Spider:

# -*- coding: utf-8 -*-
 import scrapy

 #导入CrawlSpider模块 需改写原来的def parse(self,response)方法
 from scrapy.spiders import CrawlSpider ,Rule

 #导入链接提取模块
 from scrapy.linkextractors import LinkExtractor 
 from Geely.items import GeelyItem

 class BoyueSpider(CrawlSpider):
     name = 'BoYue'
     allowed_domains = ['car.autohome.com.cn']
     start_urls = ['https://car.autohome.com.cn/pic/series/3788.html']

     #如需要进行页面解释则使用callback回调函数 因为有下一页,所以我们需要跟进,这里使用follow令其为True
     rules = {
         Rule(LinkExtractor(allow=r'https://car.autohome.com.cn/pic/series/3788.+'), callback= 'parse_page', follow=True),
     } 

     def parse_page(self, response):
         catagory = response.xpath('//div[@class = "uibox"]/div/text()').get()
         srcs = response.xpath('//div[contains(@class,"uibox-con")]/ul/li//img/@src').getall()

         #map(函数,参数二),将参数二中的每个都进行函数计算并返回一个列表
         srcs = list(map(lambda x:x.replace('t_',''),srcs))
         srcs = list(map(lambda x:response.urljoin(x),srcs))
         yield GeelyItem(catagory=catagory, image_urls = srcs)

4.编写PIPELINE:

    import os
     from urllib import request

     class GeelyPipeline(object):

         def __init__(self):
             #os.path.dirname()获取当前文件的路径,os.path.join()获取当前目录并拼接成新目录
             self.path = os.path.join(os.path.dirname(__file__), 'images')

             # 判断路径是否存在
             if not os.path.exists(self.path):  
                 os.mkdir(self.path)

         def process_item(self, item, spider):

             #分类存储
             catagory = item['catagory']
             urls = item['image_urls']

             catagory_path = os.path.join(self.path, catagory)

             #如果没有该路径即创建一个
             if not os.path.exists(catagory_path): 
                 os.mkdir(catagory_path)

             for url in urls:
                 #以_进行切割并取最后一个单元
                 image_name = url.split('_')[-1] 
                 request.urlretrieve(url,os.path.join(catagory_path,image_name))

             return item

5.编写settings.py

    BOT_NAME = 'Geely'

     SPIDER_MODULES = ['Geely.spiders']
     NEWSPIDER_MODULE = 'Geely.spiders'

     # Obey robots.txt rules
     ROBOTSTXT_OBEY = False

     ITEM_PIPELINES = {
        'Geely.pipelines.GeelyPipeline': 1,
     }

6.让项目跑起来:

$ scrapy crawl BoYue

7.结果展示:

pic2.png
pic3.png

使用Images_pipeline进行图片下载

使用步骤:

  1. 定义好一个item,然后定义两个属性 image_urls 和 images。 image_urls是用来存储需要下载的文件的url链接,列表类型;
  2. 当文件下载完成后,会把文件下载的相关信息存储到item的images属性中。例如:下载路径,下载url 和文件的效验码;
  3. 再配置文件settings.py中配置FILES_STORE,指定文件下载路径;
  4. 启动pipeline,在ITEM_PIPELINES中设置自定义的中间件!!!

具体步骤

在上面的基础上修改

1.修改settings.py

    ITEM_PIPELINES = {
        # 'Geely.pipelines.GeelyPipeline': 1,
        # 'scrapy.pipelines.images.ImagesPipeline': 1,
        'Geely.pipelines.GeelyImagesPipeline': 1,
     }

     #工程根目录
     project_dir = os.path.dirname(__file__)
     #下载图片存储位置
     IMAGES_STORE = os.path.join(project_dir, 'images')

2.改写pipelines,py

    # -*- coding: utf-8 -*-

     # Define your item pipelines here
     #
     # Don't forget to add your pipeline to the ITEM_PIPELINES setting
     # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html

     import os
     from urllib import request

     from scrapy.pipelines.images import ImagesPipeline
     from Geely import settings

     # class GeelyPipeline(object):

     #     def __init__(self):
     #         #os.path.dirname()获取当前文件的路径,os.path.join()获取当前目录并拼接成新目录
     #         self.path = os.path.join(os.path.dirname(__file__), 'images')

     #         # 判断路径是否存在
     #         if not os.path.exists(self.path):  
     #             os.mkdir(self.path)

     #     def process_item(self, item, spider):

     #         #分类存储
     #         catagory = item['catagory']
     #         urls = item['image_urls']

     #         catagory_path = os.path.join(self.path, catagory)

     #         #如果没有该路径即创建一个
     #         if not os.path.exists(catagory_path): 
     #             os.mkdir(catagory_path)

     #         for url in urls:
     #             #以_进行切割并取最后一个单元
     #             image_name = url.split('_')[-1] 
     #             request.urlretrieve(url,os.path.join(catagory_path,image_name))

     #         return item

     # 继承ImagesPipeline
     class GeelyImagesPipeline(ImagesPipeline):

         # 该方法在发送下载请求前调用,本身就是发送下载请求的
         def get_media_requests(self, item, info):

             # super()直接调用父类对象
             request_objects = super(GeelyImagesPipeline, self).get_media_requests(item, info)
             for request_object in request_objects:
                 request_object.item = item
             return request_objects

         def file_path(self, request, response=None, info=None):

             path = super(GeelyImagesPipeline, self).file_path(request, response, info)

             # 该方法是在图片将要被存储时调用,用于获取图片存储的路径
             catagory = request.item.get('catagory')

             # 拿到IMAGES_STORE
             images_stores = settings.IMAGES_STORE
             catagory_path = os.path.join(images_stores, catagory)

             #判断文件名是否存在,如果不存在创建文件
             if not os.path.exists(catagory_path): 
                 os.mkdir(catagory_path)

             image_name = path.replace('full/','')
             image_path = os.path.join(catagory+'/',image_name)

             return image_path

3.让项目跑起来:

$ scrapy crawl BoYue

将会得到与原来相同的结果!!!!


相关文章和视频推荐

圆方圆学院汇集 Python + AI 名师,打造精品的 Python + AI 技术课程。 在各大平台都长期有优质免费公开课,欢迎报名收看。

公开课地址:https://ke.qq.com/course/362788?flowToken=1007319

加入python学习讨论群 78486745 ,获取资料,和广大群友一起学习。

原文链接:https://www.fkomm.cn/article/2018/8/7/32.html

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小尘哥的专栏

小程序(3):授权登录

判断是否授权,如果没有,则显示授权按钮。注意上面的open-type="getUserInfo",这个会自动调起授权框。看一下js

1994
来自专栏每日一篇技术文章

OpenGLES_入门01_创建第一个工程

今天就带这个大家把OpenGL 用原始的方法创建一下,之后我们会使用苹果给我封装的类做,简化操作!

1132
来自专栏你不就像风一样

网络爬虫之Url含有中文如何转码

1052
来自专栏Python学习心得

​Python爬虫 --- 2.3 Scrapy 框架的简单使用

原文链接:https://www.fkomm.cn/article/2018/8/3/28.html

740
来自专栏24K纯开源

用Qt写软件系列一:QCacheViewer(浏览器缓存查看器)

介绍      Cache技术广泛应用于计算机行业的软硬件领域。该技术既是人们对新技术探讨的结果,也是对当前软硬件计算能力的一种妥协。在浏览器中使用cache技...

2505
来自专栏大魏分享(微信公众号:david-share)

从PowerVM,KVM到Docker:存储池的配置与调优---第一篇终结(第3子篇)

VIOC 上的 VSCSI 性能调优 在本实验的 VIOC 中,一个磁盘对应 4 条 VSCSI 路径。查看磁盘默认的属性 ; # lsattr -El hdi...

5086
来自专栏美团技术团队

Android Hook技术防范漫谈

背景 当下,数据就像水、电、空气一样无处不在,说它是“21世纪的生产资料”一点都不夸张,由此带来的是,各行业对于数据的争夺热火朝天。随着互联网和数据的思维深入人...

5627
来自专栏ytkah

laravel用crud之index列出产品items

  前面我们说了laravel用crud修改产品items-新建resource controller和routing,现在我们要把产品items罗列出来,需要...

1273
来自专栏程序猿DD

Jenkins Pipeline插件十大最佳实践!

Jenkins Pipeline 插件对于 Jenkins 用户来说可以让用户能够改变游戏规则。基于 Groovy 中的领域特定语言(DSL),Pipeline...

51310
来自专栏向治洪

Android App瘦身实战

随着业务的快速迭代增长,不断引入新的业务逻辑代码、图片资源和第三方SDK等,很多app都面临一个一个结果,app越来越大,甚至很多无用的代码,包体积的增大带来了...

3668

扫码关注云+社区

领取腾讯云代金券