本文是这篇文章《Java实现爬虫给App提供数据(Jsoup 网络爬虫)》 http://blog.csdn.net/never_cxb/article/details/50524571 的衍生。当时面阿里的时候,聊到我做新闻 App 的时候,使用 Jsoup 爬虫,面试官随即问我对爬虫了解多深。所以稍微深入了解爬虫底层原理,后期打算看一下 Jsoup 底层实现。
笔者做的爬虫侧重于对于网页内容的提取,url 遵守一定概率(比如末尾数字递增)。
比如 http://blog.csdn.net/never_cxb/article/details/50524571 是一篇博客的地址,把数字50524571换成50515216就可以得到另一篇博客的地址 http://blog.csdn.net/never_cxb/article/details/50515216。
爬虫的基本思路如下
1. 根据 Url 获取相应页面的 Html 代码
2. 利用正则匹配或者 Jsoup 等库解析 Html 代码,提取需要的内容
3. 将获取的内容持久化到数据库中
4. 处理好中文字符的编码问题,可以采用多线程提高效率
关于 Html 和 Jsoup 的基本介绍请看这篇文章 https://liuzhichao.com/p/1484.html,写得很好。
从 Jsoup 的 Api 可以看出,Element 继承自 Node。
根据 DOM,HTML 文档中的每个成分都是一个Node。Node 之间有等级关系,父 Node、子 Node、兄弟 Node 等等。
Joup 其实是 Html 解析器,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。如果不使用 Jsoup 解析,也可以利用正则匹配找出 Html 中需要的内容。
如何获取 url 呢?有一种方法从文章列表中获取,比如下面的博客目录视图中,文章的对于的 html代码中可以获取href=”/never_cxb/article/details/50524571”, 标题为Java实现爬虫给App提供数据(Jsoup 网络爬虫)。
<h1>
<span class="link_title"><a href="/never_cxb/article/details/50524571">
<font color="red">[置顶]font>
Java实现爬虫给App提供数据(Jsoup 网络爬虫)
a>span>
h1>
更宽泛意义上的爬虫侧重于如果在大量的 url 中寻找出高质量的资源,如何在有限的时间内访问更多页面等等。网络爬虫的基本工作流程如下:
1.首先选取一部分精心挑选的种子URL;
2.将这些URL放入待抓取URL队列;
3.从待抓取URL队列中取出待抓取在URL,解析DNS,并且得到主机的ip,并将URL对应的网页下载下来,存储进已下载网页库中。此外,将这些URL放进已抓取URL队列。
4.分析已抓取URL队列中的URL,分析页面里包含的其他URL,并且将URL放入待抓取URL队列,从而进入下一个循环。
有几个概念,一个是发http请求,一个是正则匹配你感兴趣的链接,一个是多线程,另外还有两个队列。
来源于 该文章 的一张图
网络爬虫有时候会陷入循环或者环路中,比如从页面 A,A 链接到页面 B,B 链接 页面C,页面 C 又会链接到页面 A。这样就陷入到环路中。
1. 简单限定爬虫的最大循环次数,对于某 web 站点访问超过一定阈值就跳出,避免无限循环
2. 保存一个已访问 url 列表,记录页面是否被访问过的技术
有些 url 名称不一样,但是指向同一个资源。
该表格来自于 《HTTP 权威指南》
URl 1 | URL 2 | 什么时候是别名 |
---|---|---|
www.foo.com/bar.html | www.foo.com:80/bar.html | 默认端口是80 |
www.foo.com/~fred | www.foo.com/%7Ffred | %7F与~相同 |
www.foo.com/x.html#top | www.foo.com/x.html#middle | %7F与~相同 |
https://www.baidu.com/ | https://www.BAIDU.com/ | 服务器是大小写无关 |
www.foo.com/index.html | www.foo.com | 默认页面为 index.html |
www.foo.com/index.html | 209.123.123/index.html | ip和域名相同 |
比如日历程序,它会生成一个指向下一月的链接,真正的用户是不会不停地请求下个月的链接的。但是不了解这内容特性的爬虫蜘蛛可能会不断向这些资源发出无穷的请求。
一般策略是深度优先或者广度优先。有些技术能使得爬虫蜘蛛有更好的表现
动态变化,根据当前热点新闻等等
规划化 url,把一些转义字符、ip 与域名之类的统一
全文索引就是一个数据库,给它一个单词,它可以立刻提供包含那个单词的所有文字。创建了索引之后,就不必对文档自身进行扫描了。
比如 文章 A 包含了 Java、学习、程序员
文章 B 包含了 Java 、Python、面试、招聘
如果搜索 Java,可以知道得到 文章 A 和文章 B,而不必对文章 A、B 全文扫描。
自己曾实现了Python 爬虫,统计学校论坛上男女用户各占多少。
我当时做的思路是 get 请求获取 html 源代码,对 html 用字符串匹配(前后多加一些限定单词进行正则匹配 比如em>上次发表时间
后面跟的是活动时间)。
回过头来看,可能解析Dom 树可能更优雅一些。
网络爬虫基本原理以及Jsoup基本使用方法