html解析器
瀏覽器解析html的過程如下:
HTML解析器的工作是解析HTML標記到解析樹
1)HTML語法定義
HTML的詞彙與句法定義在w3c組織創建的規范中。當前版本是HTML4,HTML5的工作正在進行中。
2)不是上下文無關語法
在對解析器的介紹中看到,語法可以用類似BNF的格式規范地定義。不幸的是所有常規解析器的討論都不適用於HTML(我提及它們並不是為了娛樂,它們可以用於解析CSS和javaScript)。HTML無法用解析器所需的上下文無關的語法來定義。過去HTML格式規范由DTD (Document Type Definition)來定義,但它不是一個上下文無關語法。
HTML與XML相當接近。XML有許多可用的解析器。HTML還有一個XML變種叫XHTML,那麼它們主要區別在哪裡呢?區別在於HTML應用更加」寬容」,它容許你漏掉一些開始或結束標簽等。它整個是一個「軟」句法,不像XML那樣嚴格死板。 總的來說這一看似細微的差別造成了兩個不同的世界。一方面這使得HTML很流行,因為它包容你的錯誤,使網頁作者的生活變得輕松。另一方面,它使編寫語法格式變得困難。所以綜合來說,HTML解析並不簡單,現成的上下文相關解析器搞不定,XML解析器也不行。
3)HTML DTD
HTML的定義使用DTD文件。這種格式用來定義SGML族語言,它包含對所有允許的元素的定義,包括它們的屬性和層級關系。如我們前面所說,HTML DTD構不成上下文無關語法。
DTD有幾種不同類型。嚴格模式完全尊守規范,但其它模式為了向前兼容可能包含對早期瀏覽器所用標簽的支持。當前的嚴格模式DTD:http://www.w3.org/TR/html4/strict.dtd
4)DOM
解析器輸出的樹是由DOM元素和屬性節點組成的。DOM的全稱為:Document Object Model。它是HTML文檔的對象化描述,也是HTML元素與外界(如Javascript)的介面。
DOM與標簽有著幾乎一一對應的關系,如下:
<html>
<body>
<p>hello world</p>
<div><img src="aa.png"/></div>
</body>
</html>
② HTML哪個解析器是最好的
個人比較喜歡用:HtmlCleaner解析器,你試試
③ python html 解析工具是什麼意思
在准備我的 PyCon上關於HTML的演講 的時候我覺得我應該對現有的一些解析器和文檔模型做個性能對比。
實際上,情況有點復雜,因為處理HTML需要幾個步驟:
解析這個 HTML
把它解析為一個對象(比如一個文檔對象)
把它序列化
有些解析器只處理第一步,有些只處理第二步,有些能處理所有的三個步驟…。例如,ElementSoup 使用 ElementTree 來表示文檔,卻使用 BeautifulSoup 作為實際的解析器。而 BeautifulSoup 內部也擁有一個文檔對象。 HTMLParser 僅僅做解析(不解析出任何對象),然而 html5lib 卻能夠生成幾種不同的文檔樹(DOM樹)。序列化也分為XML和HTML兩種方式。
所以我選取了下面這些解析器的庫做基準性能測試:
lxml:包含一個解析器,能夠產生文檔對象,支持HTML序列化。它也可以不適用內置的解析器而使用 BeautifulSoup 或者 html5lib 進行解析。
BeautifulSoup:nbsp;包含一個解析器,能夠產生文檔對象,支持HTML序列化。
html5lib:有解析器。它也有一個序列化器,但是我沒有使用它。它也有一個內置的文檔對象(即simpletree),只是…除了自我測試我也不知道這東西還能做什麼。
ElementTree:這個包里有一個XML序列化器,ElementTree能夠產生文檔對象,它也是python內置的XML解析模塊。(我覺得下個版本會帶一個HTML序列化器,不過我也沒測試這個XML序列化器)。它也有一個解析器,測試的時候我用html5lib當做解析器來測試ElementTree的。
cElementTree:這是一個使用C語言擴展實現的python模塊,實現了ElementTree。
HTMLParser:包含一個解析器。但是其實它不能解析出文檔對象,很多正常網頁都不能正常處理(包含Table或者Script),有語法錯誤的網頁就更處理不了了。它只是使用解析器遍歷文檔。
htmlfill:它使用了HTMLParser作為解析器,相對HTMLParser,它在解析過程中對Element做了更多處理。
Genshi[1]:包含一個解析器,能夠產生文檔對象,支持HTML序列化。
xml.dom.minidom:python標准庫里的內置文檔模型,html5lib 能夠解析出這種文檔對象。(我並不推薦使用minidom — 這篇文章里寫了一些理由,還有很多理由我沒寫出來)
我預想 lxml 的性能會比較好,因為它基於 libxml2這個C庫。但是實際上它的性能比我預計的還要好,超過其它所有的同類庫。所以,除非考慮到一些難以解決的安裝問題(尤其是在Mac上),我都推薦你用lxml 來進行HTML解析的工作。
我的測試代碼在這里,你可以自己下載下來運行測試程序。裡麵包含了所有的樣例數據,用來生成圖表的命令在這里。這些測試數據來自於從 python.org 隨機選取的一些頁面(總共355個)。
解析
lxml:0.6; BeautifulSoup:10.6; html5lib ElementTree:30.2; html5lib minidom:35.2; Genshi:7.3; HTMLParser:2.9; htmlfill:4.5
第一個測試運行這些解析器解析文檔。需要注意的是:lxml 比 HTMLParser快6倍,盡管 HTMLParser
不生成任何文檔對象(lxml在內存中建立了一個文檔樹)。這里也沒有包含 html5lib 所能生成的全部種類的樹,因為每一種花費的時間都差不多。之所以包含了使用 xml.dom.minidom 作為輸出結果的 html5lib 測試結果是為了說明 minidom 有多慢。Genshi確實很快,只是它也是最不穩定的,相比之下,html5lib , lxml 以及 BeautifulSoup 都要健壯的多。html5lib 的好處是,總是能夠正確的解析HTML(至少在理論上如此)。
lxml在解析過程中會釋放 GIL ,但是我覺得應該影響不大。
序列化
lxml:0.3; BeautifulSoup:2.0; html5lib ElementTree:1.9; html5lib minidom:3.8; Genshi:4.4
所有這些庫執行序列化都很快,可是 lxml 又一次遙遙領先。ElementTree 和 minidom 只做XML序列化,但是沒有理由說HTML序列化更快。還有就是,Genshi居然比minidom要慢,實話說任何比minidom要慢的東西都挺讓人震驚的。
內存佔用
lxml:26; BeautifulSoup:82; BeautifulSoup lxml:104; html5lib cElementTree:54; html5lib ElementTree:64; html5lib simpletree:98; html5lib minidom:192; Genshi:64; htmlfill:5.5; HTMLParser:4.4
最後一項測試是內存。我並不是特別確信我做這個測試的方法很科學,但是數據總能說明一些問題。這項測試會解析所有的文檔並把解析出來的DOM樹保存在內存中,利用 ps 命令結果的RSS(resident set size)段來表示進程佔用的內存。計算基準內存佔用之後所有的庫已經被import,所以只有解析HTML和生成文檔對象會導致內存使用量上升。
我才用 HTMLParser 作為基準線,因為它把文檔保存在內存中,只產生一些中間字元串。這些中間字元串最終也不回佔用多少內存,因為內存佔用基本上等同於這些html問價大小之和。
測量過程中有個棘手的問題就是python的內存分配器並不會釋放它請求的內存,所以,如果一個解析器創建了很多中間對象(字元串等等)然後又釋放了它們,進程仍然會持有這些內存。為了檢測是否有這種情況,我試著分配一些新的字元串知道進程佔用的內存增長(檢測已經分配但是沒有被使用的內存),但是實際上沒檢測到什麼,只有 BeautifulSoup 解析器,在序列化到一個 lxml 樹的時候,顯示出使用了額外的內存。
只有在內存測試中,html5lib 使用 cElementTree 來表示文檔對象同使用 ElementTree 能表現出明顯的不同。我倒不是很驚訝,我猜因為我沒有找到一個C語言編寫的序列化工具,我猜使用 cElementTree 構建文檔樹的話,只有在用本地代碼調用它的時候比較快(就像本地的libxml,並且不需要把數據結構傳遞到python中)。
lxml比較節省內存很可能是因為它使用了本地的libxml2的數據結構,並且只有在需要的時候才創建Python對象。
總結
在進行基準測試之前我就知道lxml會比較快,但是我自己也沒料到會這么快。
所以呢,總結一下:lxml太牛逼了[2]。你可以用很多種方式使用它,你可以對一個HTML進行解析,序列化,解析,再序列化,在機器卡機之前你能重復這些操作很多次。很多操作都是通過本地介面實現的,python只做了一層很淺的封裝。例如,如果你做一次XPath查詢,查詢字元串會被編譯為本地代碼,然後遍歷本地的libxml2對象,只在返回查詢結果的時候才會產生一個python對象。 另外,測試中lxml內存佔用比較小使我更有理由相信lxml在高負載的情況下仍然會很可靠。
我覺得,文檔樹相對按字元流解析(不生成樹,只掃描一次文檔並針對特定的標簽做處理)更有優勢。表面看起來按字元流解析更好:你不把整個文檔放在內存里,處理的時間之和文檔大小線性相關。HTMLParser就是這樣一種解析器,遇到各種符號(標簽開始和關閉,變遷中間的文字等等)。Genshi 也是用的這個模型,因為使用了一些更高級的特性(比如 filters
)所以使用起來更自然一些。其實字元流模型本身就不是一種特別自然的處理XML文檔的方式,從某種程度上說,它只是用來處理一些本來就可以當做字元串處理的文檔的一種笨拙的方法(regex可以實現同樣的功能)。只有你需要處理上G的XML文件的時候按字元流解析才有意義(不過lxml和ElementTree針對這種情況都有額外的參數支持)。HTML文件不會有這么大,這些測試也有理由讓我們相信lxml可以很好的處理大的HTML文件,所以一個大文檔也不會導致一個為小文檔優化過的系統崩潰。
Ian Bicking on Sunday, March30th, 2008
[1]. Genshi是EdgewallSoftware的產品,它的其他產品還包括大名鼎鼎的Trac。
[2]. 本文的作者Ian Bicking是lxml.html(lxml的一個模塊)的開發者和維護者(這里修正一下)。
P.S. 譯者記:這里還有一個解析器沒有提到就是python標准庫里的SGMLParser,它也可以產生ElementTree,但是性能很差,本機測試解析600k的html文檔(ddd的單頁html文檔)需要480秒,不推薦應用在性能要求比較高的場合。本文作者也是lxml的作者,對自己的作品大力推薦也是正常的,我實測過lxml性能確實很好。
④ JavaScript的HTML解析器 node-htmlparser如何使用
你好,根據你問題的描述,你要使用的應該不是htmlparser功能,而應該是xmldom包,給你個例子:
varxmldom=require('xmldom'),
html='<divclass="abc"><divid="def">aaa</div><ahref="#"target="_blank">deflink</a></div>';
vardp=newxmldom.DOMParser();
vardom=dp.parseFromString(html);
console.log(dom.getElementById('def'));//element
console.log(dom.getElementsByTagName('a'));//NodeList
將代碼保存為index.js,在index.js目錄下執行
npminstall--savexmldom
然後執行
nodeindex
會看類似下面的結果:
更詳細的使用方法,請自行前往npm官網,搜索xmldom查看!
希望是你想要的答案,望點贊~~
⑤ html解析 <br/>問題
不知道你引入的.h文件是幹啥用的,但是把你的html放上去是會出現換行效果的呀,我截了個圖;你是在那個瀏覽器上顯示不對的呢,也可能是瀏覽器版本太低的原因吧;
⑥ HTML解析器是什麼
解析html語言,獲取想要的部分,如一個網頁里有一篇文章,你只想要這篇文章,其餘網頁元素都不要,用HTML解析器就能完美分離這篇文章,網上有很多
⑦ 瀏覽器如何解析html
一般復 HTML 是通過 webview 來顯示的。一般簡制單的 html 是通過
解析字元串來解析。沒有成熟現成 html 解析器。
一般伺服器去抓取 html 解析 html 形成 json xml 文件供手機端讀
取。
⑧ web 瀏覽器是使用的什麼解析器解析html
為什麼要研究這個?不同的瀏覽器可能會有不同的解析html的解析器,比如IE和其他瀏覽器
⑨ 如何將一個html頁面解析
瀏覽器載入和渲染的順序
1. IE下載的順序是從上到下,渲染的順序也是從上到下,下載和渲染是同時進行的。
2. 在渲染到頁面的某一部分時,其上面的所有部分都已經下載完成(並不是說所有相關聯的元素都已經下載完)。
3. 如果遇到語義解釋性的標簽嵌入文件(JS腳本,CSS樣式),那麼此時IE的下載過程會啟用單獨連接進行下載。
4. 樣式表在下載完成後,將和以前下載的所有樣式表一起進行解析,解析完成後,將對此前所有元素(含以前已經渲染的)重新進行渲染。
5. JS、CSS中如有重定義,後定義函數將覆蓋前定義函數。
JS的載入
1. 不能並行下載和解析(阻塞下載)。
2. 當引用了JS的時候,瀏覽器發送1個js request就會一直等待該request的返回。因為瀏覽器需要1個穩定的DOM樹結構,而JS中很有可能有
代碼直接改變了DOM樹結構,比如使用 document.write 或 appendChild,甚至是直接使用的location.href進行跳轉,瀏覽器為了防止出現JS修
改DOM樹,需要重新構建DOM樹的情況,所以 就會阻塞其他的下載和呈現.
如何加快HTML頁面載入速度
1. 頁面減肥:
a. 頁面的肥瘦是影響載入速度最重要的因素。
b. 刪除不必要的空格、注釋。
c. 將inline的script和css移到外部文件。
d. 可以使用HTML Tidy來給HTML減肥,還可以使用一些壓縮工具來給JavaScript減肥。
2. 減少文件數量:
a. 減少頁面上引用的文件數量可以減少HTTP連接數。
b. 許多JavaScript、CSS文件可以合並最好合並,人家財幫子都把自己的JavaScript. functions和Prototype.js合並到一個base.js文件里去了。
3. 減少域名查詢:
a. DNS查詢和解析域名也是消耗時間的,所以要減少對外部JavaScript、CSS、圖片等資源的引用,不同域名的使用越少越好。
4. 緩存重用數據:
a. 對重復使用的數據進行緩存。
5. 優化頁面元素載入順序:
a. 首先載入頁面最初顯示的內容和與之相關的JavaScript和CSS,然後載入HTML相關的東西,像什麼不是最初顯示相關的圖片、flash、視頻等很肥的資源就最後載入。
6. 減少inline JavaScript的數量:
a. 瀏覽器parser會假設inline JavaScript會改變頁面結構,所以使用inline JavaScript開銷較大。
b. 不要使用document.write()這種輸出內容的方法,使用現代W3C DOM方法來為現代瀏覽器處理頁面內容。
7. 使用現代CSS和合法的標簽:
a. 使用現代CSS來減少標簽和圖像,例如使用現代CSS+文字完全可以替代一些只有文字的圖片。
b. 使用合法的標簽避免瀏覽器解析HTML時做「error correction」等操作,還可以被HTML Tidy來給HTML減肥。
8. Chunk your content:
a. 不要使用嵌套table,而使用非嵌套table或者div。將基於大塊嵌套的table的layout分解成多個小table,這樣就不需要等到整個頁面(或大table)內容全部載入完才顯示。
9. 指定圖像和table的大小:
a. 如果瀏覽器可以立即決定圖像或table的大小,那麼它就可以馬上顯示頁面而不要重新做一些布局安排的工作。
b. 這不僅加快了頁面的顯示,也預防了頁面完成載入後布局的一些不當的改變。
c. image使用height和width。
HTML頁面載入和解析流程
1. 用戶輸入網址(假設是個html頁面,並且是第一次訪問),瀏覽器向伺服器發出請求,伺服器返回html文件。
2. 瀏覽器開始載入html代碼,發現<head>標簽內有一個<link>標簽引用外部CSS文件。
3. 瀏覽器又發出CSS文件的請求,伺服器返回這個CSS文件。
4. 瀏覽器繼續載入html中<body>部分的代碼,並且CSS文件已經拿到手了,可以開始渲染頁面了。
5. 瀏覽器在代碼中發現一個<img>標簽引用了一張圖片,向伺服器發出請求。此時瀏覽器不會等到圖片下載完,而是繼續渲染後面的代碼。
6. 伺服器返回圖片文件,由於圖片佔用了一定面積,影響了後面段落的排布,因此瀏覽器需要回過頭來重新渲染這部分代碼。
7. 瀏覽器發現了一個包含一行Javascript代碼的<script>標簽,趕快運行它。
8. Javascript腳本執行了這條語句,它命令瀏覽器隱藏掉代碼中的某個<style>(style.display=」none」)。杯具啊,突然就少了這么一個元素,瀏覽器不得不重新渲染這部分代碼。
9. 終於等到了</html>的到來,瀏覽器淚流滿面……
10. 等等,還沒完,用戶點了一下界面中的「換膚」按鈕,Javascript讓瀏覽器換了一下<link>標簽的CSS路徑。
11. 瀏覽器召集了在座的各位<div><span><ul><li>們,「大夥兒收拾收拾行李,咱得重新來過……」,瀏覽器向伺服器請求了新的CSS文件,重新渲染頁面。
⑩ java中幾種解析html的工具
HTML分析是一個比較復雜的工作,Java世界主要有幾款比較方便的分析工具:
1.Jsoup
Jsoup是一個集強大和便利於一體的HTML解析工具。它方便的地方是,可以用於支持用jQuery中css selector的方式選取元素,這對於熟悉js的開發者來說基本沒有學習成本。
String content = "blabla";
Document doc = JSoup.parse(content);
Elements links = doc.select("a[href]");
- InputStream inputStream = null;
- HtmlParser htmlParser = new HtmlParser();
- htmlParser.parse(new ByteArrayInputStream(page.getContentData()),
- contentHandler, metadata, new ParseContext());
Jsoup還支持白名單過濾機制,對於網站防止XSS攻擊也是很好的。
2.HtmlParser
HtmlParser的功能比較完備,也挺靈活,但談不上方便。這個項目很久沒有維護了,最新版本是2.1。HtmlParser的核心元素是Node,對應一個HTML標簽,支持getChildren()等樹狀遍歷方式。HtmlParser另外一個核心元素是NodeFilter,通過實現NodeFilter介面,可以對頁面元素進行篩選。這里有一篇HtmlParser的使用文章:使用 HttpClient 和 HtmlParser 實現簡易爬蟲。
3.Apache tika
tika是專為抽取而生的工具,還支持PDF、Zip甚至是JavaClass。使用tika分析HTML,需要自己定義一個抽取內容的Handler並繼承org.xml.sax.helpers.DefaultHandler,解析方式就是xml標準的方式。crawler4j中就使用了tika作為解析工具。SAX這種流式的解析方式對於分析大文件很有用,我個人倒是認為對於解析html意義不是很大。
4.HtmlCleaner與XPath
HtmlCleaner最大的優點是:支持XPath的方式選取元素。XPath是一門在XML中查找信息的語言,也可以用於抽取HTML元素。XPath與CSS Selector大部分功能都是重合的,但是CSS Selector專門針對HTML,寫法更簡潔,而XPath則是通用的標准,可以精確到屬性值。XPath有一定的學習成本,但是對經常需要編寫爬蟲的人來說,這點投入絕對是值得的。