scrapy爬取doutula动图笔记

写在前面:记录在使用scrapy框架爬取动态图片时遇到得问题和不熟悉的地方。主要问题:多页爬取的规则匹配及process_item方法的编写

scrapy爬取doutula动图笔记_第1张图片

第一步:soogif.py的编写

  • 首先到导入所需要的第三方模块
from ..items import SoofigItem  # 导入保存数据的容器
from scrapy.spiders import CrawlSpider, Rule  # CrawlSpider可与Rule规则结合使用实现翻页爬取操作
from scrapy.linkextractors import LinkExtractor  # 提取html中符合规则的链接
  • rules是一个列表或元组,保存的是Rule规则
    start_urls = ['https://www.doutula.com/article/list/?page=1']
# allow参数表示允许提取符合此正则的链接
# follow=True表示跟随匹配到的链接继续匹配,可匹配到所有的页面
# 写正则表达式时注意将?进行转义,否则匹配不到内容
# callback回调parse_img方法,不能回调parse方法,因为parse方法会被CrawlSpider类自动调用
    rules = [
        Rule(LinkExtractor(allow=r'https://www.doutula.com/article/list/\?page=\d'), follow=True, callback="parse_img"),
    ]
  • parse_img方法负责解析html
    def parse_img(self, response):
        divs = response.xpath('//div[contains(@class,"col-sm-9")]/a')
        for div in divs:
            folder_name = div.xpath('./div[@class="random_title"]/text()').get()
            url = div.xpath('.//img[contains(@class,"img-responsive")]/@data-original').getall()
            yield SoofigItem(folder_name=folder_name, url=url)
# yield 返回获取到的数据供pipelines.py文件使用,用于下载图片
  • item定义
# url为图片的链接,folder_name为表情包的分类,用于生成文件夹名字
import scrapy
class SoofigItem(scrapy.Item):
    url = scrapy.Field()
    folder_name = scrapy.Field()

第二步:pipelines.py的编写

  • 第一次尝试,使用继承scrapy自带的ImagesPipeline类,重写get_media_requests,file_path及item_completed方法下载图片。后来才查到这样做保存不了gif格式的图片,因此表情包就没有了灵魂
    scrapy爬取doutula动图笔记_第2张图片
from scrapy.pipelines.images import ImagesPipeline
from scrapy.exceptions import DropItem
class ImagePipeline(ImagesPipeline):
    def get_media_requests(self, item, info):
        '''通过抓取的item对象获取图片信息,并创建Request请求对象添加调度队列,等待调度执行下载'''
        for i in range(4):
            yield scrapy.Request(url=item['url'][i])

    def file_path(self, request, response=None, info=None):
        '''返回图片下载后保存的名称,没有此方法Scrapy则自动给一个唯一值作为图片名称'''
        url = request.url
        file_name = url.split("/")[-1]
        return file_name

    def item_completed(self, results, item, info):
        ''' 下载完成后的处理方法,可将图片保存位置item容器'''
        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
  • results参数中的内容为:
 [(True, {'url': 'https://img-bss.csdn.net/201803191642534078.png', 
          'path': '201803191642534078.png', 
          'checksum': 'cc1368dbc122b6762f3e26ccef0dd105'}
 )]
  • 此方法失败后,查阅博客发现需要重写process_item方法
from scrapy.pipelines.images import ImagesPipeline
from scrapyStudy import settings  # 用于获取settings中配置的常量
import os
from urllib.request import urlretrieve   # 用于下载图片
class ImagePipeline(ImagesPipeline):
   '''自定义图片存储类'''
   # 重写process_item方法可下载动态图片,get_media_requests及file_path方法不被执行
   def process_item(self, item, spider):
       dir_path = '%s/%s' % (settings.IMAGES_STORE, item['folder_name'])
       if not os.path.exists(dir_path):
           os.makedirs(dir_path)
       for image_url in item['url']:
           us = image_url.split('/')[-1]
           file_path = '%s/%s' % (dir_path, us)
           if os.path.exists(file_path):
               continue
           urlretrieve(image_url, file_path)  # 传入图片链接及文件位置
       return item

第三步:settings.py的配置

# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla / 5.0(Windows NT 10.0;Win64;x64) AppleWebKit / 537.36(KHTML, likeGecko)' \
             'Chrome / 71.0.3578.98Safari / 537.36'
ROBOTSTXT_OBEY = False
ITEM_PIPELINES = {
    'scrapyStudy.pipelines.ImagePipeline': 299,
}
IMAGES_STORE = './images' # 必须配置,否则找不到保存路径

执行scapy crawl soogif 运行爬虫,这里将spider的名字记为soogif,是因为好像以前这个网站是这个名字,记不清了。哎,是真的烦,soogif跟doutula是两个不同的网站。

scrapy爬取doutula动图笔记_第3张图片

总结

暂时没有遇到反爬的问题,也没有用到代理,在优化方法没有做任何考虑,只是单纯的能将表情包下载到本地。在调试的过程中,学到的是如何快速的解决问题,并理清思路和熟练编写代码。
接下来就是愉快的表情包大战了。

你可能感兴趣的:(爬虫,爬虫)