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)

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

  • 相关阅读:
    微信二维码 场景二维码 用于推送事件,关注等 注册用户 ,经过测试
    简单的 Helper 封装 -- CookieHelper
    简单的 Helper 封装 -- SecurityHelper 安全助手:封装加密算法(MD5、SHA、HMAC、DES、RSA)
    Java反射机制
    Windows Azure Web Site (13) Azure Web Site备份
    Windows Azure Virtual Machine (1) IaaS用户手册
    Windows Azure Web Site (1) 用户手册
    Windows Azure Web Site (12) Azure Web Site配置文件
    Windows Azure Web Site (11) 使用源代码管理器管理Azure Web Site
    Windows Azure Web Site (10) Web Site测试环境
  • 原文地址:https://www.cnblogs.com/518894-lu/p/9181448.html
Copyright © 2011-2022 走看看