如何编写一个简易网络爬虫
感谢小臣投稿
本文将简述网络爬虫及其工作流程,结合个人实践,简单介绍如何使用HttpClient、HtmlParser第三方jar工具包,编写一个简易的网络爬虫。
网络爬虫简述及流程架构
网络爬虫,又叫网页蜘蛛,是一种按照一定的规则逻辑,自动地抓取网络信息的程序或者脚本。
在当今网络时代,信息量爆炸性增长,不同领域、不同背景的用户对信息的获取有不同的需求。人们无法在这么海量信息中及时有效地获取到极具针对性的信息。搜索引擎一定程度上也无法根据语义查询,满足用户定制化需求。诸如此类各种原因,网络爬虫应运而生。
“寄宿”在网络服务器节点上的网络爬虫,一般工作流程如下,
流程上,爬虫程序从种子URL开始,根据设定的规则、策略(如广度优先搜索、最佳优先搜索、深度优先搜索)对目标站点网页进行爬取。
一般架设起来的爬虫系统,主要有如下几种结构,
(1)主从式
Master节点维护待抓取URL队列,它负责每次将URL分发到不同的Slave节点上,而各Slave节点则负责实际的网页下载工作。同时,主节点也负责调解各个Slave节点的负载情况。
(2)对等式
通过哈希计算,每一台抓取节点都可以从待抓取在URL队列中获取URL。
思路:对该URL或其主域名计算hash值(java中的hashCode方法,也是其中的一种实现),简单一点就是通过哈希函数mod m(其中m是服务器的数量,以上图为例,m为3),计算得到取模余数,这就是处理该URL的主机编号了。
(3)对等式改良版
将URL的主域名进行哈希运算,映射在一个范围之间的某个数。而将这个范围平均的分配给m台服务器。如果某一台服务器出现问题,那么本该由该服务器负责的网页则按照顺时针顺延,由下一台服务器进行抓取。
比如,一个域hash映射范围是8个数,那么4个节点平均每个节点承载2个数范围。url哈希运算得到值3,那么就分发到第二个节点上。如果该节点宕机了,那么第三个节点就会承接该请求。如果是末级节点宕了,那么应该有算法处理转发给首节点,形成节点的环形结构。
实例具体实现
通过部分伪代码(颜色对应实现代码),介绍案例,讲解细节实现,
案例1:抓取某体育直播网站上的球队队徽、队旗图标
//控制台输入指令,从配置文件匹配到种子URL
String reqUrl = PropertiesOperateUtils.getReqUrlByCommand(command);
//获取图片节点
NodeList imgNodeList = getImgTagsByUrl(reqUrl);
List<String> imgUrlTagList =parserNodeList2ImgsList(imgNodeList);
//将获取的图片url,遍历写入磁盘
FileOpearateUtils.writeImgIntoHardDisk(imgUrlTagList,null);
函数部分代码如下,
/**
* 通过reqUrl获取图片标签节点List
* @param reqUrl
* @return
*/
static NodeList getImgTagsByUrl(String reqUrl) {
Parser parser = ParseHtmlUtils.getParserByUrl(reqUrl);
returne HtmlTag.getImgTags(parser);
}
/**
* 根据图片节点解析出对应的图片URL
* @param nodeList
* @return
*/
private static List<String> parserNodeList2ImgsList(NodeList nodeList) {
List<String> imgUrlList = new ArrayList<String>();
if (nodeList != null) {
for (int i = 0; i < nodeList.size(); i++) {
ImageTag imageTag = (ImageTag)nodeList.elementAt(i);
String imgUrl = imageTag.getImageURL();
//集合中不存在的,才保存,避免相同、重复的图片url
if (!imgUrlList.contains(imgUrl))
imgUrlList.add(imgUrl);
}
}
return imgUrlList;
}
method:writeImgIntoHardDisk{
//...省略部分,贴出核心逻辑
ExecutorService executorService = Executors.newCachedThreadPool();
for (String urlString : parserNodeList2ImgsList) {
executorService.execute(new DownLoadImgThread(RandomStringUtils.randomAlphabetic(5), urlString));//通过写入流,将图片写入磁盘
}
executorService.shutdown();
}
战利品展示:
图示 爬取下载的部分球队队徽、队旗
本案例中,可以通过HttpClient对目标url发起客户端请求或HtmlParser转换解析器直接获取url网页文本,后者相对方便。
调用HtmlParser解析中的函数getImgTags完成对文本图片标签的过滤、提取(也可以通过HtmlParser工具jar包中的NodeFilter 过滤器,指定目标标签过滤筛选)。
案例2:抓取需要客户端登录状态的网站信息
本案例,是通过公司内部wiki网页进行爬取的。
//一句话不合,马上就上代码
HttpClient client = postLogin(loginUrl); //创建客户端连接对象,提交登录
String tarPage = getTargetPage(reqUrl, client);//同一个客户端对象 parsePage(tarPage);//解析获取到的目标文本
主要介绍几处不同点:
wiki网站记录公司内部日常交流资料,是需要OA账号完成登录下才能访问的。所以,在爬取这类需要登录的网页时,首先必须完成账号的登录步骤。
大概步骤如下:
1、借助开发工具,获取登录页面输入框标签的id;
2、通过 List<NameValuePair> parms 封装账号信息;
3、httpClient发起post请求,提交至目标验证url,账号信息正确通过验证;
4、使用同一个httpClient客户端对象(必须是通过验证那个),再次对所要爬取的种子URL发起类似案例1的请求,解析出所要的文本标签内容即可;
- Spring Cloud中的API网关服务Zuul
- MYSQL | 企业整合解决方案之mysql集群搭建-主从配置
- Spring Cloud中Feign配置详解
- Spring Cloud中Feign的继承特性
- JavaScript 常用方法总结
- Spring Cloud中声明式服务调用Feign
- Spring Cloud中Hystrix仪表盘与Turbine集群监控
- 轻量级压力测试工具 - AB
- Spring Cloud中Hystrix的请求合并
- Spring Cloud中Hystrix的请求缓存
- mysql主从复制配置
- Spring Cloud系列勘误
- Spring Cloud Stream使用细节
- Redis3 对集群进行重新分片
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 「干货」你需要了解的六种渲染模式
- 分享两个操作Java枚举的实用方法
- 从零开始强化学习:在Python笔记本中设计和解决一个任务
- 基于深度学习的新闻推荐算法(1)
- 以复现图表的方式来学习一篇文章
- 盘点 Python 10 大常用数据结构(上篇)
- (长文预警) 你还在烦工作中碰到的拖拽问题?一个框架jiejue
- 重磅 | 青藤与腾讯安全隆重举办容器安全平台新品战略合作发布会
- 如何使用强化学习玩21点?
- 这3个Scikit-learn的特征选择技术,能够有效的提高你的数据预处理能力
- 使用神经网络解决拼图游戏
- 用机器学习预测收益
- 一种基于深度学习的低成本细胞生物学研究方法
- 从零搭建Spring Boot脚手架(2):增加通用的功能
- Qt官方示例-K线图