还等什么,Scrapy启动,爬取开始!
目标网站
这里我们选取的目标网站是我常逛的干货集中营,而要爬取的就是她:
准确的说是她们,点击右上角“今日力荐”,可以跳转至往期“干货”,这里就不再贴图了,下面我们先简单说下Scrapy的架构和各部分功能。
架构说明
- Scrapy Engine(引擎): 负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等。
- Scheduler(调度器): 它负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎。
- Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理,
- Spider(爬虫):它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器).
- Item Pipeline(管道):它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方。
- Downloader Middlewares(下载中间件):你可以当作是一个可以自定义扩展下载功能的组件。
- Spider Middlewares(Spider中间件):你可以理解为是一个可以自定扩展和操作引擎和Spider中间通信的功能组件(比如进入Spider的Responses;和从Spider出去的Requests)
下面正式开始爬取工作。
创建项目
在工作目录shift+鼠标右键打开命令窗口,输入
scrapy startproject girls
之后一个名为“girls”的Scrapy项目就已经创建了。
打开PyCharm选择“open”方式打开已创建项目(这里不建议用把项目直接拖到PyCharm的方式打开,笔者因此遇到了已经下好的库无法载入的问题)。好了,让我们看下载入好的项目目录:
- scrapy.cfg: 项目的配置文件。
- girls/:项目的Python模块,后续代码在该目录添加。
- girls/items.py:项目中的item文件,保存爬取数据的容器。
- girls/pipelines.py:项目中的pipelines文件,用于处理获取的item。
- girls/settings.py:项目的设置文件。
- girls/spiders/:放置spider代码的目录。
明确目标
通过定义Item明确爬取目标。Item使用方法类似Python的字典,另外它还提供了额外保护机制防止拼写错误。这里只需要爬取图片,所以源码为:
import scrapy
class GirlsItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
# 图片url
image_urls = scrapy.Field()
# 图片信息
images = scrapy.Field()
- image_urls :图片url,爬虫(spider)抓取项目后会将对应url放入image_urls 中
- images :图片信息,图片下载完后更新到images结构中。它包含一个字典列表,其中包括下载路径、源抓取地址(image_urls中获得)、图片校验码,并且图片顺序与image_urls保持一致。如果下载失败,将记录错误信息,不再出现在images 中。
(这里用到了ImagesPipeline
,下面会详情讲)
制作爬虫
即编写girls/spiders/目录下的spider,spider类定义了爬取网站的逻辑,包括爬取的动作(如是否跟进链接),将网页内容提取成结构化数据(爬取Item)等。
这里建议通过命令直接生成spider文件:
点击打开PyCharm左下角Terminal窗口,输入
scrapy genspider girl gank.io/
在girls/spiders/目录下会生成对应girl.py文件,文件内容:
# -*- coding: utf-8 -*-
import scrapy
class GirlSpider(scrapy.Spider):
name = 'girl'
allowed_domains = ['gank.io/']
start_urls = ['http://gank.io//']
def parse(self, response):
pass
当然手动创建也是一样的效果,命令只是省去了书写样板代码过程。解释下代码:
- name:爬虫名字,必须且唯一,后续命令也以此名字为准。
- allowed_domains:爬虫允许的域名列表,域名不在列表时将不再跟进,可选。
- start_urls:爬取的url列表,未制定特定url时,爬虫从该列表开始爬取。
- parse(self, response):负责处理response并返回数据以及跟进的url(如果需要的话)。
在生成文件基础上添加我们的爬取逻辑:
# -*- coding: utf-8 -*-
import scrapy
from girls.items import GirlsItem
class GirlSpider(scrapy.Spider):
name = 'girl'
allowed_domains = []
start_urls = ['http://gank.io//']
def parse(self, response):
item = GirlsItem()
item["image_urls"] = response.xpath("/html/body/div[1]/div[1]/div[2]/p[1]/img/@src").extract()
print(item)
yield item
new_url = response.xpath("/html/body/div[1]/div[1]/div[1]/div[2]/p/a/@href").extract_first()
if new_url:
# 将相对路径转为绝对路径
new_url = response.urljoin(new_url)
print(new_url)
yield scrapy.Request(new_url, callback=self.parse)
简单说下代码中网页元素xpath获取方法,这里用的浏览器是Chrome。
- 在想要获取xpath的网页元素上点击右键,选择检查;
-
在被选择的标签上右键,Copy →Copy XPath,
粘贴至代码中即可。
存储内容
这里主要指设计管道( item pipeline)存储爬取到的内容,即上边提到的ImagesPipeline
。
ImagesPipeline即Scrapy提供的一个item pipeline,用来下载某个特定项目中的图片并保存到本地,并且具有如下特点:
- 将所有下载的图片转换成通用的格式(JPG)和模式(RGB)
- 避免重新下载最近已经下载过的图片
- 缩略图生成
- 检测图像的宽/高,确保它们满足最小限制
这里如果需要生成缩略图,请下载Pillow库,下载方法“安装篇”里有提到。
使用ImagesPipeline除了items.py中的代码外,只需要在settings.py配置相关设置即可,贴上源码根据需求设置:
# 开启图片管道 ImagesPipeline地址项目实际地址为准
ITEM_PIPELINES = {'scrapy.pipelines.images.ImagesPipeline': 300}
# 设置图片存储目录,一个有效的文件夹
IMAGES_STORE = 'girls/bitmap'
# 图片开始下载延时
# DOWNLOAD_DELAY = 0.25
#缩略图的尺寸,设置这个值就会产生缩略图
# IMAGES_THUMBS = {
# 'small': (50, 50),
# 'big': (200, 200),
# }
# 90天的图片失效期限
# 避免下载最近已经下载的图片
# IMAGES_EXPIRES = 90
# 滤出小图片
# IMAGES_MIN_HEIGHT = 110
# IMAGES_MIN_WIDTH = 110
注意:开启图片管道设置ImagesPipeline地址应以项目实际地址为准这里是scrapy.pipelines.images.ImagesPipeline
,这点官方中文文档有误。
另外如果需要定制图片管道请参考官方文档的 实现定制图片管道,这里不再赘述。
开始爬取(✪ω✪)
虽然直接在命令行中输入命令即可开始爬取,但是既然我们使用了PyCharm不妨使用IDE的方式:
- 在scrapy.cfg文件同级目录创建start.py文件,输入
# -*- coding:utf-8 -*-
from scrapy import cmdline
cmdline.execute("scrapy crawl girl".split())
-
右上角
左边或者Run
菜单中选择 -
弹出菜单点击加+号,选择
Python
-
做如下设置
设置完,OK结束。
-
点击右上角
即可开始爬取。
稍等片刻图片就爬取完啦,如图⁄(⁄⁄•⁄ω⁄•⁄⁄)⁄
总结
综上可见一个标准的Scrapy爬取流程是:
- 创建项目 (scrapy startproject xxx):新建一个新的爬虫项目
- 明确目标 (编写items.py):明确你想要抓取并存储的目标
- 制作爬虫 (spiders/xxspider.py):制作爬虫,明确爬取的网页元素及爬取动作
- 存储内容 (pipelines.py):设计管道存储爬取内容
那么以上各个部分在爬取过程中是如何运行和配合的呢?
结合上面提到的架构图可知:
- Scrapy引擎从爬虫(Spider)文件中获取开始的url,并交由调度器和下载器处理,处理好后得到的response交还爬虫;
- 爬虫根据爬虫文件中设置的爬取动作,爬取
image_urls
并储存至items中,需要跟进的url提交给引擎; - Scrapy引擎将items中
image_urls
交给管道(Item Pipeline)处理,跟进的url交给调度器; - 管道这里根据ImagesPipeline及settings.py中的设置处理并将
image_urls
通过引擎交由调度器和下载器下载,项目会在这个特定的管道阶段保持“locker”的状态,直到完成图片的下载(或者由于某些原因未完成下载),下载完后,图片信息更新到images
中。之后调度器根据需跟进的url从1.
开始循环,直到调度器中不再有任何request,爬取结束。
参考文章:
官方文档:https://scrapy-chs.readthedocs.io/zh_CN/0.24/index.html
Scrapy 入门教程:http://www.runoob.com/w3cnote/scrapy-detail.html
Scrapy爬取美女:https://www.cnblogs.com/qiyeboy/p/5428240.html