写在前面:记录在使用scrapy框架爬取动态图片时遇到得问题和不熟悉的地方。主要问题:多页爬取的规则匹配及process_item方法的编写
from ..items import SoofigItem # 导入保存数据的容器
from scrapy.spiders import CrawlSpider, Rule # CrawlSpider可与Rule规则结合使用实现翻页爬取操作
from scrapy.linkextractors import LinkExtractor # 提取html中符合规则的链接
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"),
]
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文件使用,用于下载图片
# url为图片的链接,folder_name为表情包的分类,用于生成文件夹名字
import scrapy
class SoofigItem(scrapy.Item):
url = scrapy.Field()
folder_name = scrapy.Field()
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
[(True, {'url': 'https://img-bss.csdn.net/201803191642534078.png',
'path': '201803191642534078.png',
'checksum': 'cc1368dbc122b6762f3e26ccef0dd105'}
)]
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
# 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是两个不同的网站。
暂时没有遇到反爬的问题,也没有用到代理,在优化方法没有做任何考虑,只是单纯的能将表情包下载到本地。在调试的过程中,学到的是如何快速的解决问题,并理清思路和熟练编写代码。
接下来就是愉快的表情包大战了。