陈浩然 2025-11-02 01:53:11
每经编辑|陈玉雯
当地时间2025-11-02,mjwysadhwejkrbdsfjhbsdvf,健身房强上
【Java】【HTMLParser】精通(tong)HTML解析的秘(mi)密武(wu)器(qi):HTMLParser的强大(da)应用(yong)与实战技巧(qiao)
在(zai)当今信息(xi)爆炸的(de)时(shi)代,数(shu)据的价值日(ri)益(yi)凸显。而(er)互(hu)联网(wang),作为(wei)海(hai)量信(xin)息(xi)的宝库(ku),更是吸引着无数开(kai)发(fa)者前去(qu)挖(wa)掘(jue)。在(zai)进行网络数据(ju)抓取时(shi),HTML解析无(wu)疑是其中(zhong)至关(guan)重(zhong)要(yao)的一(yi)环。想象一下(xia),您面(mian)对(dui)着(zhe)一(yi)个(ge)复(fu)杂的(de)HTML文档,需要从中(zhong)精准(zhun)地提(ti)取出特(te)定(ding)的文本信(xin)息、链接,甚至是(shi)表格(ge)数(shu)据(ju),这(zhe)该(gai)是多么令人头(tou)疼的(de)任务?幸运(yun)的是(shi),Java社区(qu)为我(wo)们提供了(le)强(qiang)大的工具,而(er)HTMLParser便是(shi)其中一颗(ke)璀璨的明(ming)珠。
HTMLParser是(shi)一个(ge)用Java编写的(de)、轻量(liang)级的(de)、高效(xiao)的HTML解析器。它能够以多种(zhong)方(fang)式(shi)解(jie)析HTML,包(bao)括(kuo)但不(bu)限于(yu)DOM(DocumentObjectModel)解析,并(bing)提供了(le)一(yi)系(xi)列便捷的(de)API,让您可以(yi)轻松地遍历、搜索和(he)提取HTML文(wen)档中的内(nei)容。
相较于(yu)一(yi)些其他的(de)解析(xi)库,HTMLParser的(de)优势(shi)在于它的(de)简洁性、易(yi)用性以及对(dui)不(bu)规范(fan)HTML的良好容(rong)错(cuo)性。这(zhe)使(shi)得它在各(ge)种Web抓(zhua)取、数据分(fen)析(xi)、内(nei)容聚(ju)合等(deng)项(xiang)目中大(da)放(fang)异(yi)彩(cai)。
在正(zheng)式开(kai)始(shi)实战之(zhi)前,我们有(you)必要(yao)先(xian)理解HTMLParser的一些核心概念(nian)。
Parser类(lei):这(zhe)是HTMLParser的(de)入(ru)口(kou)点(dian)。您(nin)可以(yi)通过(guo)Parser.parse(url)或Parser.parse(newURL(url))来获取一个(ge)Document对象,其中(zhong)url是您(nin)想要解析的HTML网(wang)页(ye)的(de)地址(zhi)。
Document对(dui)象:代表(biao)了整个HTML文档。它包含(han)了文(wen)档的(de)所有节点(dian),如元素、文(wen)本、注(zhu)释(shi)等(deng)。您(nin)可以将(jiang)Document对(dui)象想(xiang)象(xiang)成一(yi)个树(shu)状(zhuang)结构,其(qi)中根(gen)节点是整(zheng)个(ge)HTML文档(dang)。Node接口:HTML文(wen)档中的所有元(yuan)素(su)、文(wen)本、标签等(deng)都可以看(kan)作(zuo)是(shi)Node。
Node接口(kou)提供(gong)了一系(xi)列(lie)通用(yong)的方(fang)法来访问(wen)和(he)操(cao)作节点。NodeList:当您通(tong)过某(mou)些方法获(huo)取(qu)到(dao)多(duo)个节(jie)点时(shi),它们(men)通(tong)常(chang)会(hui)被(bei)封装(zhuang)在(zai)一个NodeList中。您(nin)可以(yi)像遍(bian)历数组一(yi)样(yang)遍(bian)历NodeList,并访问其中(zhong)的每(mei)一个Node。Tag类:Tag类代表了(le)HTML中的一(yi)个标(biao)签(qian),例如
,,
它(ta)提(ti)供了(le)获取(qu)标签名(ming)、属(shu)性(xing)名(ming)、属性(xing)值等(deng)方法(fa)。TextNode类:代表HTML中(zhong)的文(wen)本内(nei)容(rong)。
让我(wo)们从最基(ji)础(chu)的(de)开(kai)始,看看如何使用(yong)HTMLParser来解析一个网(wang)页并提取其(qi)中(zhong)的文本内容。
您(nin)需要(yao)将HTMLParser添(tian)加到您的(de)Java项(xiang)目(mu)中。如果您(nin)使用(yong)Maven,可(ke)以在pom.xml中添加(jia)如(ru)下(xia)依赖:
org.htmlparserhtmlparser2.1
我们编写(xie)一个(ge)简(jian)单(dan)的Java方(fang)法来解析(xi)URL并提取文(wen)本(ben):
importorg.htmlparser.Parser;importorg.htmlparser.util.ParserException;importorg.htmlparser.nodes.TextNode;importorg.htmlparser.nodes.CompositeNode;importorg.htmlparser.Node;publicclassHtmlParserExample{publicstaticStringextractTextFromUrl(Stringurl){StringBuildertextContent=newStringBuilder();try{Parserparser=newParser(url);NoderootNode=parser.parse(null);//null表示使(shi)用默认的ParserFilter//递归(gui)遍历节(jie)点,提取文本(ben)extractTextRecursively(rootNode,textContent);}catch(ParserExceptione){e.printStackTrace();return"ErrorparsingURL:"+e.getMessage();}returntextContent.toString();}privatestaticvoidextractTextRecursively(Nodenode,StringBuildertextContent){if(nodeinstanceofTextNode){textContent.append(((TextNode)node).getText()).append("\n");}elseif(nodeinstanceofCompositeNode){Node[]children=node.getChildrenAsNodeArray();if(children!=null){for(Nodechild:children){extractTextRecursively(child,textContent);}}}}publicstaticvoidmain(String[]args){StringwebsiteUrl="http://example.com";//替(ti)换(huan)为(wei)您想(xiang)解(jie)析的(de)URLStringextractedText=extractTextFromUrl(websiteUrl);System.out.println("ExtractedText:\n"+extractedText);}}
在这个例(li)子(zi)中(zhong),我们首先创建一个Parser对象(xiang),然后(hou)调(diao)用(yong)parse(null)方法(fa)来解析URL。parser.parse(null)返回的(de)是整个文档(dang)的(de)根节点(dian)。接着,我(wo)们定义了一个(ge)递归(gui)方(fang)法extractTextRecursively来遍(bian)历文档树(shu)。
当(dang)遇(yu)到TextNode时,我(wo)们(men)就将其(qi)文(wen)本(ben)内(nei)容添(tian)加到(dao)textContent中(zhong)。
这段代码展示了HTMLParser的基本(ben)用法,它能够(gou)将一(yi)个完(wan)整的(de)HTML页(ye)面(mian)“翻译”成(cheng)可(ke)读(du)的文本。这对(dui)于快(kuai)速预(yu)览网(wang)页内(nei)容或者进(jin)行(xing)简单的(de)文本分析(xi)非(fei)常有用(yong)。这(zhe)仅仅是(shi)HTMLParser冰山(shan)一角(jiao)。在(zai)接下来(lai)的(de)部分,我(wo)们(men)将深入挖掘(jue)它(ta)更强大的功能(neng),让(rang)您能够(gou)精(jing)确地定位并(bing)提取您所(suo)需(xu)的数(shu)据。
在实(shi)际应(ying)用中,我们通常(chang)不会(hui)想要(yao)提取网页(ye)的全部(bu)文(wen)本,而(er)是需(xu)要精确地定(ding)位到特(te)定的(de)元(yuan)素(su),例如(ru)所有(you)的链接、特(te)定class的(de)div、或者(zhe)某个(ge)id的元素。HTMLParser提(ti)供(gong)了(le)强大(da)的过(guo)滤和(he)查找(zhao)机制,让这(zhe)种精确(que)操作变(bian)得触手可及(ji)。
HTMLParser的核(he)心(xin)过滤机制(zhi)是(shi)NodeFilter接口。您可以实现(xian)这个(ge)接(jie)口,定(ding)义自己(ji)的过滤(lv)规则,来(lai)选择(ze)您(nin)感兴趣的节(jie)点。最常用(yong)的(de)NodeFilter实现类是TagNameFilter(按(an)标签(qian)名(ming)过滤)和(he)AndFilter(组合多(duo)个(ge)过滤(lv)器)。
importorg.htmlparser.Parser;importorg.htmlparser.filters.TagNameFilter;importorg.htmlparser.nodes.TagNode;importorg.htmlparser.util.ParserException;importorg.htmlparser.NodeIterator;importorg.htmlparser.Node;importorg.htmlparser.util.NodeList;publicclassLinkExtractor{publicstaticvoidextractLinks(Stringurl){try{Parserparser=newParser(url);//使(shi)用(yong)TagNameFilter来(lai)只选择(ze)标签(qian)NodeListnodeList=parser.extractAllNodesThatMatch(newTagNameFilter("a"));for(inti=0;i
在这(zhe)个例子中(zhong),TagNameFilter("a")会告(gao)诉HTMLParser只(zhi)返回(hui)标签(qian)。然后,我们(men)遍历这些(xie)标签,并从(cong)中提(ti)取(qu)href属(shu)性(xing)的值。这(zhe)只(zhi)是NodeFilter的(de)一个简(jian)单应用,您还(hai)可(ke)以组(zu)合多个过(guo)滤器(qi),例如同时(shi)按标(biao)签名和(he)属(shu)性名(ming)进行(xing)过滤(lv),实(shi)现更(geng)精(jing)细(xi)的(de)选择。
除(chu)了使用过滤器(qi),您还(hai)可(ke)以(yi)直(zhi)接遍历Document的DOM树,并结(jie)合(he)条件判(pan)断来(lai)查找(zhao)特定元素(su)。这在处(chu)理结构(gou)相对固定(ding)的HTML时(shi)非常有(you)效。
importorg.htmlparser.Parser;importorg.htmlparser.nodes.TagNode;importorg.htmlparser.util.ParserException;importorg.htmlparser.Node;importorg.htmlparser.NodeVisitor;publicclassSpecificElementFinder{publicstaticvoidfindDivById(Stringurl,StringtargetId){try{Parserparser=newParser(url);NoderootNode=parser.parse(null);//使(shi)用(yong)NodeVisitor来(lai)遍历(li)节(jie)点rootNode.accept(newNodeVisitor(){@OverridepublicvoidvisitTag(TagNodetag){//检查(cha)是否(fou)是(shi)div标(biao)签,并且id属(shu)性匹(pi)配if("div".equalsIgnoreCase(tag.getTagName())&&targetId.equals(tag.getAttribute("id"))){System.out.println("Founddivwithid'"+targetId+"':"+tag.toHtml());//如(ru)果只需要第一个匹(pi)配(pei)的,可以(yi)在这里设(she)置(zhi)一(yi)个标(biao)志(zhi)并中断(duan)遍历(li)}super.visitTag(tag);//继(ji)续(xu)访问(wen)子节点}});}catch(ParserExceptione){e.printStackTrace();}}publicstaticvoidmain(String[]args){StringwebsiteUrl="http://example.com";//替换为您想(xiang)解析(xi)的URLStringidToFind="main-content";//替(ti)换为您想查(cha)找(zhao)的idfindDivById(websiteUrl,idToFind);}}
NodeVisitor是一个(ge)强大(da)的遍(bian)历(li)工具,它允许您在(zai)遍(bian)历(li)DOM树的过程中(zhong),对(dui)不同(tong)类型的节(jie)点(dian)执行自定义(yi)操作。在这(zhe)个例(li)子中(zhong),我们(men)重写(xie)了(le)visitTag方法,当(dang)遇到(dao)
2025-11-02,小白袜小学生榨精,基辅之星CEO:俄乌和平协议将提升其在美国上市后的价值
1.伽罗去衣,德法英意芬及北约和欧盟领导人,集体赴美一区男同调教性奴,全域协同:AI-COP助力天津旅游集团数智跃迁
图片来源:每经记者 陈小茹
摄
2.17c一起草+ 国卢+无毛一线天萌白酱,美版“花呗”Affirm(AFRM.US)Q4业绩超预期 股价盘后飙升
3.嘉青娱乐+金银酶15,寒武纪逆市冲锋,登顶A股成交第一!科创人工智能ETF(589520)随市回调,近5日连续吸金1.25亿元
友妻社区+崩坏三堕落的浮华,增值率达439%业绩补偿覆盖率仅39%!海兰信超10亿元并购引关注
御梦子糖心logo-御梦子糖心甜蜜梦境,logo启航
封面图片来源:图片来源:每经记者 名称 摄
如需转载请与《每日经济新闻》报社联系。
未经《每日经济新闻》报社授权,严禁转载或镜像,违者必究。
读者热线:4008890008
特别提醒:如果我们使用了您的图片,请作者与本站联系索取稿酬。如您不希望作品出现在本站,可联系金年会要求撤下您的作品。
欢迎关注每日经济新闻APP