我们准备爬取的网站:https://alpha.wallhaven.cc/random
分析该网站图片的标签: 这是一张图片的标签
xpath解析一下:
//figure/@data-wallpaper-id 可以获取图片的编号集合
再根据图片的编号获取到整个标签
//figure[@data-wallpaper-id="316105"] (这里的 316105 就是图片的编号)
就可以获取整个 figure 标签,然后就可以抓取需要的信息了,具体字段分析见后面爬虫部分
命令: scrapy startproject wallhavenSpider
目录结构如下:
通常需要编辑的几个py有:settings.py 和 items.py 和 pipelines.py
USER_AGENT = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)"
启用ITEM_PIPELINES 配置,本次我们就使用默认生成的item即可。
ITEM_PIPELINES = {
'wallhavenSpider.pipelines.WallhavenspiderPipeline': 300,
}
#编写自定义配置字段
IMAGES_STORE = "H:\\python_workspace\\scrapy\\imgaedownload"
该文件就是设置我们需要存储的字段信息。
class WallhavenspiderItem(scrapy.Item):
# define the fields for your item here like:
# 图片的id
imageId = scrapy.Field()
# 图片的缩略图路径
imageThumbnailUrl = scrapy.Field()
# 图片的分辨率
imageSize = scrapy.Field()
# 图片的下载路径
imageDownloadUrl = scrapy.Field()
# 图片的tag的路径
imageTagUrl = scrapy.Field()
# 图片保存的路径
#imagePath = scrapy.Field()
pipelines.py 我们在编写完爬虫再编写。
进入spiders目录,使用命令:scrapy genspider imageInfoDownload "alpha.wallhaven.cc"
会在spiders目录下创建一个 爬虫程序的模板。
首先确定爬取网站网址:https://alpha.wallhaven.cc/random
我们来进入下一页,查看网址变化,确定该网站的分页的字段:
https://alpha.wallhaven.cc/random?page=x
通过page 字段来实现分页,那么我们可以根据 page 值的变化,爬取每页的信息
在文章最开始,图片信息已经分析了一下。
那么就具体使用xpath 将图片信息拿出来
(1)获取一个图片的整体标签体:
//figure[@data-wallpaper-id="+id+"]
这里的id 是一个图片的id标识,到时候我们得到一页中所有图片id,分页爬取
那我们先获取一个 id 进行测试。
(2)图片的缩略图的路径
//figure[@data-wallpaper-id="378330"]/img/@data-src
(3)图片的分辨率
//figure[@data-wallpaper-id="378330"]/div/span/text()
(4)图片的真实路径
这个路径,需要点击图片进入图片的详情页才能看到。
但是,经过发现这些图片的前缀路径都是一致的,变化的仅是 图片的id。
我们就可以使用拼接的方式,拿到图片的id将图片的真实路径拼接出来。
# -*- coding: utf-8 -*-
import scrapy
from wallhavenSpider.items import WallhavenspiderItem
class ImageinfodownloadSpider(scrapy.Spider):
"""
爬取图片信息
"""
name = 'imageInfoDownload'
allowed_domains = ['alpha.wallhaven.cc']
#拼接请求分页的路径
url = 'https://alpha.wallhaven.cc/random?page='
offset = 1
reqUrl = url + str(offset)
start_urls = [reqUrl]
def parse(self, response):
"""
解析response
:param response:
:return:
"""
imageId_list = response.xpath("//figure/@data-wallpaper-id")
for imageid in imageId_list:
#创建一个新的 item
item = WallhavenspiderItem()
id = imageid.extract()
#图片的编号
item['imageId'] = id
#根据图片id进行解析
imageinfo = response.xpath("//figure[@data-wallpaper-id="+id+"]")
for imginfo in imageinfo:
# 图片的缩略图
item['imageThumbnailUrl'] = imginfo.xpath("./img/@data-src").extract()[0]
#图片的分辨率
item['imageSize'] = imginfo.xpath("./div/span/text()").extract()[0]
item['imageTagUrl'] = imginfo.xpath('./div/a[@title="Tags"]/@href').extract()[0]
#https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-634130.jpg
#截取图片的后缀
imgSuffix = item['imageThumbnailUrl'].split('.')[-1]
item['imageDownloadUrl'] = 'https://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-'+id+'.'+imgSuffix
#交给管道文件进行处理
yield item
# 分页请求,控制页码变化
if self.offset < 13320:
self.offset += 1
# else:
# raise "结束工作"
#处理完一页,再次发送分页请求
yield scrapy.Request(self.url + str(self.offset), callback=self.parse)
运行测试爬虫:scrapy crawl imageInfoDownload
看是否正常爬取。
pipelines 文件就是用来处理 item(数据)的地方
我们现在的需求是下载图片
scrapy 中提供了一个对图片下载的 pipline 文件:ImagesPipeline
引入该pipline 的方式:
from scrapy.pipelines.images import ImagesPipeline
在该ImagesPipeline 中提供了两个方法,支持下载的功能
get_media_requests 和 item_completed
看下具体代码实现:
# -*- 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
#引入settings.py 的配置项
import scrapy
import json
from scrapy.utils.project import get_project_settings
from scrapy.pipelines.images import ImagesPipeline
import os
class WallhavenspiderPipeline(ImagesPipeline):
#获取在 settings 文件中的配置项
IMAGE_SOURCE = get_project_settings().get('IMAGES_STORE')
def get_media_requests(self, item, info):
image_url = item['imageDownloadUrl'] #拿到图片的真实路径
yield scrapy.Request(image_url)
def item_completed(self, result, item, info):
image_path = [x["path"] for ok, x in result if ok]
os.rename(self.IMAGE_SOURCE + "\\" + image_path[0], self.IMAGE_SOURCE + "\\" + item["imageId"] + ".jpg")
item['imageDownloadUrl'] = image_path
return item
os.rename(self.IMAGE_SOURCE + "\\" + image_path[0], self.IMAGE_SOURCE + "\\" + item["imageId"] + ".jpg")
这一句主要将 图片改名称
其中这两个方法的编写,基本可以作为模板代码使用。只需要修改部分参数即可。
scrapy提供了图片下载的方式很方便,也可以自己写下载图片的方法。
具体参考:http://scrapy-chs.readthedocs.io/zh_CN/latest/topics/images.html
如果需要查看源码:https://github.com/gengzi/wallhavenSpider