zoukankan      html  css  js  c++  java
  • 爬虫实战篇---使用Scrapy框架进行汽车之家宝马图片下载爬虫

    (1)、前言

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

    FilePipeline

    ImagesPipeline

    (2)、使用Scrapy内置的下载方法的好处

    1、可以有效避免重复下载

    2、方便指定下载路径

    3、方便格式转换,例如可以有效的将图片转换为png 或jpg

    4、方便生成缩略图

    5、方便调整图片大小

    6、异步下载,高效率

    (3)、较为传统的Scrapy框架图片下载方式

    1、创建项目:scrapy startproject baoma---cd baoma --创建爬虫scrapy genspider spider car.autohome.com.cn

    2、使用pycharm打开项目

    改写settings.py

    不遵守robots协议

    设置请求头

    开启pipelines.py

    改写spider.py

     1 # -*- coding: utf-8 -*-
     2 import scrapy
     3 from ..items import BaomaItem
     4 
     5 class SpiderSpider(scrapy.Spider):
     6     name = 'spider'
     7     allowed_domains = ['car.autohome.com.cn']
     8     start_urls = ['https://car.autohome.com.cn/pic/series/65.html']
     9 
    10     def parse(self, response):
    11         #SelecorList类型
    12         uiboxs = response.xpath('//div[@class = "uibox"]')[1:] #第一个我们不需要
    13         for uibox in uiboxs:
    14             catagory = uibox.xpath('.//div[@class = "uibox-title"]/a/text()').get()
    15             urls = uibox.xpath('.//ul/li/a/img/@src').getall()
    16             #遍历列表,并将列表中的某一项执行函数操作,再将函数的返回值以列表的形式返回
    17             #map()
    18             # for url in urls:
    19             #     # url = 'https:' + url
    20             #     # print(url)
    21             #     #方法二:
    22             #     url = response.urljoin(url)
    23             #     print(url)
    24                 #方法三:
    25                 #将列表中的每一项进行遍历传递给lambda表达式,并执行函数中的代码,再以返回值以列表形式进行返回,结果是map对象,接着使用list转换为列表
    26             urls = list(map(lambda url:response.urljoin(url),urls))
    27             item = BaomaItem(catagory = catagory,urls = urls)
    28             yield item

    改写pipelines.py

     1 # -*- coding: utf-8 -*-
     2 
     3 # Define your item pipelines here
     4 #
     5 # Don't forget to add your pipeline to the ITEM_PIPELINES setting
     6 # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
     7 import os
     8 from urllib import request
     9 
    10 class BaomaPipeline(object):
    11     def __init__(self):
    12         self.path = os.path.join(os.path.dirname(__file__), 'images') #os.path.dirname()获取当前文件的路径,os.path.join()获取当前目录并拼接成新目录
    13         if not os.path.exists(self.path):  # 判断路径是否存在
    14             os.mkdir(self.path)
    15 
    16     def process_item(self, item, spider):
    17         #分类存储
    18         catagory = item['catagory']
    19         urls = item['urls']
    20 
    21         catagory_path = os.path.join(self.path,catagory)
    22         if  not os.path.exists(catagory_path): #如果没有该路径即创建一个
    23             os.mkdir(catagory_path)
    24 
    25         for url in urls:
    26             image_name = url.split('_')[-1] #以_进行切割并取最后一个单元
    27             request.urlretrieve(url,os.path.join(catagory_path,image_name))
    28 
    29 
    30         return item

    新建测试py(main.py)

    1 #author: "xian"
    2 #date: 2018/6/14
    3 from scrapy import cmdline
    4 cmdline.execute('scrapy crawl spider'.split())

    运行结果:(我们成功获取了以catagory分类并以图片地址_后的参数作为图片名的图片)

    Scrapy框架提供了两个中间件1、下载文件的Files pipeline 和下载图片的Image pipeline

    下载文件的Files pipeline

    使用步骤:

    1、定义好一个item,然后定义两个属性file_urls 和 files . file_urls是用来存储需要下载的文件的url链接,列表类型

    2、当文件下载完成后,会把文件下载的相关信息存储到item的files属性中。例如:下载路径,下载url 和文件的效验码

    3、再配置文件settings.py中配置FILES_STORE,指定文件下载路径

    4、启动pipeline,在ITEM_PIPELINES中设置scrapy.pipelines.files.FilesPipeline :1

    下载图片的Images Pipeline

    使用步骤:

    1、定义好一个item,然后定义两个属性image_urls 和 images. image_urls是用来存储需要下载的文件的url链接,列表类型

    2、当文件下载完成后,会把文件下载的相关信息存储到item的images属性中。例如:下载路径,下载url 和文件的效验码

    3、再配置文件settings.py中配置FILES_STORE,指定文件下载路径

    4、启动pipeline,在ITEM_PIPELINES中设置scrapy.pipelines.images.ImagesPipeline :1

    (4)、使用Images_pipeline进行图片下载(还是以汽车之家图片为例)

    改写settings.py

    开启自己定义的中间件

    改写pipelines,py

     1 # -*- coding: utf-8 -*-
     2 
     3 # Define your item pipelines here
     4 #
     5 # Don't forget to add your pipeline to the ITEM_PIPELINES setting
     6 # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
     7 import os
     8 from urllib import request
     9 from scrapy.pipelines.images import ImagesPipeline
    10 import settings
    11 
    12 class BaomaPipeline(object):
    13     def __init__(self):
    14         self.path = os.path.join(os.path.dirname(__file__), 'images') #os.path.dirname()获取当前文件的路径,os.path.join()获取当前目录并拼接成新目录
    15         if not os.path.exists(self.path):  # 判断路径是否存在
    16             os.mkdir(self.path)
    17 
    18     def process_item(self, item, spider):
    19         #分类存储
    20         catagory = item['catagory']
    21         urls = item['urls']
    22 
    23         catagory_path = os.path.join(self.path,catagory)
    24         if  not os.path.exists(catagory_path): #如果没有该路径即创建一个
    25             os.mkdir(catagory_path)
    26 
    27         for url in urls:
    28             image_name = url.split('_')[-1] #以_进行切割并取最后一个单元
    29             request.urlretrieve(url,os.path.join(catagory_path,image_name))
    30 
    31 
    32         return item
    33 
    34 
    35 class BMWImagesPipeline(ImagesPipeline):  # 继承ImagesPipeline
    36     # 该方法在发送下载请求前调用,本身就是发送下载请求的
    37     def get_media_requests(self, item, info):
    38         request_objects = super(BMWImagesPipeline, self).get_media_requests(item, info)  # super()直接调用父类对象
    39         for request_object in request_objects:
    40             request_object.item = item
    41         return request_objects
    42 
    43     def file_path(self, request, response=None, info=None):
    44         path = super(BMWImagesPipeline, self).file_path(request, response, info)
    45         # 该方法是在图片将要被存储时调用,用于获取图片存储的路径
    46         catagory = request.item.get('catagory')
    47         images_stores = settings.IMAGES_STORE #拿到IMAGES_STORE
    48         catagory_path = os.path.join(images_stores,catagory)
    49         if not os.path.exists(catagory_path): #判断文件名是否存在,如果不存在创建文件
    50             os.mkdir(catagory_path)
    51         image_name = path.replace('full/','')
    52         image_path = os.path.join(catagory_path,image_name)
    53         return image_path

    运行结果展示:

    通过对比我们可以直观感受到下载速度明显提高。

    下面我们对图片进行优化,获取高清图片

    通过分析缩略图和高清图的url,我们发现缩略图只是多了t_罢了

    缩略图地址:https://car3.autoimg.cn/cardfs/product/g24/M08/2F/9E/t_autohomecar__wKgHIVpogfqAIlTbAAUzcUgKoGY701.jpg

    高清图地址:https://car3.autoimg.cn/cardfs/product/g24/M08/2F/9E/autohomecar__wKgHIVpogfqAIlTbAAUzcUgKoGY701.jpg

    (5)、下面我们获取所有的高清图片

    传统思路如下:找到更多获取接口的url,进入详情页--找分页接口(显然这种情况会大大提高我们的工作量,下面我们使用Scrapy框架中的CrawlSpider进行爬取,因为CrawlSpider只要指定响应的规则,爬虫会自动进行爬取,省事省力!)

    我们首先分析下url的规律:

    https://car.autohome.com.cn/pic/series/65-1.html(更多的第一页url)

    https://car.autohome.com.cn/pic/series/65-1-p2.html(更多的第二页url)

    改写spider.py

     1 # -*- coding: utf-8 -*-
     2 import scrapy
     3 from scrapy.spiders import CrawlSpider ,Rule#导入CrawlSpider模块 需改写原来的def parse(self,response)方法
     4 from scrapy.linkextractor import LinkExtractor #导入链接提取模块
     5 from ..items import BaomaItem
     6 
     7 
     8 class SpiderSpider(CrawlSpider):
     9     name = 'spider'
    10     allowed_domains = ['car.autohome.com.cn']
    11     start_urls = ['https://car.autohome.com.cn/pic/series/65.html']
    12 
    13     rules = {
    14         Rule(LinkExtractor(allow=r'https://car.autohome.com.cn/pic/series/65.+'),callback= 'parse_page',follow=True),
    15 
    16     } #如需要进行页面解释则使用callback回调函数 因为有下一页,所以我们需要跟进,这里使用follow令其为True
    17 
    18 
    19     def parse_page(self, response): #页面解析函数
    20         catagory = response.xpath('//div[@class = "uibox"]/div/text()').get()
    21         srcs = response.xpath('//div[contains(@class,"uibox-con")]/ul/li//img/@src').getall()
    22         srcs = list(map(lambda x:x.replace('t_',''),srcs)) #map(函数,参数二),将参数二中的每个都进行函数计算并返回一个列表
    23         # urls = {}
    24         # for src in srcs:
    25         #     url = response.url.join(src)
    26         #     urls.append(url)
    27         srcs = list(map(lambda x:response.urljoin(x),srcs))
    28         yield BaomaItem(catagory=catagory,image_urls = srcs)

    运行结果(展示):(我们成功获取了高清图片到本地)

  • 相关阅读:
    快递员—你惹不起的“组织”
    BF的真正意义
    读书:《四点起床-最养生和高效的时间管理》
    你究竟有多想成功?汗水铸造巨星(中英结合版含视频)
    美国女生给我的六个惊诧(转)
    据说是世界上最健康的作息
    少走弯路的十条忠告
    编程—休息片刻的好处
    学电脑必懂的53个英文单词和缩写
    四件在我步入职业软件开发生涯那天起就该知道的事情
  • 原文地址:https://www.cnblogs.com/518894-lu/p/9181448.html
Copyright © 2011-2022 走看看