網(wǎng)絡(luò)爬蟲內(nèi)存溢出問題
問題:
SparkStreaming 流式流式任務(wù)總是異常退出,看過worker的日志后發(fā)現(xiàn)再爬取一個二進(jìn)制文件時會出現(xiàn)堆內(nèi)存溢出的問題,將該文件下載下來后發(fā)現(xiàn)該文件的大小只有8m左右,我們的任務(wù)設(shè)置的worker內(nèi)存為3G,正常來說是不會導(dǎo)致內(nèi)存溢出的。網(wǎng)絡(luò)爬蟲的框架使用的是webmagic,于是單獨(dú)對這一段代碼進(jìn)行了debug看看。
報錯堆棧信息:Exception in thread "pool-1-thread-1" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOfRange(Arrays.java:3664) at java.lang.String.<init>(String.java:201) at java.lang.String.substring(String.java:1956) at java.lang.String.trim(String.java:2865) at org.jsoup.nodes.Element.text(Element.java:864) at us.codecraft.xsoup.xevaluator.ElementOperator$AllText.operate(ElementOperator.java:44) at us.codecraft.xsoup.xevaluator.DefaultXElement.get(DefaultXElement.java:31) at us.codecraft.xsoup.xevaluator.DefaultXElement.get(DefaultXElement.java:24) at us.codecraft.xsoup.xevaluator.DefaultXElements.list(DefaultXElements.java:47) at us.codecraft.webmagic.selector.XpathSelector.selectList(XpathSelector.java:31) at us.codecraft.webmagic.selector.HtmlNode.selectElements(HtmlNode.java:80) at us.codecraft.webmagic.selector.HtmlNode.xpath(HtmlNode.java:43)
根據(jù)提示得知時xpath部分的代碼導(dǎo)致的,我們這行代碼如下:page.getHtml.xpath("///allText()")
查了下xpath的語法,發(fā)現(xiàn)沒有///這種語法形式,
/ 從根節(jié)點選取。
表達(dá)式描述/從根節(jié)點選取。//從匹配選擇的當(dāng)前節(jié)點選擇文檔中的節(jié)點,而不考慮它們的位置。.選取當(dāng)前節(jié)點..選取當(dāng)前節(jié)點的父節(jié)點。
這部分代碼不止怎么寫成了///,但是并不會報入?yún)㈠e誤。讓我們來看看源碼是怎么寫的:
一路調(diào)試發(fā)現(xiàn)此處有一個編譯xpath字符串的代碼:public XpathSelector(String xpathStr) { this.xPathEvaluator = Xsoup.compile(xpathStr); }
這部分字符串會根據(jù)【// / |】這三個字符做一個拆分:

那么所匹配的路徑相當(dāng)于 ""和allText()


xpath被編譯成""的部分除了問題,在查詢element的時候會生成大量的對象,導(dǎo)致內(nèi)存的溢出。為什么會查詢到大量的元素呢?
當(dāng)匹配規(guī)則為空的時候,會將每一個標(biāo)簽頁當(dāng)成一個元素。例如下圖中的tag="w=w"

還有一個問題,為什么一個二進(jìn)制文件會有那么多的標(biāo)簽?zāi)兀?/strong>
當(dāng)this.html ==null的時候,會調(diào)用new Html創(chuàng)建,在創(chuàng)建后會對原來的數(shù)據(jù)添加很多標(biāo)簽public Html getHtml() { if (this.html == null) { this.html = new Html(this.rawText, this.request.getUrl()); } return this.html; }
T?T?T?*U+U,U-U.U/U0U1U2U3U4U5U6U7U8U9U:U;U <w=w>
那么在調(diào)用selectelement的時候,會將每一個標(biāo)簽映射為一個對象,導(dǎo)致創(chuàng)建了2000多個對象。
鏈接:https://www.dianjilingqu.com/473445.html