scrapy框架
(使用之前如果没有相应的模块需要安装,然后import scrapy)
- scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架,可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。
- scrapy最初是为了页面抓取(更准确的来说是网络抓取)所设计的,也可以应用在获取API所返回的数据或者通用的网络爬虫。
整体架构
-
Scrapy Engine(引擎): 负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等。(scrapy已经实现,不用手写)
-
Scheduler(调度器): 负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎。(scrapy已经实现,不用手写)
-
Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理。(scrapy已经实现,不用手写)
-
Spider(爬虫):它负责处理所有Responses,从中分析提取数据,获取Item(手写定义)字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器)。(需要手写爬虫)
-
Item Pipeline(管道):它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方。(需要手写)
-
Downloader Middlewares(下载中间件):你可以当作是一个可以自定义扩展下载功能的组件。
-
Spider Middlewares(Spider中间件):你可以理解为是一个可以自定扩展和操作引擎和Spider中间通信的功能组件(比如进入Spider的Responses;和从Spider出去的Requests。
使用scrapy框架
使用scrapy抓取一个网站一共需要四个步骤:
1、创建一个scrapy项目;
2、定义item容器(需求);
3、编写爬虫(获取需求);
4、存储内容。
一、创建一个scrapy项目
scrapy startproject 项目名
这里我们采用命令行的形式来创建scrapy工程
scrapy startproject animation
文件目录如下(斜体为文件夹):
- anmation
- animation
- _ pycahe_
- 空文件夹
- spiders
- __ pycahche__
- 空文件夹
- __ init__.py
- __ pycahche__
- __ init__.py
- items.py
- middlewares.py
- pipelines.py
- settings.py
- _ pycahe_
- scrapy.cfg
文件说明:
- animation
文件 | 作用 |
---|---|
scrapy.cfg | 项目的主配置信息。(真正爬虫相关的配置信息在settings.py文件中) |
items.py | 设置数据存储模板,用于结构化数据,以及设置需要查找的内容。 |
pipelines.py | 数据处理行为,如:爬虫爬完后返回的结果如果想用 txt、excel、mysql 等格式存储,就在这里写 |
settings.py | 配置文件,如:递归的层数、并发数,延迟下载等 |
spiders | 爬虫目录,如:创建文件,编写爬虫规则 |
二、定义item容器
检查想要爬取的网站内容,并在items.py中编写存储item的名字。
item 是保存爬取到的数据容器,其使用的方法和python中的字典类似,并且提供了额外的保护机制来避免拼写错误导致的未定义的字段错误。
这里以爬取樱花动漫网站日本人气动漫名为例:
在items.py中编写
class AnimationItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
Popular_Cartoon_Name = scrapy.Field() #编写内容
pass
三、编写爬虫
使用命令创建一个爬虫模板,在模板的基础上修改
scrapy genspider 爬虫名称.py 域名
scrapy genspider animation_scrapy www.imomoe.io
爬虫文件模板内容展示:
import scrapy
class AnimationScrapySpider(scrapy.Spider):
name = 'animation_scrapy' #爬虫名
allowed_domains = ['www.imomoe.io'] #允许爬虫爬取的网站范围
start_urls = ['http://www.imomoe.io/'] #爬取的网站地址
def parse(self, response):
'''
是一个回调方法,起始url请求成功后,会回调这个方法
:param response: 响应结果
:return:
'''
pass
在scrapy中是使用一种基于Xpath和CSS的表达机制:scrapy selector(从网页中提取需要信息的一种工具,类似于正则表达式)
selector是一种选择器,他有四个基本的方法:
- xpath() :传入Xpath表达式,返回该表达式所对应的所有节点的selector list列表
- css():传入css表达式,返回该表达式所对应的所有节点的selector list 列表
- re(): 根据传入的正则表达式对数据进行提取,返回unicode字符串list列表
- extract():序列化该节点为unicode字符串并返回list
(这里使用Xpath来查找网页中需要的内容)
Xpath是一门在网页中查找特定信息的语言,所以用Xpath来筛选数据要比使用正则表达式容易些。
例:
<1> /html/head/title:选择HTML文档中< head>标签内的< title>元素
<2>/html/head/title/text():选择上面提到的< title>元素的文字
<3>//td: 选择网页中所有的< td>标签元素
<4>div[@class = “mine”]: 选择所有具有class="mine"属性的div元素
编写爬虫模板
1.从items.py中导入item,以保存数据
2.编写Xpath,获取网页信息
3.实例化导入的item,将信息存入对应的字典映射中。
import scrapy
from animation.items import AnimationItem #导入items.py中的AnimationItem
class AnimationScrapySpider(scrapy.Spider):
name = 'animation_scrapy'
allowed_domains = ['www.baidu.com']
start_urls = ['http://www.imomoe.io/so.asp?page=1&fl=0&dq=%C8%D5%B1%BE&pl=hit'] #目前只爬取一页
def parse(self, response):
results = response.xpath('//div[@class="pics"]/ul/li/h2') #查找需要的网页内容
items = []
for result in results:
item = AnimationItem() #实例化一个对象
item['name'] = result.xpath('a/text()').extract()
item['url'] = result.xpath('a/@href').extract()
items.append(item)
return items
在编写完之后为了初步验证程序有没有什么语法错误等,可以使用 scrapy shell 命令进行初步的测试,在 prompt中输入:
scrapy shell “网址”
scrapy shell "http://www.imomoe.io/so.asp?page=1&fl=0&dq=%C8%D5%B1%BE&pl=hit"
没有报错则正确运行,然后检查你的item存储是否正确,这里演示一个:
response.xpath('//div[@class="pics"]/ul/li/h2/a/text()').extract()
输出:
Out[2]:
['东京食尸鬼第四季',
'东京食尸鬼第三季',
'一拳超人',
'缘之空',
'日在校园',
'死神',
'妖精的尾巴',
'东京食尸鬼第二季',
'海贼王',
'进击的巨人',
'七原罪第二季',
'东京食尸鬼',
'魁拔3战神崛起',
'偶像活动第三季',
'精灵使的剑舞OVA',
'JOJO的奇妙冒险',
'神鹤丹丹',
'阿U第三季',
'茶啊二中',
'假面骑士Drive',
'神马镇的浮云街',
'虫师续章第二季']
如上述所示代码没有明显的bug。
四、储存数据
当Item在Spider中被收集之后,它将会被传递到Item Pipeline,这些Item Pipeline组件按定义的顺序处理Item,对其进行筛选存储。
Item Pipeline的典型应用:
1.验证爬取的数据(检查item包含某些字段,比如说name字段)
2.查重(并丢弃)
3.将爬取结果保存到文件或者数据库中
对pipelines.py文件进行修改时,其中process_item()方法必须实现
item pipiline组件是一个独立的Python类,为了启用Item Pipeline组件,必须将它的类添加到 settings.py文件ITEM_PIPELINES 配置中,则需要将settings.py中的相关注释去掉。
例:
# Configure item pipelines
# See https://doc.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
'animation.pipelines.AnimationPipeline': 300,
}
分配给每个类的整型值,确定了他们运行的顺序,item按数字从低到高的顺序,通过pipeline,通常将这些数字定义在0-1000范围内(0-1000随意设置,数值越低,组件的优先级越高)
编写pipelines.py文件:
将数据保存在一个文件夹中:
class AnimationPipeline(object):
def process_item(self, item, spider):
name = item['name']
url = item['url']
with open('animation.txt', 'a') as f:
f.write(str(name))
f.write('\t')
f.write(str(url)+'\n') #write方法只能写入str类型而url和name是list类型,所以要转义。
return item
调用单个爬虫:
scrapy crawl 爬虫名 #爬虫名为在spide文件夹中.py爬虫程序定义的name属性
例:
scrapy crawl animation_scrapy
(note:注意要切换到项目的根目录下运行,因为程序是根据scrapy.cfg文件来运行的。)
以上代码写完保存运行的结果:
生成一个.txt 文件,内容为:
[‘东京食尸鬼第四季’] [’/view/7501.html’]
[‘东京食尸鬼第三季’] [’/view/7208.html’]
[‘一拳超人’] [’/view/1409.html’]
[‘缘之空’] [’/view/2883.html’]
[‘日在校园’] [’/view/5082.html’]
[‘死神’] [’/view/4548.html’]
[‘妖精的尾巴’] [’/view/4101.html’]
[‘东京食尸鬼第二季’] [’/view/1716.html’]
[‘海贼王’] [’/view/189.html’]
[‘进击的巨人’] [’/view/4225.html’]
[‘七原罪第二季’] [’/view/870.html’]
[‘东京食尸鬼’] [’/view/2149.html’]
[‘魁拔3战神崛起’] [’/view/1806.html’]
[‘偶像活动第三季’] [’/view/1805.html’]
[‘精灵使的剑舞OVA’] [’/view/1804.html’]
[‘JOJO的奇妙冒险’] [’/view/1801.html’]
[‘神鹤丹丹’] [’/view/1803.html’]
[‘阿U第三季’] [’/view/1802.html’]
[‘茶啊二中’] [’/view/1800.html’]
[‘假面骑士Drive’] [’/view/1798.html’]
[‘神马镇的浮云街’] [’/view/1797.html’]
[‘虫师续章第二季’] [’/view/1796.html’]