文章大纲
一, 网络爬虫基本介绍
二, java 常见爬虫框架介绍
三, webCollector 实战
四, 项目源码下载
五, 参考文章
一, 网络爬虫基本介绍
1. 什么是网络爬虫
网络爬虫(又被称为网页蜘蛛, 网络机器人, 在社区中间, 更经常的称为网页追逐者), 是一种按照一定的规则, 自动地抓取万维网信息的程序或者脚本. 另外一些不常使用的名字还有蚂蚁, 自动索引, 模拟程序或者蠕虫.
2. 常见问题介绍
爬虫可以爬取 Ajax 信息么?
网页上有一些异步加载的数据, 爬取这些数据有两种方法: 使用模拟浏览器(问题 1 中描述过了), 或者分析 Ajax 的 http 请求, 自己生成 Ajax 请求的 url, 获取返回的数据. 如果是自己生成 Ajax 请求, 使用开源爬虫的意义在哪里? 其实是要用开源爬虫的线程池和 URL 管理功能(比如断点爬取).
如果我已经可以生成我所需要的 Ajax 请求(列表), 如何用这些爬虫来对这些请求进行爬取?
爬虫往往都是设计成广度遍历或者深度遍历的模式, 去遍历静态或者动态页面. 爬取 Ajax 信息属于 deep Web(深网)的范畴, 虽然大多数爬虫都不直接支持. 但是也可以通过一些方法来完成. 比如 WebCollector 使用广度遍历来遍历网站. 爬虫的第一轮爬取就是爬取种子集合 (seeds) 中的所有 url. 简单来说, 就是将生成的 Ajax 请求作为种子, 放入爬虫. 用爬虫对这些种子, 进行深度为 1 的广度遍历(默认就是广度遍历).
爬虫支持多线程么, 爬虫能用代理么, 爬虫会爬取重复数据么, 爬虫能爬取 JS 生成的信息么?
能不能爬 JS 生成的信息和爬虫本身没有太大关系. 爬虫主要是负责遍历网站和下载页面. 爬 JS 生成的信息和网页信息抽取模块有关, 往往需要通过模拟浏览器 (htmlunit,selenium) 来完成. 这些模拟浏览器, 往往需要耗费很多的时间来处理一个页面. 所以一种策略就是, 使用这些爬虫来遍历网站, 遇到需要解析的页面, 就将网页的相关信息提交给模拟浏览器, 来完成 JS 生成信息的抽取.
爬虫怎么保存网页的信息?
有一些爬虫, 自带一个模块负责持久化. 比如 webmagic, 有一个模块叫 pipeline. 通过简单地配置, 可以将爬虫抽取到的信息, 持久化到文件, 数据库等. 还有一些爬虫, 并没有直接给用户提供数据持久化的模块. 比如 crawler4j 和 webcollector. 让用户自己在网页处理模块中添加提交数据库的操作. 至于使用 pipeline 这种模块好不好, 就和操作数据库使用 ORM 好不好这个问题类似, 取决于你的业务.
爬虫怎么爬取要登陆的网站?
这些开源爬虫都支持在爬取时指定 cookies, 模拟登陆主要是靠 cookies. 至于 cookies 怎么获取, 不是爬虫管的事情. 你可以手动获取, 用 http 请求模拟登陆或者用模拟浏览器自动登陆获取 cookie.
爬虫怎么抽取网页的信息?
开源爬虫一般都会集成网页抽取工具. 主要支持两种规范: CSS SELECTOR 和 XPATH. 至于哪个好, 这里不评价.
明明代码写对了, 爬不到数据, 是不是爬虫有问题, 换个爬虫能解决么?
如果代码写对了, 又爬不到数据, 换其他爬虫也是一样爬不到. 遇到这种情况, 要么是网站把你封了, 要么是你爬的数据是 JavaScript 生成的. 爬不到数据通过换爬虫是不能解决的.
爬虫速度怎么样?
单机开源爬虫的速度, 基本都可以讲本机的网速用到极限. 爬虫的速度慢, 往往是因为用户把线程数开少了, 网速慢, 或者在数据持久化时, 和数据库的交互速度慢. 而这些东西, 往往都是用户的机器和二次开发的代码决定的.
爬虫被网站封了怎么办?
爬虫被网站封了, 一般用多代理 (随机代理) 就可以解决. 但是这些开源爬虫一般没有直接支持随机代理 ip 的切换.
二, java 常见爬虫框架介绍
1. Apache Nutch
(1)官方网站: http://nutch.apache.org/
(2)是否支持分布式: 是
(3)可扩展性: 中. Apache Nutch 并不是一个可扩展性很强的爬虫, 它是一个专门为搜索引擎定制的网络爬虫, 虽然 Apache Nutch 具有一套强大的插件机制, 但通过定制插件并不能修改爬虫的遍历算法, 去重算法和爬取流程.
(4)适用性: Apache Nutch 是为搜索引擎定制的爬虫, 具有一套适合搜索引擎的 URL 维护机制(包括 URL 去重, 网页更新等), 但这套机制并不适合目前大多数的精抽取业务(即结构化数据采集).
(5)上手难易度: 难. 需要使用者熟悉网络爬虫原理, hadoop 开发基础及 Linux shell, 且需要熟悉 Apache Ant
2. WebCollector
(1)官方网站: https://github.com/CrawlScript/WebCollector
(2)可扩展性: 强
(3)适用性: WebCollector 适用于精抽取业务.
(4)上手难易度: 简单
3. WebMagic
(1)官方网站: http://git.oschina.net/flashsword20/webmagic
(2)是否支持分布式: 否
(3)可扩展性: 强
(4)适用性: WebMagic 适用于精抽取业务.
(5)上手难易度: 简单.
4. Crawler4j
(1)官方网站: https://github.com/yasserg/crawler4j
(2) 是否支持分布式: 否
(3)可扩展性: 低. Crawler4j 实际上是一个单机版的垂直爬虫, 其遍历算法是一种类似泛爬的算法, 虽然可以添加一些限制, 但仍不能满足目前大部分的精抽取业务. 另外, Crawler4j 并没有提供定制 http 请求的接口, 因此 Crawler4j 并不适用于需要定制 http 请求的爬取业务(例如模拟登陆, 多代理切换).
(4)上手难易度: 简单
三, WebCollector 实战
1. WebCollector 与传统网络爬虫的区别
传统的网络爬虫倾向于整站下载, 目的是将网站内容原样下载到本地, 数据的最小单元是单个网页或文件. 而 WebCollector 可以通过设置爬取策略进行定向采集, 并可以抽取网页中的结构化信息.
2. WebCollector 与 HttpClient,Jsoup 的区别
WebCollector 是爬虫框架, HttpClient 是 Http 请求组件, Jsoup 是网页解析器(内置了 Http 请求功能).
一些程序员在单线程中通过迭代或递归的方法调用 HttpClient 和 Jsoup 进行数据采集, 这样虽然也可以完成任务, 但存在两个较大的问题:
(1)单线程速度慢, 多线程爬虫的速度远超单线程爬虫.
(2)需要自己编写任务维护机制. 这套机制里面包括了 URL 去重, 断点爬取 (即异常中断处理) 等功能.
WebCollector 框架自带了多线程和 URL 维护, 用户在编写爬虫时无需考虑线程池, URL 去重和断点爬取的问题.
3. WebCollector 能够处理的量级
WebCollector 目前有单机版和 Hadoop 版(WebCollector-Hadoop), 单机版能够处理千万级别的 URL, 对于大部分的精数据采集任务, 这已经足够了. WebCollector-Hadoop 能够处理的量级高于单机版, 具体数量取决于集群的规模.
4. WebCollector 的遍历
WebCollector 采用一种粗略的广度遍历, 但这里的遍历与网站的拓扑树结构没有任何关系, 用户不需要在意遍历的方式.
网络爬虫会在访问页面时, 从页面中探索新的 URL, 继续爬取. WebCollector 为探索新 URL 提供了两种机制, 自动解析和手动解析.
5. 代码实战
maven 引入依赖
- <dependencies>
- <dependency>
- <groupId>cn.edu.hfut.dmic.webcollector</groupId>
- <artifactId>WebCollector</artifactId>
- <version>2.73-alpha</version>
- </dependency>
- </dependencies>
自动解析
- import cn.edu.hfut.dmic.webcollector.model.CrawlDatums;
- import cn.edu.hfut.dmic.webcollector.model.Page;
- import cn.edu.hfut.dmic.webcollector.plugin.berkeley.BreadthCrawler;
- public class AutoNewsCrawler extends BreadthCrawler {
- public AutoNewsCrawler(String crawlPath, boolean autoParse) {
- super(crawlPath, autoParse);
- this.addSeed("http://news.hfut.edu.cn/list-1-1.html");// 种子页面, 起始页面
- // 正则规则设置 寻找符合 http://news.hfut.edu.cn/show-xxxxxxhtml 的 url
- this.addRegex("http://news.hfut.edu.cn/show-.*html");
- this.addRegex("-.*\\.(jpg|png|gif).*");
- // 不要爬取包含 #的 URL
- this.addRegex("-.*#.*");
- setThreads(50);// 线程数
- getConf().setTopN(100);// 设置每次迭代中爬取数量的上限
- // 设置是否为断点爬取, 如果设置为 false, 任务启动前会清空历史数据.
- // 如果设置为 true, 会在已有 crawlPath(构造函数的第一个参数)的基础上继
- // 续爬取. 对于耗时较长的任务, 很可能需要中途中断爬虫, 也有可能遇到
- // 死机, 断电等异常情况, 使用断点爬取模式, 可以保证爬虫不受这些因素
- // 的影响, 爬虫可以在人为中断, 死机, 断电等情况出现后, 继续以前的任务
- // 进行爬取. 断点爬取默认为 false*/
- // setResumable(true);
- }
- /*
- visit 函数定制访问每个页面时所需进行的操作
- */
- @Override
- public void visit(Page page, CrawlDatums next) {
- String url = page.url();
- // 如果页面地址如何我们要求
- if (page.matchUrl("http://news.hfut.edu.cn/show-.*html")) {
- String title = page.select("div[id=Article]>h2").first().text();// 获取 url 标题
- String content = page.selectText("div#artibody");
- System.out.println("URL:\n" + url);// 地址
- System.out.println("title:\n" + title);// 标题
- System.out.println("content:\n" + content);// 内容
- /* 如果你想添加新的爬取任务, 可以向 next 中添加爬取任务,
- 这就是上文中提到的手动解析 */
- /*WebCollector 会自动去掉重复的任务(通过任务的 key, 默认是 URL),
- 因此在编写爬虫时不需要考虑去重问题, 加入重复的 URL 不会导致重复爬取 */
- /* 如果 autoParse 是 true(构造函数的第二个参数), 爬虫会自动抽取网页中符合正则规则的 URL,
- 作为后续任务, 当然, 爬虫会去掉重复的 URL, 不会爬取历史中爬取过的 URL.
- autoParse 为 true 即开启自动解析机制 */
- //next.add("http://xxxxxx.com");
- }
- }
- public static void main(String[] args) throws Exception {
- AutoNewsCrawler crawler = new AutoNewsCrawler("crawl", true);
- crawler.start(4);// 启动爬虫
- }
- }
运行接入如下所示:
手动解析
- import cn.edu.hfut.dmic.webcollector.model.CrawlDatums;
- import cn.edu.hfut.dmic.webcollector.model.Page;
- import cn.edu.hfut.dmic.webcollector.plugin.berkeley.BreadthCrawler;
- public class ManualNewsCrawler extends BreadthCrawler {
- public ManualNewsCrawler(String crawlPath, boolean autoParse) {
- super(crawlPath, autoParse);
- /*add 10 start pages and set their type to "list"
- "list" is not a reserved Word, you can use other string instead
- */
- for(int i = 1; i <= 10; i++) {
- this.addSeed("http://news.hfut.edu.cn/list-1-" + i + ".html", "list");// 种子页面, 起始页面
- }
- setThreads(50);// 线程数
- getConf().setTopN(100);// 设置每次迭代中爬取数量的上限
- // 设置是否为断点爬取, 如果设置为 false, 任务启动前会清空历史数据.
- // 如果设置为 true, 会在已有 crawlPath(构造函数的第一个参数)的基础上继
- // 续爬取. 对于耗时较长的任务, 很可能需要中途中断爬虫, 也有可能遇到
- // 死机, 断电等异常情况, 使用断点爬取模式, 可以保证爬虫不受这些因素
- // 的影响, 爬虫可以在人为中断, 死机, 断电等情况出现后, 继续以前的任务
- // 进行爬取. 断点爬取默认为 false*/
- // setResumable(true);
- }
- /*
- visit 函数定制访问每个页面时所需进行的操作
- * */
- @Override
- public void visit(Page page, CrawlDatums next) {
- String url = page.url();
- if (page.matchType("list")) {
- next.add(page.links("div[class=' col-lg-8 '] li>a")).type("content");
- }else if(page.matchType("content")) {
- /*if type is "content"*/
- /*extract title and content of news by CSS selector*/
- String title = page.select("div[id=Article]>h2").first().text();
- String content = page.selectText("div#artibody", 0);
- //read title_prefix and content_length_limit from configuration
- title = getConf().getString("title_prefix") + title;
- content = content.substring(0, getConf().getInteger("content_length_limit"));
- System.out.println("URL:\n" + url);
- System.out.println("title:\n" + title);
- System.out.println("content:\n" + content);
- }
- }
- public static void main(String[] args) throws Exception {
- ManualNewsCrawler crawler = new ManualNewsCrawler("crawl", false);
- crawler.getConf().setExecuteInterval(5000);
- crawler.getConf().set("title_prefix","PREFIX_");
- crawler.getConf().set("content_length_limit", 20);
- crawler.start(4);// 启动爬虫
- }
- }
运行结果如下图所示:
四, 项目源码下载
链接: https://pan.baidu.com/s/10Ze9xloOpVqmlBOj97XNaQ
提取码: ig45
五, 参考文章
- https://blog.51cto.com/14059916/2317860
- https://blog.csdn.net/acmdream/article/details/70159898
- https://blog.csdn.net/lhz15527200472/article/details/77868996
来源: https://www.cnblogs.com/WUXIAOCHANG/p/10617232.html