分布式爬虫设计和实现
1.总体设计
功能模块划分:
数据抓取引擎
1.1 调研市面上爬虫框架或库
pholcus
colly
gocrawl
开发工具:goland
开发语言:golang
数据存储:ElasticSearch
前端展示:使用Go语言标准模板库实现http的数据显示部分
爬取内容:相亲类网站的数据
爬虫算法:城市列表 --城市--用户信息,从种子页面开始爬取页面
爬虫的实现步骤:单机版 -- 并发版--分布式版
难点:动态页面内容解析,模拟登录,突破反爬机制
一、单机版步骤
1.获取初始页面的内容
2.提取页面内容关键信息(本项目采用正则表达式)
css选择器
xpath
正则表达式
3.提取城市和url链接,将城市打印
4.整体架构
通过分析,针对城市列表,城市,用户,我们分别抽象出对应的解析器
内容 | 对应解析器 |
城市列表 | 城市列表解析器 |
--城市列表解析器
城市--城市解析器
用户--用户解析器
解析器Parser定义
输入:utf-8编码格式的文本
输出:Request{URL,对应的Parser}列表,Item列表
Engine引擎
城市列表解析器
城市解析器
用户信息解析器
二、并发版爬虫架构
并发版的爬虫
介绍一下Scheduler调度模块,负责将任务队列中的众多Request请求分配个不同的Worker来解析
不同模块之间的数据传输采用的是Channel通道,并发版的实现在于Scheduler调度器的实现
1.将Fetcher模块和Parser模块整合成Worker模块,然后针对每个Worker创建一个go协程,提高开发效率
2.当把种子url传递给Engine引擎后,会解析出更多的requests,
3.Scheduler调度模块负责将任务队列中的多个Request请求,分发给后端的Worker来解析,
4.Worker解析出来的Item结果再回传给Engine引擎
5.Engine引擎将解析结果Item进行保存,暂时只是打印了item数据
期间遇到了两个问题
channel死等待:最后看这个问题
Fetcher模块被卡住:可能是网站服务器针对爬虫做了连接限速策略,在Fetcher模块拉取网页数据时,可采用设置User-Agent和ratelimit的方式
三、并发版爬虫的队列版本(Work队列和Request队列)
每个Worker对应创建一个Worker队列,并反向注册到Scheduler调度模块中,
Scheduler调度模块在收到Request请求以后投递到Request队列中
Scheduler调度模块在收到WorkerReady完成通知时,会将其投递到Worker队列中
当Request队列和Worker队列中都有元素时,进行如下操作
1.从Requests队列中获取头部的request请求
2.从Worker队列中获取worker对应的channel通道(或称队列)
3.将request请求投递到worker对应的channel通道中,worker就能处理了。
四、数据存储和展示
项目进行到现在,爬虫系统能够解析珍爱网的数据了,我们需要把解析到的数据存储起来
Elastic search 全文搜索引擎 介绍
快速的存储,搜索,分析海量数据
用户:维基百科,github,stack overflow
Elastic Search 能做什么?
1.存储我们爬取的数据
2.无需建表,配置字段
3.json格式的文档
4.全文搜索
寻找:男,有房,有车
寻找:女,年轻漂亮-》身材好-》身材指标好,三维,体重,身高,哈哈
原声支持,不需要写代码,不需要拼接查询语句
go操作Elastic Search
使用的elastic第三方库
https://github.com/olivere/elastic
写程序要的就是持续优化代码,每隔一段时间就自己找下程序的毛病,看看还有那些地方可以进行优化的。
五、分布式爬虫
分布式系统
多个节点、消息传递、完成特定需求
节点具有私有存储,易于开发
消息传递:REST,RPC,中间件(消息队列)
一般来说
对外:REST
模块内部:RPC 主流的有三种jsonrpc grpc thrift
模块之间:中间件
自有协议 docker/libchan
NATS streaming
gocricuit
根据自己需求