Jericho Html Parser初探
2015-10-16 14:50
477 查看
Jericho Html Parser初探
作者:SharpStill
Jericho作为其SourceForge上人气最高的最新Html解析框架,自然有其强大的理由。但是由于目前中国人使用的不多,因此网上的中文教程和资料不多,所以造成了大家的学习困难。因此,我们从学习复杂度,代码量等初学者入门指标来看看这个框架的魔力吧。可以使用制作开源爬虫引擎。
这个例子我们以淘宝这样的购物网站作为解析实例。
淘宝网的页面分为http://list.taobao.com http://www.taobao.com/go/chn/game,(类似album)和http://item.taobao.com(类似video)和面还有许许多多这样的页面,我们利用Jericho
Html Parser作为页面解析框架,来看一下他的威力。
这个网页解析框架的xml书写如下:
JerichoHtml Parser的核心的类便是Source类,source类代表了html文档,他可以从URL得到文档或者从String得到。
In certain circumstances you may be able to improve performance bycalling the
before calling anytagsearch methods. See the documentation of the
for details.
在其说明文档中有这样一句话,就是说如果在特定情况下可以使用
this method can greatly improve performance if most or allof the tags in the document need to be parsed.
如果在一个类里将大部分或者所有的tag标记都解析了的话,比如我们经常需要提取出网页所有的URL或者图片链接,在这种情况下使用这种方法可以加快提取速度,但是值得注意的一点是:只有在Source对象被new出来的后面一句紧接着调用这句话有效。紧接着调用Tag
Search Method(文档中有详细说明)即可。
我们以提取这个页面为例:
![](https://img-blog.csdn.net/20151016150640075?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
这个页面包含以下几点:价格,运费信息,所在地区,收藏人气,宝贝类型。利用这个页面提取,看看其编程效率能提高多少。
package com.test.html;
import java.util.List;
import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.Source;
import com.test.html.bean.ShoppingDetail;
public class HtmlParseTest {
public static ShoppingDetail extract(String inputHtml){
Source source = new Source(inputHtml);
Element form = source.getElementById("J_FrmBid");
List<Element> inputArea = form.getAllElements("input");
String price ="";
String area ="";
String transportInfo="";
for(Element input : inputArea){
if(input.getAttributeValue("name").equals("buy_now"))price = input.getAttributeValue("value");
if(input.getAttributeValue("name").equals("region"))area = input.getAttributeValue("value");
if(input.getAttributeValue("name").equals("who_pay_ship"))transportInfo = input.getAttributeValue("value");
}
Element others = source.getAllElementsByClass("other clearfix").get(0);
String otherInfo = others.getContent().getTextExtractor().toString().trim();
int startBabyType =otherInfo.indexOf("宝贝类型:");
int endBabyType= otherInfo.indexOf("收藏人气:");
String babyType = otherInfo.substring(startBabyType+5,endBabyType);
int endStore = otherInfo.indexOf("类似收藏");
String storeCount = otherInfo.substring(endBabyType+5,endStore-1).trim();
ShoppingDetail detail = new ShoppingDetail();
detail.setArea(area);
detail.setBabyType(babyType);
detail.setPrice(price);
detail.setStroreCount(Integer.parseInt(storeCount));
detail.setTransportInfo(transportInfo);
return detail;
}
public static void main(String[] args) throws Exception {
String content = HttpClientUtils.getContent("http://item.taobao.com/item.htm?id=3144581940", "UTF-8");
ShoppingDetail detail = HtmlParseTest.extract(content);
System.out.println(detail);
运行结果如下所示
com.test.html.bean.ShoppingDetail@1aaa14a[title=索尼
PSP 4.3寸摇杆游戏机 8G mp5高清电影+TV输出+收音,price=235.00,transportInfo=卖家承担运费,area=广东深圳,stroreCount=17711,babyType=全新
]
提取这个页面的核心代码仅为上面的那个函数,可以说从编程的复杂度而言比HtmlParser减少了不少,而且也没有繁琐的访问者模式了。
下面作为对比,我们来看看HtmlParser在这个页面解析上所做的代码量:
@Override
public boolean execute(Context context) throws Exception {
//spring若与commons chain可以集成IOC的话,就删去
parserTool = new SingleHtmlParserTool();
filterUtils = new FilterUtils();
filterUtils.setTool(new PropertiesTool("/Config/Properties/TaobaoFilter.properties"));
//这一段若研究了spring的胶水机制就删了
String url = ((String)context.get("url")).toLowerCase();
String seller_Url = "";
String seller_Nickname = "";
String seller_Taobao_Id = "";
if(url.contains(Url_Pattern)){
System.out.println("开始提取数据自"+url);
NodeList forms = parserTool.getContainerInnerTags(url, formFilter);
Map<String,String> valueMap = new HashMap<String,String>();//key-value map to store
for(int i = 0;i<forms.size();i++){
FormTag form = (FormTag)forms.elementAt(i);
NodeList inputs = form.getFormInputs();
for(int j = 0;j<inputs.size();j++){
InputTag input = (InputTag)inputs.elementAt(j);
String inputName = input.getAttribute("name");
String inputValue = input.getAttribute("value");
valueMap.put(inputName, inputValue);
}
//进入卖家分析程序分析时要用的一些Context中的值
seller_Taobao_Id = valueMap.get("seller_id");
seller_Nickname = valueMap.get("seller_nickname");
seller_Url = "http://rate.taobao.com/user-rate-"+seller_Taobao_Id+".htm";
//进入卖家分析程序分析时要用的一些Context中的值
filterUtils.filterMap(valueMap, filterStoreItemKey,
merchandiseItemSeparatorKey,
DictItem.MerchandiseItemSiteToEngine);// 过滤网址上的其他杂质<inputname="杂质" />,保证最后存于数据库的map被返回
valueMap.put("TaobaoSite_Url", url);// 最后把网页"内容"里提取不出来的url加入其中
// 存入数据库
IBasicSqlDao dao = BeanMapDaoUsingCommonsBeanutils.getInstance();
dao.storeMapToDb(valueMap, sqlId, MerchandiseItem.class);
// 存入数据库
for(Map.Entry<String, String> entry : valueMap.entrySet()){
System.out.println(entry.getKey()+":"+entry.getValue());
}
System.out.println("---页面"+url+"提取完毕---");
//重构可以删去
valueMap.clear();// 清除map
}
Context sellerContext = new UrlContext(seller_Url);
sellerContext.put("Seller_Nickname", seller_Nickname);
sellerContext.put("Seller_Taobao_Id", seller_Taobao_Id);
EmergencyLinkUrl.addUnVisitUrl(sellerContext, this);
return true;
}
return false;
}
可以明显看到,Jercho从编程风格来看,拥有这几大优势:
去除了内部类,由于Html Parser使用过滤器或访问者模式,不可避免地引入内部类。
编程使用泛型,简化编写,Html Parser没有使用泛型作为其框架,可能其创造年代较早,但是大量使用了设计模式,可以窥见其作者对设计模式的功力很深。
可以直接提取页面文本信息,将HTML标签去除。这个在全文搜索时非常常用。
Tag Search Method类似XPath的提取方式,可以不受限制地提取若干层以下的元素Element。
目前观察到的几大优势使我们有理由相信,Jercho在未来的Html解析届会成为翘楚的。以下为一篇不错的Jercho Html Parser文章推荐下:
http://www.ehelper.com.cn/blog/post/httpclient-jericho.html
我又查了一下资料,发现 jsoup HTML解析器比 htmpparser 更好
HtmlUnit 比 httpclient更易用
Jericho Html Parser初探
作者:SharpStill
Jericho作为其SourceForge上人气最高的最新Html解析框架,自然有其强大的理由。但是由于目前中国人使用的不多,因此网上的中文教程和资料不多,所以造成了大家的学习困难。因此,我们从学习复杂度,代码量等初学者入门指标来看看这个框架的魔力吧。可以使用制作开源爬虫引擎。
这个例子我们以淘宝这样的购物网站作为解析实例。
淘宝网的页面分为http://list.taobao.com http://www.taobao.com/go/chn/game,(类似album)和http://item.taobao.com(类似video)和面还有许许多多这样的页面,我们利用Jericho
Html Parser作为页面解析框架,来看一下他的威力。
这个网页解析框架的xml书写如下:
JerichoHtml Parser的核心的类便是Source类,source类代表了html文档,他可以从URL得到文档或者从String得到。
In certain circumstances you may be able to improve performance bycalling the
fullSequentialParse()method
before calling anytagsearch methods. See the documentation of the
fullSequentialParse()method
for details.
在其说明文档中有这样一句话,就是说如果在特定情况下可以使用
fullSequentialParse()方法,提高解析速度,这个方法里的说明:Calling
this method can greatly improve performance if most or allof the tags in the document need to be parsed.
如果在一个类里将大部分或者所有的tag标记都解析了的话,比如我们经常需要提取出网页所有的URL或者图片链接,在这种情况下使用这种方法可以加快提取速度,但是值得注意的一点是:只有在Source对象被new出来的后面一句紧接着调用这句话有效。紧接着调用Tag
Search Method(文档中有详细说明)即可。
我们以提取这个页面为例:
这个页面包含以下几点:价格,运费信息,所在地区,收藏人气,宝贝类型。利用这个页面提取,看看其编程效率能提高多少。
package com.test.html;
import java.util.List;
import net.htmlparser.jericho.Element;
import net.htmlparser.jericho.Source;
import com.test.html.bean.ShoppingDetail;
public class HtmlParseTest {
public static ShoppingDetail extract(String inputHtml){
Source source = new Source(inputHtml);
Element form = source.getElementById("J_FrmBid");
List<Element> inputArea = form.getAllElements("input");
String price ="";
String area ="";
String transportInfo="";
for(Element input : inputArea){
if(input.getAttributeValue("name").equals("buy_now"))price = input.getAttributeValue("value");
if(input.getAttributeValue("name").equals("region"))area = input.getAttributeValue("value");
if(input.getAttributeValue("name").equals("who_pay_ship"))transportInfo = input.getAttributeValue("value");
}
Element others = source.getAllElementsByClass("other clearfix").get(0);
String otherInfo = others.getContent().getTextExtractor().toString().trim();
int startBabyType =otherInfo.indexOf("宝贝类型:");
int endBabyType= otherInfo.indexOf("收藏人气:");
String babyType = otherInfo.substring(startBabyType+5,endBabyType);
int endStore = otherInfo.indexOf("类似收藏");
String storeCount = otherInfo.substring(endBabyType+5,endStore-1).trim();
ShoppingDetail detail = new ShoppingDetail();
detail.setArea(area);
detail.setBabyType(babyType);
detail.setPrice(price);
detail.setStroreCount(Integer.parseInt(storeCount));
detail.setTransportInfo(transportInfo);
return detail;
}
public static void main(String[] args) throws Exception {
String content = HttpClientUtils.getContent("http://item.taobao.com/item.htm?id=3144581940", "UTF-8");
ShoppingDetail detail = HtmlParseTest.extract(content);
System.out.println(detail);
运行结果如下所示
com.test.html.bean.ShoppingDetail@1aaa14a[title=索尼
PSP 4.3寸摇杆游戏机 8G mp5高清电影+TV输出+收音,price=235.00,transportInfo=卖家承担运费,area=广东深圳,stroreCount=17711,babyType=全新
]
提取这个页面的核心代码仅为上面的那个函数,可以说从编程的复杂度而言比HtmlParser减少了不少,而且也没有繁琐的访问者模式了。
下面作为对比,我们来看看HtmlParser在这个页面解析上所做的代码量:
@Override
public boolean execute(Context context) throws Exception {
//spring若与commons chain可以集成IOC的话,就删去
parserTool = new SingleHtmlParserTool();
filterUtils = new FilterUtils();
filterUtils.setTool(new PropertiesTool("/Config/Properties/TaobaoFilter.properties"));
//这一段若研究了spring的胶水机制就删了
String url = ((String)context.get("url")).toLowerCase();
String seller_Url = "";
String seller_Nickname = "";
String seller_Taobao_Id = "";
if(url.contains(Url_Pattern)){
System.out.println("开始提取数据自"+url);
NodeList forms = parserTool.getContainerInnerTags(url, formFilter);
Map<String,String> valueMap = new HashMap<String,String>();//key-value map to store
for(int i = 0;i<forms.size();i++){
FormTag form = (FormTag)forms.elementAt(i);
NodeList inputs = form.getFormInputs();
for(int j = 0;j<inputs.size();j++){
InputTag input = (InputTag)inputs.elementAt(j);
String inputName = input.getAttribute("name");
String inputValue = input.getAttribute("value");
valueMap.put(inputName, inputValue);
}
//进入卖家分析程序分析时要用的一些Context中的值
seller_Taobao_Id = valueMap.get("seller_id");
seller_Nickname = valueMap.get("seller_nickname");
seller_Url = "http://rate.taobao.com/user-rate-"+seller_Taobao_Id+".htm";
//进入卖家分析程序分析时要用的一些Context中的值
filterUtils.filterMap(valueMap, filterStoreItemKey,
merchandiseItemSeparatorKey,
DictItem.MerchandiseItemSiteToEngine);// 过滤网址上的其他杂质<inputname="杂质" />,保证最后存于数据库的map被返回
valueMap.put("TaobaoSite_Url", url);// 最后把网页"内容"里提取不出来的url加入其中
// 存入数据库
IBasicSqlDao dao = BeanMapDaoUsingCommonsBeanutils.getInstance();
dao.storeMapToDb(valueMap, sqlId, MerchandiseItem.class);
// 存入数据库
for(Map.Entry<String, String> entry : valueMap.entrySet()){
System.out.println(entry.getKey()+":"+entry.getValue());
}
System.out.println("---页面"+url+"提取完毕---");
//重构可以删去
valueMap.clear();// 清除map
}
Context sellerContext = new UrlContext(seller_Url);
sellerContext.put("Seller_Nickname", seller_Nickname);
sellerContext.put("Seller_Taobao_Id", seller_Taobao_Id);
EmergencyLinkUrl.addUnVisitUrl(sellerContext, this);
return true;
}
return false;
}
可以明显看到,Jercho从编程风格来看,拥有这几大优势:
去除了内部类,由于Html Parser使用过滤器或访问者模式,不可避免地引入内部类。
编程使用泛型,简化编写,Html Parser没有使用泛型作为其框架,可能其创造年代较早,但是大量使用了设计模式,可以窥见其作者对设计模式的功力很深。
可以直接提取页面文本信息,将HTML标签去除。这个在全文搜索时非常常用。
Tag Search Method类似XPath的提取方式,可以不受限制地提取若干层以下的元素Element。
目前观察到的几大优势使我们有理由相信,Jercho在未来的Html解析届会成为翘楚的。以下为一篇不错的Jercho Html Parser文章推荐下:
http://www.ehelper.com.cn/blog/post/httpclient-jericho.html
我又查了一下资料,发现 jsoup HTML解析器比 htmpparser 更好
HtmlUnit 比 httpclient更易用
相关文章推荐
- android 代码实现控件之间的间距
- Python3写爬虫(四)多线程实现数据爬取
- 介绍一款信息管理系统的开源框架---jeecg
- 源码被倒卖,大厂薅羊毛,开源真的只能被予取予求?
- Scrapy的架构介绍
- [Android]在代码里运行另一个程序的方法
- 爬虫笔记
- 专家解读:开源软件项目是否会被限制出口?
- 专家解读:开源软件项目是否会被限制出口?
- 肯特·贝克:改变人生的代码整理魔法
- fuse-dfs的设定手册
- Centos下***(pptpd)的部署
- 网页恶意代码的预防
- 高手写的Tracer-Flash代码调试类代码下载
- 插件管理框架 for Delphi(一)
- CSS代码缩写技巧
- 非主流Q-zOne代码代码搜集第1/2页
- CreateWeb.vbs 代码
- Lua中编译执行代码相关的函数详解