文章目录
大纲
制作scrapy爬虫一共需要4步,(涉及关键脚本就3个)
新建项目(scrapy startproject xxx):新建一个爬虫项目
明确目标(编写items.py):明确你想要抓取的目标,对应网页元素
定义键和值的字典,当爬取到字段(相应的键)时,将值存进去。
制作爬虫(spiders/xxspider.py):制作爬虫开始爬取网页。
爬哪些数据,爬到之后怎么处理,url还是转到item.
存储内容(pipelines.py) :设计管道存储爬取内容。
官方文档
数据流¶
Scrapy中的数据流由执行引擎控制,如下所示:
- 这个 Engine 获取要从 Spider .
- 这个 Engine 在中安排请求 Scheduler 并请求下一个要爬行的请求。
- 这个 Scheduler 将下一个请求返回到 Engine .
- 这个 Engine 将请求发送到 Downloader ,通过 Downloader Middlewares (见
process_request()
) - 一旦页面完成下载, Downloader 生成响应(使用该页)并将其发送到引擎,并通过 Downloader Middlewares (见
process_response()
) - 这个 Engine 接收来自的响应 Downloader 并发送到 Spider 用于处理,通过 Spider Middleware (见
process_spider_input()
) - 这个 Spider 处理响应并向 Engine ,通过 Spider Middleware (见
process_spider_output()
) - 这个 Engine 将已处理的项目发送到 Item Pipelines ,然后将已处理的请求发送到 Scheduler 并请求可能的下一个爬行请求。
- 该过程重复(从步骤1开始),直到不再有来自 Scheduler .
scrapy 初试
pip install scrapy # 安装scrapy
scrapy # 查看当前文件夹的scrapy状态,以及指令。此时显示no-project
scrapy fetch 'http://www.baidu.com' # 使用下载器抓取网页,返回scrapy配置信息、抓取结果、抓取状态等信息。
scrapy shell 'http://www.baidu.com' # 交互界面。python语言。
print(response)
print(response.body)
# 创建项目
scrapy startporjects xxxx # 新建一个scrapy项目
cd xxx # 目录切换进去,即认为启动项目。
scrapy # 查看当前文件夹的scrapy状态,以及指令。 此时显示project:xxx
# 创建爬虫
scrapy genspider itcast "www.itcast.cn" # spider下会出现一个新的itcast.py文件
```PYTHON
class ItcastSpider(scrapy.Spider):
name = 'itcast' # 工程里该spider的识别名
allowed_domains = ['http://www.itcast.cn'] # 限定允许爬虫的域范围。
start_urls = ['http://www.itcast.cn/'] # 队列式爬取,逐一调用parse函数。可以是任意可迭代对象。
def parse(self, response): # 用于编辑命令处理响应文件。
print(response.body)
#pass
```
# 运行爬虫程序
scrapy check itcast # 检测是否正常运行,其中itcast
scrapy crawl itcast # 运行spider文件夹下,name='itcast'的函数。
# 查看当前工程下有哪些spider
scrapy list
一个鲜活的例子
解析网页
首先使用xpath解析网页,推荐xpath helper插件(chrome)进行解析。
网址http://www.itcast.cn/channel/teacher.shtml
解析的字段:
姓名://div[@class=‘li_txt’]/h3
职称://div[@class=‘li_txt’]/h4
信息://div[@class=‘li_txt’]/p
声明字段:配置item.py
再去定义item.py文件,为想要获取的信息,开辟存储字段。
class ScTestItem(scrapy.Item): # ORM的映射关系
# define the fields for your item here like:
# name = scrapy.Field() # 创建item的name字段,写爬虫文件的时候,可以用item['name'] = '爬取的内容',进行赋值。
# 老师的姓名
name = scrapy.Field() # 通过定义类属性,来定义类。
# 职称
title = scrapy.Field()
# 信息
info = scrapy.Field()
爬取网页解析结果:配置spider
【#1检测爬取结果】生成spider文件,调整脚本参数,检查爬取的结果是否跟预期一致。
【#2调用item实例存储】将字段结果,放进之前定义的item类中。【导包,生成item实例,赋值】
【#3调用管道】可以使用管道,存储结果
import scrapy
from sc_test.items import ScTestItem # 此时sc_test可以看作是python的pkg
class ItcastSpider(scrapy.Spider): # scrapy.Spider 提供了最基础的方法类。
# 爬虫名,teminal启动爬虫时需要的参数必须。
name = 'itcast'
# 爬取域范围,允许在此域名下进行爬取
allowed_domains = ['http://www.itcast.cn']
# 起始url列表,爬虫执行后第一批请求,将从这个列表里获取。
# 队列式爬取,逐一调用parse函数。
start_urls = ['http://www.itcast.cn/channel/teacher.shtml']
def parse(self, response): # 用于处理响应文件,对应网页解析结果。
# 1解析网页
node_list = response.xpath("//div[@class='li_txt']")
# 2先用字典保存,后期会用管道替换
items = []
for node in node_list:
# extract() 将下path对象转化为Unicode字符串,返回结果是列表。
name = node.xpath("./h3/text()").extract() # 从当前节点找h3
title = node.xpath("./h4/text()").extract()
info = node.xpath("./p/text()").extract()
#print(name[0]) # 检查爬到的结果,是否符合预期
#print(title[0])
# 2创建item字段对象,用来存储信息,可以视为字典。
item = ScTestItem()
item['name'] = name[0]
item['title'] = title[0]
item['info'] = info[0]
#3 返回数据给pipeline,函数持续运行、内存限制,相对于return的方式来说
# yield item
items.append(item)
return items # return 给引擎。如果return scrapy.Request(url) 则返回给调度器
关于return给引擎,引擎会直接显示在terminal上,此时可以使用以下方式将结果存入文件。
# 默认Unicode编码
# 存入json,可以使用网站解析json文件# https://www.json.cn/
scrapy crawl itcast -o itcast.json
scrapy crawl itcast -o itcast.jsonl
scrapy crawl itcast -o itcast.csv # 存入csv。注意英文逗号分隔符问题
scrapy crawl itcast -o itcast.xml
数据存储:配置pipelines.py
class ScTestPipeline:
def __init__(self):
self.f = open("itcast_pipeline.json",'w')
def process_item(self, item, spider): # 该方法必须,其余可以酌情增减
# with open("itcast_pipeline.json", "w") as f:
# f.write(item)
content = json.dumps(dict(item), ensure_ascii=False)+", \n "
self.f.write(content.encode("utf-8"))
return item # 一定要返回item告诉引擎处理完毕!
def close_spider(self, spider):
self.f.close()
class ScTestPipeline2: # 可以定义多个pipeline,在setting.py中设置优先级。
pass
#ITEM_PIPELINES = {
# 'sc_test.pipelines.ScTestPipeline': 300, # ScTestPipeline为管道的类名。
# 'sc_test.pipelines.ScTestPipeline2': 200 # 取值1——1000
#}
保存结果:创建data目录
在data目录下,运行脚本,将结果都存储在该目录下。