这篇文章我们来学习使用 scrapy 框架,首先介绍一下什么是 scrapy:scrapy 是一套基于 Twisted 的异步处理框架,纯 python 实现的爬虫框架,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页内容以及各种图片,非常之方便。
我们使用 wheel 来安装 scrapy 框架,scrapy 的 whl 包安装地址如下:https://www.lfd.uci.edu/~gohlke/pythonlibs/www.lfd.uci.edu
如果不知道自己的 python 支持哪个版本的 scrapy,可以打开 python,输入以下代码即可查询:
import pip
print(pip.pep425tags.get_supported())
找到对应版本后,将whl文件下载到 python 的 Scripts 的目录中,然后直接使用如下命令来进行安装:
pip install xxxxx.whl
scrapy 安装完成后先建立项目,输入 scrapy startproject xxx 即可。
项目建立完成后会生成以下目录:
我们就在此项目中编写爬虫爬取 http://www.itcast.cn/channel/teacher.shtml#ajavaee 网站中的所有老师信息,包括名称(name)、职位(title)和简介(info)。
首先打开setting.py文件,将 ROBOTSTXT_OBEY 属性改为 False,表示不遵守 robot 协议。
然后打开 items.py 文件,定义要爬取的信息:
为了将字段进行完整的格式化,scrapy 为我们提供了 Item 类,这些 Item 类可以让我们自己来指定字段 name、title 和 info。
接着在 spiders 文件夹中创建爬虫文件,使用如下命令进行:
scrapy genspider itcast itcast.cn
创建完成后,可以生成如下内容:
接下来我们就在这个文件中开始我们爬虫文件的编写。
首先导入相应的包:
# -*- coding: utf-8 -*-
import scrapy
#继承 Itcast.items 中的 ItcastItem 类
from Itcast.items import ItcastItem
然后编写 ItcastSpider 类:
class ItcastSpider(scrapy.Spider):
#爬虫名:启动爬虫时必须的参数(必选)
name = 'itcast'
#爬取域范围,允许爬虫在这个域名下进行爬取(可选)
allowed_domains = ['itcast.cn']
#起始url列表,爬虫执行后第一批请求,将从这个列表中获取
start_urls = ['http://www.itcast.cn/channel/teacher.shtml']
def parse(self, response):
node_list = response.xpath("//div[@class = 'li_txt']")
for node in node_list:
item = ItcastItem()
item['name'] = node.xpath('./h3/text()').extract()[0]
item['title'] = node.xpath('./h4/text()').extract()[0]
item['info'] = node.xpath('./p/text()').extract()[0]
yield item
其中 name 是爬虫的名字,启动爬虫时是必选的参数,allowed_domains 是爬取域范围,允许爬虫在这个域名下进行爬取,start_urls 是起始 url 列表,爬虫执行后第一批请求,将从这个列表中获取。
parse 函数也是必须,并且名字不能改变,否则引擎无法识别请求函数。在 parse 函数中,我们使用 xpath 来匹配信息,打开网页的开发者工具我们不难发现,所有老师的信息都存于各自的 "li_txt" 字段中:
因此我们用一个列表来寻找所有的 "li_txt" 字段,然后遍历其中的每一个结点,每次将找到的信息存入 item 对应的字段中,比如 title 字段存于 h4 标签中,那么 xpath 匹配就可以写为:
item['title'] = node.xpath('./h4/text()').extract()[0]
其中 .extract() 表示取文本,并且 xpath 出来的内容默认是列表形式,使用 [0] 选出其内容,并将其赋给 item['title'] 字段。
最后使用 yield 返回 item 数据给引擎,并且不会造成程序终止。yield 和 return 的区别在于:yield 返回执行结果并不中断程序执行,return 在返回执行结果的同时中断程序执行。
这样我们就可以使用 scrapy crawl itcast 命令来执行爬虫程序,但这样执行时数据只会出现在控制台中,如果我们想保存在 json 文件中需要使用管道文件 pipelines.py 。
在 pipelines 文件中首先导入 json 文件包:
import json
然后编写 ItcastPipeline 类:
class ItcastPipeline:
def __init__(self):
self.f = open("itcast.json", "w",encoding = 'utf-8')
def process_item(self, item, spider):
content = json.dumps(dict(item), ensure_ascii = False) + '\n'
self.f.write(content)
return item
def close_spider(self):
self.f.close()
首先定义 json 文件名,设置编码格式为 utf-8。item 格式的数据和字典形式类似但有不同,因此需要使用 dict() 方法来进行强转,然后再使用 json.dumps() 函数将字典形式的数据转换为字符串然后进行保存。
编写完 pipelines 文件后还要在 settings.py 文件中启动 Item Pipeline组件:
# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
'Itcast.pipelines.ItcastPipeline': 300,
}
分配给每个类的整型值,确定了他们运行的顺序,item 按数字从低到高的顺序,通过pipelines,通常将这些数字定义在 0-1000 范围内(数值越低,组件的优先级越高)
最后执行完毕后数据已存于 json 文件中:
本文只是 scrapy 的入门介绍,更多关于 scrapy 框架的知识请大家阅读:Scrapy入门教程 - Scrapy 0.24.6 文档scrapy-chs.readthedocs.io
最后本文的代码已经放在我的 github 中。https://github.com/feihun1/Pythongithub.com
END!此专栏持续更新~~欢迎大家点赞关注收藏!