爬虫实战:基于 HtmlParser 实现网页链接的提取
来源:互联网 发布:贝克汉姆 帅 知乎 编辑:程序博客网 时间:2024/06/07 03:13
爬虫程序的第三步,是提取页面链接。
页面链接的提取,是爬虫程序中非常关键的一部分。一个完整的爬虫程序,要能从种子 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 接口的过滤器,如下表所示:
NotFilter
OrFilter 判断类 HasAttributeFilter
HasChildFilter
HasParentFilter
HasSiblingFilter
IsEqualFilter
TagNameFilter 其他 CssSelectorNodeFilter
LinkRegexFilter
LinkStringFilter
NodeClassFilter
RegexFilter
StringFilter
当然,开发人员也可以自定义 Filter,用于实现一些特殊情况的过滤。
简易链接提取器
使用 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; }}
我们编写一个简单的单元测试进行测试。
@Testpublic 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 - 发现链接个数:148INFO - 提取链接个数:131linkUrl:http://sm.xmu.edu.cn/html/mp/linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=lists&catid=432linkUrl:http://sm.xmu.edu.cn/html/english/linkUrl:http://sm2.xmu.edu.cn/default2.asplinkUrl: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.aspxlinkUrl: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.cnlinkUrl:https://xmu.higheredtalent.org/LoginlinkUrl: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.cnlinkUrl:http://ifas.xmu.edu.cn/cms/Channel.aspx?ID=147linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=3103linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2982linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2975linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2923linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2914linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2896linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2873linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2872linkUrl:http://sm.xmu.edu.cn/html/jwxx/linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=150&id=3278linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=150&id=3267linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=150&id=3246……
如果我们想添加自定义的过滤规则,比如只保留当前域名下的链接,可通过以下测试示例实现:
@Testpublic 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 - 发现链接个数:148INFO - 提取链接个数:107linkUrl:http://sm.xmu.edu.cn/html/mp/linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=lists&catid=432linkUrl: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.aspxlinkUrl: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.cnlinkUrl: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=3103linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2982linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2975linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2923linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2914linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2896linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2873linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=149&id=2872linkUrl:http://sm.xmu.edu.cn/html/jwxx/linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=150&id=3278linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=150&id=3267linkUrl:http://sm.xmu.edu.cn/index.php?m=content&c=index&a=show&catid=150&id=3246……
我们发现,自定义的过滤器起到了作用,程序只提取了当前域名下的链接。
阅读全文
0 0
- 爬虫实战:基于 HtmlParser 实现网页链接的提取
- htmlparser爬虫实现网页上的图片下载
- 基于htmlparser实现网页内容解析 (主题爬虫)
- lucene-使用htmlparser提取网页特定链接
- LUCENE-使用htmlparser提取网页所有链接
- lucene-使用htmlparser提取网页普通链接
- 网页爬虫 htmlparser
- 基于htmlparser实现网页内容解析
- 基于htmlparser实现网页内容解析
- 基于BeautifulSoup解析的网页爬虫实现
- htmlparser提取网页 显示网页的树形结构
- 一个htmlparser提取网页内容的简单例子
- 利用htmlparser提取网页纯文本的例子
- HTMLParser解析网页,提取链接地址、标题名称,并插入数据库
- 【搜索引擎Jediael开发笔记3】使用HtmlParser提取网页中的链接
- 【搜索引擎Jediael开发笔记3】使用HtmlParser提取网页中的链接
- htmlParser解析网页链接问题
- 使用htmlparser抓取网页链接
- 用java计算一个目录里所有文件的大小
- HDU 5916
- 代码重构之Spring+工厂+策略模式
- JS——事件冒泡(1)
- c++中的处理类型的三种方式
- 爬虫实战:基于 HtmlParser 实现网页链接的提取
- matlab中num2str
- qt编译caffe遇到的opencv版本问题
- JAVA_String之trim()源码
- 【操作系统】死锁
- Java小面试题(4)
- PHP留言板提供功能
- airflow worker报错raised unexpected:airflowexception('celery command failed')
- 洪小文:以科学的方式赤裸裸地剖析AI(四)| 未来是人工智能+人类智能