钱夙伟 2025-11-01 22:43:11
每经编辑|陈冠达
当地时间2025-11-01,gfyuweutrbhedguifhkstebtj,WWWWXXXXWWW日本
【Java】【HTMLParser】精通(tong)HTML解析(xi)的(de)秘(mi)密武(wu)器:HTMLParser的强(qiang)大(da)应用与(yu)实战技(ji)巧
在(zai)当今信(xin)息(xi)爆炸(zha)的时(shi)代,数(shu)据的价值日益(yi)凸显。而互(hu)联(lian)网(wang),作为海量信息(xi)的宝库(ku),更(geng)是吸引着无数(shu)开发(fa)者前(qian)去挖掘(jue)。在(zai)进行网络数据(ju)抓取时(shi),HTML解(jie)析(xi)无(wu)疑是(shi)其中至关重要(yao)的一(yi)环(huan)。想(xiang)象一(yi)下,您(nin)面对(dui)着(zhe)一个复杂的(de)HTML文档(dang),需要从中(zhong)精(jing)准(zhun)地提(ti)取(qu)出(chu)特定的(de)文(wen)本信(xin)息(xi)、链接(jie),甚(shen)至是表格(ge)数(shu)据,这该是多(duo)么(me)令人头(tou)疼(teng)的任务?幸(xing)运(yun)的是,Java社区为我们(men)提供了强大(da)的工具,而(er)HTMLParser便是其中(zhong)一(yi)颗(ke)璀璨的明珠(zhu)。
HTMLParser是(shi)一个(ge)用Java编写(xie)的、轻量(liang)级(ji)的(de)、高效的(de)HTML解(jie)析器(qi)。它能够(gou)以(yi)多种方式解析(xi)HTML,包(bao)括(kuo)但不限于(yu)DOM(DocumentObjectModel)解(jie)析,并(bing)提(ti)供了(le)一系(xi)列便捷(jie)的(de)API,让您可以轻松(song)地遍(bian)历、搜索和提取HTML文档中(zhong)的内容(rong)。
相较于一(yi)些其他的(de)解析(xi)库,HTMLParser的优(you)势(shi)在于(yu)它(ta)的简洁性、易(yi)用性(xing)以及(ji)对不(bu)规(gui)范HTML的(de)良好容(rong)错性(xing)。这(zhe)使(shi)得(de)它(ta)在各种Web抓(zhua)取(qu)、数(shu)据分(fen)析(xi)、内容聚(ju)合等(deng)项目中大(da)放异彩。
在正(zheng)式(shi)开始实(shi)战之前,我(wo)们有必(bi)要先(xian)理解(jie)HTMLParser的一(yi)些核(he)心(xin)概念。
Parser类:这是(shi)HTMLParser的入口(kou)点。您可(ke)以(yi)通过(guo)Parser.parse(url)或Parser.parse(newURL(url))来获取一个(ge)Document对象(xiang),其中(zhong)url是您想要(yao)解析(xi)的HTML网(wang)页的地(di)址(zhi)。
Document对象:代(dai)表(biao)了整(zheng)个(ge)HTML文档。它包含(han)了文档的(de)所有节点(dian),如(ru)元(yuan)素、文(wen)本、注(zhu)释等。您可(ke)以将(jiang)Document对象(xiang)想(xiang)象成一(yi)个树(shu)状结(jie)构,其(qi)中根节(jie)点是整(zheng)个HTML文档。Node接口:HTML文(wen)档(dang)中的(de)所(suo)有元(yuan)素、文本、标签等(deng)都可(ke)以(yi)看(kan)作是(shi)Node。
Node接口(kou)提供了一系(xi)列通(tong)用(yong)的方(fang)法(fa)来(lai)访问(wen)和(he)操(cao)作节点。NodeList:当您通过某(mou)些方法(fa)获(huo)取(qu)到多个节点(dian)时,它(ta)们通常会(hui)被封装在(zai)一个NodeList中。您可以(yi)像遍(bian)历数组(zu)一(yi)样遍(bian)历NodeList,并(bing)访(fang)问(wen)其中(zhong)的每(mei)一个(ge)Node。Tag类:Tag类(lei)代表(biao)了(le)HTML中的(de)一(yi)个标签(qian),例(li)如
,,
它提供(gong)了(le)获取(qu)标签(qian)名、属(shu)性名、属性值等(deng)方(fang)法(fa)。TextNode类(lei):代表(biao)HTML中的文(wen)本内容。
让我(wo)们(men)从最基(ji)础的开始(shi),看看(kan)如何使(shi)用(yong)HTMLParser来(lai)解析一个网(wang)页并提(ti)取(qu)其(qi)中的文(wen)本(ben)内容。
您需要(yao)将HTMLParser添(tian)加到(dao)您的(de)Java项目(mu)中。如果您(nin)使用Maven,可(ke)以(yi)在pom.xml中(zhong)添加如(ru)下依赖(lai):
org.htmlparserhtmlparser2.1
我们(men)编(bian)写一个简单(dan)的Java方法来(lai)解析(xi)URL并(bing)提取(qu)文(wen)本:
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表示使用默认(ren)的ParserFilter//递归遍历节点(dian),提取文本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)换为(wei)您想解(jie)析的URLStringextractedText=extractTextFromUrl(websiteUrl);System.out.println("ExtractedText:\n"+extractedText);}}
在这(zhe)个(ge)例(li)子中,我们首先(xian)创建一个(ge)Parser对象,然后调用parse(null)方法(fa)来解析URL。parser.parse(null)返回的(de)是整(zheng)个文(wen)档的(de)根节点(dian)。接(jie)着,我们定义了一个(ge)递归(gui)方法extractTextRecursively来遍历文(wen)档树。
当遇(yu)到TextNode时(shi),我们(men)就(jiu)将其文本内容添(tian)加到textContent中(zhong)。
这段代(dai)码展示了(le)HTMLParser的基(ji)本(ben)用法,它(ta)能够(gou)将一(yi)个完(wan)整的(de)HTML页面“翻(fan)译(yi)”成可(ke)读的(de)文(wen)本。这对(dui)于快速(su)预(yu)览网页(ye)内(nei)容(rong)或者进(jin)行简(jian)单(dan)的文本(ben)分析非常(chang)有用(yong)。这仅仅是(shi)HTMLParser冰山(shan)一角(jiao)。在(zai)接下来的部(bu)分(fen),我(wo)们将(jiang)深入(ru)挖(wa)掘它更强大(da)的功(gong)能,让(rang)您(nin)能够精确地(di)定位并提(ti)取您(nin)所需的数据。
在实际应用中(zhong),我(wo)们通常(chang)不会想(xiang)要提取(qu)网(wang)页的全(quan)部文(wen)本,而是需(xu)要精(jing)确(que)地(di)定(ding)位(wei)到特(te)定(ding)的(de)元(yuan)素(su),例如(ru)所有(you)的(de)链接、特(te)定class的div、或者(zhe)某(mou)个(ge)id的元(yuan)素(su)。HTMLParser提(ti)供了(le)强大的(de)过滤和(he)查找机(ji)制,让这(zhe)种精(jing)确操(cao)作(zuo)变(bian)得触(chu)手(shou)可及。
HTMLParser的核(he)心过滤(lv)机制是NodeFilter接口。您可(ke)以实现(xian)这个(ge)接(jie)口(kou),定(ding)义自己的过(guo)滤规(gui)则,来(lai)选择(ze)您(nin)感(gan)兴趣的节(jie)点。最常用(yong)的(de)NodeFilter实现类是TagNameFilter(按(an)标签名过滤)和AndFilter(组合多个过滤(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);//使用(yong)TagNameFilter来只选(xuan)择(ze)标签NodeListnodeList=parser.extractAllNodesThatMatch(newTagNameFilter("a"));for(inti=0;i
在这(zhe)个例(li)子中(zhong),TagNameFilter("a")会告诉HTMLParser只(zhi)返回标(biao)签(qian)。然后,我们(men)遍历这些(xie)标签(qian),并从(cong)中(zhong)提(ti)取href属性的值(zhi)。这(zhe)只是NodeFilter的(de)一个简(jian)单(dan)应用(yong),您还可(ke)以组合多个过滤(lv)器,例如同时(shi)按标签(qian)名和(he)属(shu)性名进(jin)行过滤,实现(xian)更(geng)精细的选择。
除(chu)了(le)使用(yong)过滤器(qi),您(nin)还(hai)可(ke)以(yi)直接遍历(li)Document的(de)DOM树,并结(jie)合条(tiao)件(jian)判(pan)断来查找(zhao)特(te)定元素(su)。这在(zai)处理(li)结构相对(dui)固(gu)定(ding)的(de)HTML时(shi)非常有效。
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)用NodeVisitor来(lai)遍历节点(dian)rootNode.accept(newNodeVisitor(){@OverridepublicvoidvisitTag(TagNodetag){//检(jian)查(cha)是否是div标签,并(bing)且id属(shu)性匹配if("div".equalsIgnoreCase(tag.getTagName())&&targetId.equals(tag.getAttribute("id"))){System.out.println("Founddivwithid'"+targetId+"':"+tag.toHtml());//如(ru)果只需(xu)要(yao)第一(yi)个匹(pi)配(pei)的(de),可以(yi)在这里设置一(yi)个标(biao)志并中断遍历(li)}super.visitTag(tag);//继续访问(wen)子节(jie)点}});}catch(ParserExceptione){e.printStackTrace();}}publicstaticvoidmain(String[]args){StringwebsiteUrl="http://example.com";//替换(huan)为(wei)您想(xiang)解析的URLStringidToFind="main-content";//替(ti)换为您(nin)想查找(zhao)的idfindDivById(websiteUrl,idToFind);}}
NodeVisitor是一个(ge)强大(da)的遍历工(gong)具,它(ta)允许(xu)您(nin)在(zai)遍历DOM树的(de)过程中,对(dui)不同类(lei)型的(de)节(jie)点执行自定义(yi)操作。在(zai)这(zhe)个例(li)子中,我们(men)重写(xie)了(le)visitTag方法,当(dang)遇到(dao)
2025-11-01,双人啪啪秀喷水第二部,瑞普生物:截至2025年7月18日公司股东总户数约2.9万户
1.19分钟真实录音完整mp3下载,炒股必备!五款顶尖财经 APP 深度剖析男桶女网站,市场焦点转向以太币 比特币徘徊在七周低点附近
图片来源:每经记者 阿西木·卡斯姆
摄
2.亚洲经典一曲二曲三曲区别+隔着丝袜插入长腿御姐,特朗普称英特尔首席执行官存在严重利益冲突 除了辞职外别无他法
3.男生和女生一起相嗟嗟嗟免费观看动漫+腰塌下屁股撅起来打肿,谷歌测试升级后的谷歌财经,新增人工智能功能及实时新闻流
17路c14cm+MEYD934CN除了女朋友之,大商股份:9月12日将召开2025年半年度业绩说明会
视频科普!少司缘流眼泪翻白眼流口水.详细解答、解释与落实引发
封面图片来源:图片来源:每经记者 名称 摄
如需转载请与《每日经济新闻》报社联系。
未经《每日经济新闻》报社授权,严禁转载或镜像,违者必究。
读者热线:4008890008
特别提醒:如果我们使用了您的图片,请作者与本站联系索取稿酬。如您不希望作品出现在本站,可联系金年会要求撤下您的作品。
欢迎关注每日经济新闻APP