爬虫实战:基于 HtmlParser 实现网页链接的提取
2017-11-30 19:41
260 查看
爬虫程序的第三步,是提取页面链接。
页面链接的提取,是爬虫程序中非常关键的一部分。一个完整的爬虫程序,要能从种子 URL 出发,逐步遍历子节点中的所有页面。就比如我们想采集微博内容时,不能仅仅采集第一页的内容,而要实现从第一页开始一直采集到尾页。
本篇主要介绍一款能提取网页链接的强大类库,HtmlParser。
HtmlParser 具备如下特性:
过滤器
访问者模式
自定义标签
易于使用的 Java 组件
正如官网简介里所述,HtmlParser 是一个快速的、健壮的、经过严格测试的工具包。
HtmlParser 中与过滤相关的基本接口是 NodeFilter,接口中只定义了一个方法。
该方法的作用是,对于想要保留的节点,返回 true;对于满足过滤条件、需要过滤掉的节点,返回 false。
HtmlParser 本身就提供了多种实现 NodeFilter 接口的过滤器,如下表所示:
当然,开发人员也可以自定义 Filter,用于实现一些特殊情况的过滤。
使用 url 或者网页源码创建一个 Parser 对象;
构建满足需求的过滤器对象;
通过 Parser 的
通过节点获取链接信息。
以下是 HtmlParser 提取网页链接的具体示例:
我们编写一个简单的单元测试进行测试。
输出结果如下:
如果我们想添加自定义的过滤规则,比如只保留当前域名下的链接,可通过以下测试示例实现:
输出结果如下:
我们发现,自定义的过滤器起到了作用,程序只提取了当前域名下的链接。
页面链接的提取,是爬虫程序中非常关键的一部分。一个完整的爬虫程序,要能从种子 URL 出发,逐步遍历子节点中的所有页面。就比如我们想采集微博内容时,不能仅仅采集第一页的内容,而要实现从第一页开始一直采集到尾页。
本篇主要介绍一款能提取网页链接的强大类库,HtmlParser。
HtmlParser
HtmlParser 是一个通过线性和嵌套两种方式来解析网页的 Java 开源类库,主要用于网页元素的转换以及网页内容的抽取。HtmlParser 具备如下特性:
过滤器
访问者模式
自定义标签
易于使用的 Java 组件
正如官网简介里所述,HtmlParser 是一个快速的、健壮的、经过严格测试的工具包。
NodeFilter
HtmlParser 具备过滤器的特性,我们可以通过这个特性过滤并提取网页中的链接。HtmlParser 中与过滤相关的基本接口是 NodeFilter,接口中只定义了一个方法。
package org.htmlparser; import java.io.Serializable; import org.htmlparser.Node; public interface NodeFilter extends Serializable, Cloneable { boolean accept(Node var1); }
该方法的作用是,对于想要保留的节点,返回 true;对于满足过滤条件、需要过滤掉的节点,返回 false。
HtmlParser 本身就提供了多种实现 NodeFilter 接口的过滤器,如下表所示:
类别 | 类名 |
---|---|
逻辑运算类 | AndFilter NotFilter OrFilter |
判断类 | HasAttributeFilter HasChildFilter HasParentFilter HasSiblingFilter IsEqualFilter TagNameFilter |
其他 | CssSelectorNodeFilter LinkRegexFilter LinkStringFilter NodeClassFilter RegexFilter StringFilter |
简易链接提取器
使用 HtmlParser 实现链接提取,需要以下步骤:使用 url 或者网页源码创建一个 Parser 对象;
构建满足需求的过滤器对象;
通过 Parser 的
extractAllNodesThatMatch(NodeFilter filter)方法提取过滤后的节点;
通过节点获取链接信息。
以下是 HtmlParser 提取网页链接的具体示例:
package filter; import org.htmlparser.Node; import org.htmlparser.Parser; import org.htmlparser.filters.NodeClassFilter; import org.htmlparser.filters.OrFilter; import org.htmlparser.tags.FrameTag; import org.htmlparser.tags.LinkTag; import org.htmlparser.util.NodeList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.List; /** * 链接提取器 * * @author panda * @date 2017/10/28 */ public class LinkExtractor { private static final Logger logger = LoggerFactory.getLogger(LinkExtractor.class); public static List<String> extractLinks(String body, LinkFilter filter) { List<String> linkList = new ArrayList<String>(); try { Parser parser = new Parser(body); OrFilter linkFilter = new OrFilter( new NodeClassFilter[]{ new NodeClassFilter(LinkTag.class), new NodeClassFilter(FrameTag.class) } ); NodeList nodeList = parser.extractAllNodesThatMatch(linkFilter); if (nodeList != null) { logger.info("发现链接个数:" + nodeList.size()); } for (int i = 0; i < nodeList.size(); i++) { Node node = nodeList.elementAt(i); String linkUrl; if (node instanceof LinkTag) { LinkTag link = (LinkTag) node; linkUrl = link.getAttribute("HREF"); } else { FrameTag frame = (FrameTag) node; linkUrl = frame.getFrameLocation(); } // 如果有自定义过滤器,则增加自定义过滤条件 if (filter != null && linkUrl != null) { if (!filter.accept(linkUrl)) { linkUrl = null; } } if (linkUrl == null || "".equals(linkUrl) || "#".equals(linkUrl) || linkUrl.startsWith("javascript")) { continue; } // 防止链接重复 if (!linkList.contains(linkUrl)) { linkList.add(linkUrl); } } if (linkList != null) { logger.info("提取链接个数:" + linkList.size()); } } catch (Exception e) { logger.error("提取链接异常:", e); } return linkList; } }
我们编写一个简单的单元测试进行测试。
@Test public void testExtractLinksWithoutFilter() { String body = HttpUtil.executeGetRequest("http://sm.xmu.edu.cn/"); List<String> linkList = LinkExtractor.extractLinks(body, null); for (int i = 0; i < linkList.size(); i++) { System.out.println("linkUrl:" + linkList.get(i)); } }
输出结果如下:
INFO - 发现链接个数:148 INFO - 提取链接个数:131 linkUrl:http://sm.xmu.edu.cn/html/mp/ linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=lists&catid=432 linkUrl:http://sm.xmu.edu.cn/html/english/ linkUrl:http://sm2.xmu.edu.cn/default2.asp linkUrl:http://sm.xmu.edu.cn/ linkUrl:http://sm.xmu.edu.cn/html/about/overview/overview/ linkUrl: fe06 http://sm.xmu.edu.cn/html/about/message/ linkUrl:http://sm.xmu.edu.cn/html/about/leaders/ linkUrl:http://sm.xmu.edu.cn/html/about/department/ linkUrl:http://sm.xmu.edu.cn/html/about/structure/ linkUrl:http://sm.xmu.edu.cn/html/about/service/ linkUrl:http://sm.xmu.edu.cn/html/about/contact/ linkUrl:http://sm.xmu.edu.cn/html/current_students/ linkUrl:http://sm.xmu.edu.cn/keyan/TeacherWeb/Teacher_Special.aspx linkUrl:http://sm.xmu.edu.cn/html/research/research_news/ linkUrl:http://sm.xmu.edu.cn/html/research/academic/ linkUrl:http://sm.xmu.edu.cn/html/research/research_center/ linkUrl:http://sm.xmu.edu.cn/html/intl/ linkUrl:http://sm.xmu.edu.cn/html/intl/overview/ linkUrl:http://sm.xmu.edu.cn/html/intl/authentication/ linkUrl:http://sm.xmu.edu.cn/html/intl/news/ linkUrl:http://sm.xmu.edu.cn/html/intl/student/ linkUrl:http://sm.xmu.edu.cn/html/intl/2_2/ linkUrl:http://sm.xmu.edu.cn/html/intl/International_students/ linkUrl:http://sm.xmu.edu.cn/html/intl/guide/ linkUrl:http://sm.xmu.edu.cn/html/intl/contact/ linkUrl:http://smcareer.xmu.edu.cn/ linkUrl:http://sm-alumni.xmu.edu.cn/ linkUrl:http://sm.xmu.edu.cn linkUrl:https://xmu.higheredtalent.org/Login linkUrl:http://pme.xmu.edu.cn/ linkUrl:http://sm.xmu.edu.cn/html/programs/ linkUrl:http://sm.xmu.edu.cn/html/programs/ung/ linkUrl:http://sm.xmu.edu.cn/html/programs/master/ linkUrl:http://sm.xmu.edu.cn/html/programs/phd/ linkUrl:http://mba.xmu.edu.cn/ linkUrl:http://emba.xmu.edu.cn/ linkUrl:http://www.xmuedp.com/ linkUrl:http://sm.xmu.edu.cn/html/about/department/MPAcc/ linkUrl:http://meem.xmu.edu.cn/ linkUrl:http://sm.xmu.edu.cn/html/about/department/mta/ linkUrl:http://smice.xmu.edu.cn/ linkUrl:http://sm.xmu.edu.cn/html/programs/bsh/ linkUrl:http://sm.xmu.edu.cn/html/about/department/bm/class/ linkUrl:http://femba.xmu.edu.cn linkUrl:http://ifas.xmu.edu.cn/cms/Channel.aspx?ID=147 linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=3103 linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2982 linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2975 linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2923 linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2914 linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2896 linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2873 linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2872 linkUrl:http://sm.xmu.edu.cn/html/jwxx/ linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=150&id=3278 linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=150&id=3267 linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=150&id=3246 ……
如果我们想添加自定义的过滤规则,比如只保留当前域名下的链接,可通过以下测试示例实现:
@Test public void testExtractLinksWithFilter() { String body = HttpUtil.executeGetRequest("http://sm.xmu.edu.cn/"); LinkFilter filter = new LinkFilter() { public boolean accept(String link) { return link.contains("sm.xmu.edu.cn"); } }; List<String> linkList = LinkExtractor.extractLinks(body, filter); for (int i = 0; i < linkList.size(); i++) { System.out.println("linkUrl:" + linkList.get(i)); } }
输出结果如下:
INFO - 发现链接个数:148 INFO - 提取链接个数:107 linkUrl:http://sm.xmu.edu.cn/html/mp/ linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=lists&catid=432 linkUrl:http://sm.xmu.edu.cn/html/english/ linkUrl:http://sm.xmu.edu.cn/ linkUrl:http://sm.xmu.edu.cn/html/about/overview/overview/ linkUrl:http://sm.xmu.edu.cn/html/about/message/ linkUrl:http://sm.xmu.edu.cn/html/about/leaders/ linkUrl:http://sm.xmu.edu.cn/html/about/department/ linkUrl:http://sm.xmu.edu.cn/html/about/structure/ linkUrl:http://sm.xmu.edu.cn/html/about/service/ linkUrl:http://sm.xmu.edu.cn/html/about/contact/ linkUrl:http://sm.xmu.edu.cn/html/current_students/ linkUrl:http://sm.xmu.edu.cn/keyan/TeacherWeb/Teacher_Special.aspx linkUrl:http://sm.xmu.edu.cn/html/research/research_news/ linkUrl:http://sm.xmu.edu.cn/html/research/academic/ linkUrl:http://sm.xmu.edu.cn/html/research/research_center/ linkUrl:http://sm.xmu.edu.cn/html/intl/ linkUrl:http://sm.xmu.edu.cn/html/intl/overview/ linkUrl:http://sm.xmu.edu.cn/html/intl/authentication/ linkUrl:http://sm.xmu.edu.cn/html/intl/news/ linkUrl:http://sm.xmu.edu.cn/html/intl/student/ linkUrl:http://sm.xmu.edu.cn/html/intl/2_2/ linkUrl:http://sm.xmu.edu.cn/html/intl/International_students/ linkUrl:http://sm.xmu.edu.cn/html/intl/guide/ linkUrl:http://sm.xmu.edu.cn/html/intl/contact/ linkUrl:http://sm.xmu.edu.cn linkUrl:http://sm.xmu.edu.cn/html/programs/ linkUrl:http://sm.xmu.edu.cn/html/programs/ung/ linkUrl:http://sm.xmu.edu.cn/html/programs/master/ linkUrl:http://sm.xmu.edu.cn/html/programs/phd/ linkUrl:http://sm.xmu.edu.cn/html/about/department/MPAcc/ linkUrl:http://sm.xmu.edu.cn/html/about/department/mta/ linkUrl:http://sm.xmu.edu.cn/html/programs/bsh/ linkUrl:http://sm.xmu.edu.cn/html/about/department/bm/class/ linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=3103 linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2982 linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2975 linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2923 linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2914 linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2896 linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2873 linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2872 linkUrl:http://sm.xmu.edu.cn/html/jwxx/ linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=150&id=3278 linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=150&id=3267 linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=150&id=3246 ……
我们发现,自定义的过滤器起到了作用,程序只提取了当前域名下的链接。
相关文章推荐
- 基于htmlparser实现网页内容解析 (主题爬虫)
- Python爬虫(七)学习提取网页中所有链接
- 黄聪:使用Python中的HTMLParser、cookielib抓取和解析网页、从HTML文档中提取链接、图像、文本、Cookies(二)
- 【python】使用HTMLParser、cookielib抓取和解析网页、从HTML文档中提取链接、图像、文本、Cookies
- 使用htmlparser爬虫技术爬取电影网页的全部下载链接
- 基于htmlparser实现网页内容解析
- 使用Python中的HTMLParser、cookielib抓取和解析网页、从HTML文档中提取链接、图像、文本、Cookies
- Jsoup 实现的基于列表-详情结构的网页爬虫
- 基于C#实现网页爬虫
- Java实现网络爬虫爬取网页链接并设置搜索深度(广搜)
- 基于htmlparser实现网页内容解析
- 【搜索引擎Jediael开发笔记3】使用HtmlParser提取网页中的链接 分类: H3_NUTCH 2014-05-20 20:50 1211人阅读 评论(0) 收藏
- 基于Java HttpClient和Htmlparser实现网络爬虫代码
- Python中的HTMLParser、cookielib抓取和解析网页、从HTML文档中提取链接、图像、文本、Cookies(二)
- 使用Python中的HTMLParser、cookielib抓取和解析网页、从HTML文档中提取链接、图像、文本、Cookies(二)
- lucene-使用htmlparser提取网页特定链接
- 【搜索引擎Jediael开发笔记3】使用HtmlParser提取网页中的链接
- LUCENE-使用htmlparser提取网页所有链接
- 【搜索引擎Jediael开发笔记3】使用HtmlParser提取网页中的链接