Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
tmlParse 是一款基于windwos平臺的HTML文檔解析工具,可快速構(gòu)建DOM樹,從而輕松實(shí)現(xiàn)網(wǎng)頁元素的爬取工作。DOM樹就是一個HTML文檔的節(jié)點(diǎn)樹,每個節(jié)點(diǎn)由:標(biāo)簽(Tag)、屬性(Attribute)、文本(Text)三個值來描述。
所謂的HTML文檔解析,指的就是如何構(gòu)建一顆DOM樹,只有成功構(gòu)建出DOM樹,才有可能進(jìn)行后續(xù)的數(shù)據(jù)爬取和分析工作。顯然,構(gòu)建DOM樹是比較復(fù)雜的過程,因?yàn)椴皇敲恳粋€HTML文檔都會嚴(yán)格按照規(guī)范來書寫,因此解析過程需要具有一定容錯能力。此外,解析效率也是一個需要考慮的因素,也就是說最好通過一次文檔掃描即可建立起DOM樹,而不是反復(fù)掃描。
下面是HtmlParse介紹。
1、綠色純天然,無任何第三方依賴庫,文件大小不到150K; 2、解析速度快,具有一定的HTML語法容錯能力,可快速將HMTL文檔解析為DOM樹; 3、基于命令行參數(shù),可通過不同參數(shù)獲取指定TAG的屬性值和文本內(nèi)容,從而實(shí)現(xiàn)網(wǎng)頁爬取功能; 4、可將爬取數(shù)據(jù)輸出為json格式,方便第三方程序進(jìn)一步分析和使用; 5、可爬取script腳本到指定的js文件中;
下載地址:http://softlee.cn/HtmlParse.zip
HtmlParse HtmlPathFile -tag TagName [-attr] [Attribute] [-o] [JsonPathFile]
解析指定的HTML文檔,并將文檔中指定的標(biāo)簽及屬性輸出到指定文件中。
HtmlPathFile:必選參數(shù),要解析的HTML文檔路徑名,如果文件路徑中有空格,可使用雙引號將文件路徑包含;
-tag:必選參數(shù),用于指定要抓取的HTML標(biāo)簽名稱; -attr:可選參數(shù),用于指定標(biāo)簽的屬性值,如果不指定,則返回該標(biāo)簽的所有屬性值; -o:可選參數(shù),用于指定抓取內(nèi)容輸出的文件,可將抓取的內(nèi)容保存為json格式的文件。 如果該參數(shù)不指定,則進(jìn)行控制臺輸出。 如果抓取的是script、style則會保存為js格式文件。
如果要抓取doctype,可使用-tag doctype,將整個doctype內(nèi)容獲取。此時將會忽略-attr指定的任何屬性值。
1、爬取網(wǎng)頁中所有超鏈接
HtmlParse c:/sina.html -tag a -attr href -o c:/sina.json
解析C盤下的sina.html文檔,并提取該文檔中的所有超鏈接到sina.json文件中。其中**-tag a -attr href,用于指定獲取超鏈接標(biāo)簽a的href**屬性。
2、爬取網(wǎng)頁中所有圖片鏈接
HtmlParse c:/sina.html -tag img -attr src -o c:/sina.json
解析C盤下的sina.html文檔,并提取該文檔中的所有圖片鏈接到sina.json文件中。
3、爬取網(wǎng)頁中所有腳本
HtmlParse c:/sina.html -tag script -o c:/sina.js
解析C盤下的sina.html文檔,并提取該文檔中的所有腳本函數(shù)到sina.js文件中。
如果通過-o參數(shù)指定輸出文件,則會生成一個json格式的文檔。 TagName為爬取的標(biāo)簽名稱,比如超鏈接的a,其值是一個json數(shù)組,數(shù)組中的每個內(nèi)容為Json對象,每個Json對象,有屬性和文本構(gòu)成。如果-attr 指定了要爬取的屬性,則AttrName為指定的屬性名稱,比如href或src。text為該標(biāo)簽的文本內(nèi)容,有些標(biāo)簽不存在文本內(nèi)容,比如img、meta等,則該值為空。json格式如下:
{
"TagName":
{
{"AttrName":"AttrValue1", "text":"text1"}
{"AttrName":"AttrValue1", "text":"text2"}
}
}
下面是一個sina網(wǎng)頁的所有超鏈接json
{
"a": [{
"href": "javascript:;",
"text": "設(shè)為首頁"
}, {
"href": "javascript:;",
"text": "我的菜單"
}, {
"href": "https://sina.cn/",
"text": "手機(jī)新浪網(wǎng)"
}, {
"href": "",
"text": "移動客戶端"
}, {
"href": "https://c.weibo.cn/client/guide/download",
"text": "新浪微博"
}, {
"href": "https://so.sina.cn/palmnews/web-sinanews-app-download.d.html",
"text": "新浪新聞"
}, {
"href": "https://finance.sina.com.cn/mobile/comfinanceweb.shtml",
"text": "新浪財(cái)經(jīng)"
}, {
"href": "https://m.sina.com.cn/m/sinasports.shtml",
"text": "新浪體育"
}, {
"href": "https://tousu.sina.com.cn/about_app/index?frompage=heimaopc",
"text": "黑貓投訴"
}, {
"href": "http://blog.sina.com.cn/lm/z/app/",
"text": "新浪博客"
}, {
"href": "https://games.sina.com.cn/o/kb/12392.shtml",
"text": "新浪游戲"
}, {
"href": "https://zhongce.sina.com.cn/about/app",
"text": "新浪眾測"
}, {
"href": "https://mail.sina.com.cn/client/mobile/index.php?suda-key=mail_app&suda-value=login",
"text": "新浪郵箱客戶端"
}, {
"href": "javascript:;",
"text": "關(guān)閉置頂"
}, {
來源:https://www.cnblogs.com/softlee/p/16374079.html
在的學(xué)習(xí)路徑跟以前是不一樣的,以前是沒什么資料,很多東西要看必須得去正面剛。所以我計(jì)劃做一個專欄,聊一下Webkit相關(guān)的實(shí)現(xiàn)。但是放心,難度我會降低到最低,文章也會同步到掘金,賬號應(yīng)該是同步的,這里還在審批,有興趣可以雙擊支持一下。
·第一章:序列化與反序列化。官方的解釋就不念了,直接用前端的例子來說明一下。如果有一個介紹對象,如何把它存儲到local story里面?只要能夠?qū)懗鲞@種代碼,并且認(rèn)為這種方式是正常的,沒問題,這就是序列化的操作。同樣的,把它轉(zhuǎn)換成object的對象,這個操作就叫反序列化。
這里為什么要提這個內(nèi)容?因?yàn)楂@取到的協(xié)議通過HTTP獲取到的內(nèi)容就是一個字符串,通過字符串將它轉(zhuǎn)換成動物的過程就是parseHtml,就是這個解析html,就是parseHtml。這里是把它改成了中文,它的左邊是字母串,右邊是DOM,內(nèi)存中的結(jié)構(gòu)。
順便提一嘴,解析樣式表是什么?左邊就是一個字母串兒樣式,比如link或者是style都沒問題,右邊就是CSSOM。
·最后給個思考題,前端如何去存儲一個很惡心的對象?就是這種包含了繼承、包含了封裝的存儲關(guān)系。如果想不到也沒關(guān)系,給個提示,比如有一個element,正常情況下直接in sense of element就可以了,它就是一個元素。
但是為什么還有一個nototype?這個東西有興趣可以考慮一下。當(dāng)然nototype不一定是解決這個問題的,但是有一點(diǎn)點(diǎn)小關(guān)聯(lián)。
于parseHTML函數(shù)代碼實(shí)在過于龐大,我這里就不一次性貼出源代碼了,大家可以前往(https://github.com/vuejs/vue/blob/dev/src/compiler/parser/html-parser.js)查看源代碼。
我們來總結(jié)一下該函數(shù)的主要功能:
1、匹配標(biāo)簽的 "<" 字符
匹配的標(biāo)簽名稱不能是:script、style、textarea
有如下情況:
1、注釋標(biāo)簽 /^<!\--/
2、條件注釋 /^<!\[/
3、html文檔頭部 /^<!DOCTYPE [^>]+>/i
4、標(biāo)簽結(jié)束 /^<\/ 開頭
5、標(biāo)簽開始 /^</ 開頭
然后開始匹配標(biāo)簽的屬性包括w3的標(biāo)準(zhǔn)屬性(id、class)或者自定義的任何屬性,以及vue的指令(v-、:、@)等,直到匹配到 "/>" 標(biāo)簽的結(jié)尾。然后把已匹配的從字符串中刪除,一直 while 循環(huán)匹配。
解析開始標(biāo)簽函數(shù)代碼:
function parseStartTag () {
// 標(biāo)簽的開始 如<div
const start = html.match(startTagOpen)
if (start) {
const match = {
tagName: start[1], // 標(biāo)簽名稱
attrs: [], // 標(biāo)簽屬性
start: index // 開始位置
}
// 減去已匹配的長度
advance(start[0].length)
let end, attr
while (!(end = html.match(startTagClose)) && (attr = html.match(dynamicArgAttribute) || html.match(attribute))) {
attr.start = index
v
advance(attr[0].length)
attr.end = index
match.attrs.push(attr) // 把匹配到的屬性添加到attrs數(shù)組
}
if (end) { // 標(biāo)簽的結(jié)束符 ">"
match.unarySlash = end[1]
advance(end[0].length) // 減去已匹配的長度
match.end = index // 結(jié)束位置
return match
}
}
}
處理過后結(jié)構(gòu)如下:
接下來就是處理組合屬性,調(diào)用 “handleStartTag” 函數(shù)
function handleStartTag (match) {
const tagName = match.tagName // 標(biāo)簽名稱
const unarySlash = match.unarySlash // 一元標(biāo)簽
if (expectHTML) {
if (lastTag === 'p' && isNonPhrasingTag(tagName)) {
// 解析標(biāo)簽結(jié)束
parseEndTag(lastTag)
}
if (canBeLeftOpenTag(tagName) && lastTag === tagName) {
parseEndTag(tagName)
}
}
// 是否為一元標(biāo)簽
const unary = isUnaryTag(tagName) || !!unarySlash
const l = match.attrs.length
// 標(biāo)簽屬性集合
const attrs = new Array(l)
for (let i = 0; i < l; i++) {
const args = match.attrs[i]
const value = args[3] || args[4] || args[5] || ''
const shouldDecodeNewlines = tagName === 'a' && args[1] === 'href' ? options.shouldDecodeNewlinesForHref : options.shouldDecodeNewlines
attrs[i] = {
name: args[1], // 屬性名稱
value: decodeAttr(value, shouldDecodeNewlines) // 屬性值
}
if (process.env.NODE_ENV !== 'production' && options.outputSourceRange) {
// 開始位置
attrs[i].start = args.start + args[0].match(/^\s*/).length
// 結(jié)束位置
attrs[i].end = args.end
}
}
if (!unary) {
stack.push({ tag: tagName, lowerCasedTag: tagName.toLowerCase(), attrs: attrs, start: match.start, end: match.end })
lastTag = tagName
}
// 調(diào)用start函數(shù)
if (options.start) {
options.start(tagName, attrs, unary, match.start, match.end)
}
}
我們簡單說一下最后調(diào)用的start函數(shù)的作用:
1、判斷是否為svg標(biāo)簽,并處理svg在ie下的兼容性問題
2、遍歷標(biāo)簽屬性,驗(yàn)證其名稱是否有效
3、標(biāo)簽名是否為 style 或者 script ,如果在服務(wù)端會提示warn警告
4、檢查屬性是否存在 v-for、v-if、v-once指令
5、如果是更元素就驗(yàn)證其合法性,不能是 slot 和 template 標(biāo)簽,不能存在 v-for指令
以上就是界面html模板的開始標(biāo)簽的分析,接下來我們來分析如何匹配結(jié)束標(biāo)簽。
請看:Vue源碼全面解析三十 parseHTML函數(shù)(解析html(二)結(jié)束標(biāo)簽)
如有錯誤,歡迎指正,謝謝。
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。