如何使用HtmlExtractor实现基于模板的网页结构化信息精准抽取?

原创
2015/04/15 23:43
阅读数 2.4K

首先,我们新建一个maven工程,在pom.xml中加入HtmlExtractor依赖,如下所示:

<dependency>
    <groupId>org.apdplat</groupId>
    <artifactId>html-extractor</artifactId>
    <version>1.1</version>
</dependency>


接着,我们加入日志配置文件,在src/main/resources目录下新建日志文件logback.xml,如果想看到更多细节,请将<root level="INFO">改为<root level="DEBUG">,内容如下:

<?xml version="1.0" encoding="UTF-8"?>

<configuration>
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>%m%n</Pattern>
        </layout>
    </appender>
    <appender name="logfile" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <File>logs/logback.log</File>
        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">  
            <FileNamePattern>logs/logback_%i.log</FileNamePattern>
            <MinIndex>1</MinIndex>  
            <MaxIndex>10000</MaxIndex>
        </rollingPolicy>  
        <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">  
            <MaxFileSize>5MB</MaxFileSize> 
        </triggeringPolicy> 
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>%m%n</Pattern>j
        </layout>
    </appender>
    <root level="INFO">
        <appender-ref ref="logfile"/>
        <appender-ref ref="stdout"/>
    </root>
</configuration>


接下来,我们在src/main/java下新建一个类,如NeteasyNewsExtractor.java,内容如下:

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apdplat.extractor.html.HtmlExtractor;
import org.apdplat.extractor.html.HtmlFetcher;
import org.apdplat.extractor.html.impl.DefaultHtmlExtractor;
import org.apdplat.extractor.html.impl.ExtractRegular;
import org.apdplat.extractor.html.impl.JSoupHtmlFetcher;
import org.apdplat.extractor.html.model.CssPath;
import org.apdplat.extractor.html.model.ExtractFailLog;
import org.apdplat.extractor.html.model.ExtractResult;
import org.apdplat.extractor.html.model.ExtractResultItem;
import org.apdplat.extractor.html.model.HtmlTemplate;
import org.apdplat.extractor.html.model.UrlPattern;

/**
 *
 * @author 杨尚川
 */
public class NeteasyNewsExtractor {
    public static void main(String[] args) {
        //1、构造抽取规则
        List<UrlPattern> urlPatterns = new ArrayList<>();
        //1.1、构造URL模式
        UrlPattern urlPattern = new UrlPattern();
        urlPattern.setUrlPattern("http://money.163.com/\\d{2}/\\d{4}/\\d{2}/[0-9A-Z]{16}.html");
        //1.2、构造HTML模板
        HtmlTemplate htmlTemplate = new HtmlTemplate();
        htmlTemplate.setTemplateName("网易财经频道");
        htmlTemplate.setTableName("finance");
        //1.3、将URL模式和HTML模板建立关联
        urlPattern.addHtmlTemplate(htmlTemplate);
        //1.4、构造CSS路径
        CssPath cssPath = new CssPath();
        cssPath.setCssPath("h1");
        cssPath.setFieldName("title");
        cssPath.setFieldDescription("标题");
        //1.5、将CSS路径和模板建立关联
        htmlTemplate.addCssPath(cssPath);
        //1.6、构造CSS路径
        cssPath = new CssPath();
        cssPath.setCssPath("div#endText");
        cssPath.setFieldName("content");
        cssPath.setFieldDescription("正文");
        //1.7、将CSS路径和模板建立关联
        htmlTemplate.addCssPath(cssPath);
        //可象上面那样构造多个URLURL模式
        urlPatterns.add(urlPattern);
        //2、获取抽取规则对象
        ExtractRegular extractRegular = ExtractRegular.getInstance(urlPatterns);
        //注意:可通过如下3个方法动态地改变抽取规则
        //extractRegular.addUrlPatterns(urlPatterns);
        //extractRegular.addUrlPattern(urlPattern);
        //extractRegular.removeUrlPattern(urlPattern.getUrlPattern());
        //3、获取HTML抽取工具
       HtmlExtractor htmlExtractor = new DefaultHtmlExtractor(extractRegular);
        //4、抽取网页
        String url = "http://money.163.com/08/1219/16/4THR2TMP002533QK.html";
        HtmlFetcher htmlFetcher = new JSoupHtmlFetcher();
        String html = htmlFetcher.fetch(url);
        List<ExtractResult> extractResults = htmlExtractor.extract(url, html);
        //5、输出结果
        int i = 1;
        for (ExtractResult extractResult : extractResults) {
            System.out.println((i++) + "、网页 " + extractResult.getUrl() + " 的抽取结果");
            if(!extractResult.isSuccess()){
                System.out.println("抽取失败:");
                for(ExtractFailLog extractFailLog : extractResult.getExtractFailLogs()){
                    System.out.println("\turl:"+extractFailLog.getUrl());
                    System.out.println("\turlPattern:"+extractFailLog.getUrlPattern());
                    System.out.println("\ttemplateName:"+extractFailLog.getTemplateName());
                    System.out.println("\tfieldName:"+extractFailLog.getFieldName());
                    System.out.println("\tfieldDescription:"+extractFailLog.getFieldDescription());
                    System.out.println("\tcssPath:"+extractFailLog.getCssPath());
                    if(extractFailLog.getExtractExpression()!=null) {
                        System.out.println("\textractExpression:" + extractFailLog.getExtractExpression());
                    }
                }
                continue;
            }
            Map<String, List<ExtractResultItem>> extractResultItems = extractResult.getExtractResultItems();
            for(String field : extractResultItems.keySet()){
                List<ExtractResultItem> values = extractResultItems.get(field);
                if(values.size() > 1){
                    int j=1;
                    System.out.println("\t多值字段:"+field);
                    for(ExtractResultItem item : values){
                        System.out.println("\t\t"+(j++)+"、"+field+" = "+item.getValue());   
                    }
                }else{
                    System.out.println("\t"+field+" = "+values.get(0).getValue());     
                }
            }
            System.out.println("\tdescription = "+extractResult.getDescription());
            System.out.println("\tkeywords = "+extractResult.getKeywords());
        }
    }
}


最后,我们运行NeteasyNewsExtractor类,控制台输出如下:

开始初始化URL抽取规则
完成初始化URL抽取规则
1、网页 http://money.163.com/08/1219/16/4THR2TMP002533QK.html 的抽取结果
	title = 宗庆后:企业平稳过冬依赖政府内需政策思路转变
	content = 娃哈哈董事长 宗庆后 宗庆后: 各位专家和企业朋友,今天没有我演讲的任务,也没有准备,我谈几个感想,经济危机看你怎么看,美国的金融危机收钱就行,用了人家的钱就了,窟窿大的把钱收回来就行了,布什当了两届总统又把美国的钱用完了,现在又要收钱,人民币升值。 说到受到美国金融危机的影响,两三个月的工夫就造成了这么大困难,原因在真正地方,我认为中国就没有分配,经济学家都知道,原始社会的时候就是相互交换,现在分配的方式多式多样的。 改革开放这么多年,有的专家说我们没有政治体制改革,我们应该是政治体制改革和经济体制改革一起进行。这么多年,经济发展就非常快,但没有搞好分配,分配了以后才可以再生产。每次劳动以后就有一个剩余的价值,就没有分配给老百姓用。不能技术再生产怎么解决?就是再出口。我国60%靠出口,前面三十年是靠出口和投资发展。现在订单少了,出口受阻了。 另外我感觉制造业利润太高,税负太重了。所以有些企业家看看自己太辛苦,股市和房地产可以引起暴利,所以没有在制造业坚持发展,没有提高自己企业的核心竞争力。所以股市、房市掉下来,可能2-3个月一下就乱了。 企业的经济危机当中要承担什么责任?我感觉对于经济危机,企业没有办法扭转,关键是国家政策调整,国家政策调整中国经济要不了半年就上来了。拉动内需认识比较统一的,关键是如何拉动内需。 拉动内需关键是老百姓要有钱花,降低企业税收,要企业给员工加工资。你要提高农产品价格,放开农产品价格,等到老百姓有钱才可以花钱。 给了老百姓钱不一定要花,所以我才感觉到蒙代尔说的消费券办法可能效果有限。很多国家都在发消费券,但中国社会本质上还是在限制消费。要解决读书医疗方面的问题,让老百姓没有后顾之忧大量花钱,才可以把内需拉起来,这样工厂才可以活起来。 现在放缩银根根本就没有用了,银行贷给你就要打水飘。所以必须把内需拉起来,让工厂赚钱,这样才可以把经济危机扭转过来。我认为国家要有这个政策,整个发展国家要改变,作为企业来讲,经济比较好的国家都会非常关注企业生存。如果根本就不把企业当回事情,出的政策全部都是把负担转嫁给企业身上,企业一塌,劳动力失业,社会问题就来了,所以企业是社会创造财富最主要的力量,发展经济当中最重要的力量。企业发展员工好了,企业垮台大家就失业了,这就麻烦了。 中国政府现在还是关心企业,开始解决企业的难题,我认为这就是一个机遇。现在出口企业大部分是贴牌加工的,并不是说美国不消费,欧洲不消费,而是叫你委托加工的企业倒了。这就带来了自己品牌开拓国际市场的机会。 国外经济危机就要买中国的产品,这对出口企业也是一个机会。 现在国家出台扶持政策,出口退税,给了有多的优惠政策,对我们来讲也是一个机会。 所以我认为中国的问题很好解决,关键是政策要调整。调整得好,这次经济危机当中就会一点损失都没有,一点影响都没有。如果做到无论销售和利润都增长在4%左右,现金也比较好了,就会一切都好。 我们这些企业老老实实做饮料,没有做任何其他东西,坚持主业发展,把主业做强做大,不做自己没有能力做的事情。 所以今后的企业家心态要稳,并不是一件事情做成功了,什么事情就可以做成功的。有的时候看看别人赚钱,这个钱不是我赚的,所以就不要盲目搞。现在说抄底,抄人家底,就千万不要抄底。 我不太赞同项兵教授的说法,你没有科技创新的话,美国有先进的武器,到处可以打你,到处可以制约你。美国的武器比你先进,美国人就敢说话。所以要科技创新,我们有廉价劳动力创造财富,企业要不断的科技创新,提高竞争力,我们中国才有民族竞争力,这是我们崛起的时候,也是一个机会,我们不要救人家,而是救自己。 谢谢大家! (本文来源:网易财经 ) 【本新闻已有0人评论,点击查看。】
	description = 对于经济危机,企业没有办法扭转,关键是国家政策调整,国家政策调整中国经济要不了半年就上来了。拉动内需认识比较统一的,关键是如何拉动内需。拉动内需关键是老百姓要有钱花,降低企业税收,要企业给员工加工资。
	keywords = 宗庆后,股票,股市,行情,基金,期货,汇率,证券,证券市场,上市公司,研究报告


好了,我们第一个简单的入门小例子就到这里。


HtmlExtractor一个Java实现的基于模板的网页结构化信息精准抽取组件,本身并不包含爬虫功能,但可被爬虫或其他程序调用以便更精准地对网页结构化信息进行抽取。


HtmlExtractor为大规模分布式环境设计的,采用主从架构,主节点负责维护抽取规则,从节点向主节点请求抽取规则,当抽取规则发生变化,主节点主动通知从节点,从而能实现抽取规则变化之后的实时动态生效。



展开阅读全文
加载中
点击加入讨论🔥(3) 发布并加入讨论🔥
打赏
3 评论
12 收藏
4
分享
返回顶部
顶部