什么是XPath
? XPath全稱XML路徑語言(XML Path Language)菩混,它是一種用來確定XML文檔中某部分位置的計算機(jī)語言田藐。XPath基于XML的樹狀結(jié)構(gòu)召嘶,提供在數(shù)據(jù)結(jié)構(gòu)樹中找尋節(jié)點的能力布疼。舉例來說:
? 我們有網(wǎng)頁A,他的頁面代碼為:
它對應(yīng)的domtree為
每個網(wǎng)頁的頁面結(jié)構(gòu)都可以解析為一顆domtree,每個頁面元素都是這棵樹的一個節(jié)點捆昏,那如何唯一的表示每一個節(jié)點呢辜贵?很自然的由于每個節(jié)點到根節(jié)點的路徑都是不同的,所以可以用節(jié)點到根路徑的路徑來表示窑睁,比如meta元素可以用/html/head/meta來表示挺峡,這樣的話有個問題,比如最右和皮皮搞笑這個兩個元素都可以表示成/html/head/h1,這樣豈不是亂了套,所以對于這樣的情況可以用/html/head/h1[0],/html/head/h1[1]來表示担钮,至于誰是h1[0]誰是h1[1]取決于具體實現(xiàn)橱赠。這樣用路徑表達(dá)式唯一標(biāo)識一個頁面元素的方法就叫做XPath。
總結(jié):XPath是我們用來唯一標(biāo)識頁面元素的一種方法和工具箫津。
為什么要做XPath線索追蹤
? 為什么要做XPath線索追蹤?這其實可以分解為兩個問題:1狭姨、為什么要做線索追蹤 2宰啦、為什么要選擇XPath做線索追蹤。
? 首先是問題一饼拍,為什么要做線索追蹤赡模?這個答案很簡單,因為我們要做oCPX,需要根據(jù)轉(zhuǎn)化情況(像提交的表單师抄、咨詢工具等)漓柑,系統(tǒng)自動優(yōu)化轉(zhuǎn)化效果。它的第一步就是轉(zhuǎn)化數(shù)據(jù)收集叨吮,目前我們只對于App下載類有轉(zhuǎn)化數(shù)據(jù)的收集欺缘,而對于網(wǎng)頁線索類特別是對第三方網(wǎng)頁的線索收集是一片空白,如果無法收集到這些信息,那么對于這些類型廣告的oCPX將無從做起挤安,所以我們有必要對于這些類型的廣告做線索追蹤谚殊。這是做XPath線索追蹤的必要性。
其次是問題二蛤铜,為什么選擇選擇XPath做線索追蹤嫩絮。對于線索追蹤目前主要有:js布碼、api回傳围肥、XPath剿干,這三種做法。其中js布碼和api回傳都需要平臺方面和廣告主側(cè)投入較大的技術(shù)支持,而XPath只需要平臺側(cè)提供對應(yīng)功能穆刻,投放時廣告主可以自主選擇線索綁定,不需要投入技術(shù)支持,較為方便和易于推廣置尔。另外因為業(yè)內(nèi)有已經(jīng)有應(yīng)用的比較好的先例,可以省去一些調(diào)研選型的時間氢伟,還有完整的產(chǎn)品形態(tài)可以參考榜轿,對于最終可以達(dá)到的效果也有個預(yù)期。這是做XPath線索追蹤的充分性朵锣。
總結(jié):通過問題一,二的討論谬盐,我們知道我們有充分且必要的理由做XPath線索追蹤這件事。
XPath線索追蹤技術(shù)實現(xiàn)
-
服務(wù)端domtree和截圖技術(shù)選型
通過調(diào)研可供我們選擇的有三種方案:1诚些、基于PhantomJS的方案飞傀,2、基于ChromeDP的方案诬烹,3砸烦、基于Puppeteer的方案。
經(jīng)過嘗試調(diào)研后總結(jié)他們的優(yōu)缺點對比如下:優(yōu)點 缺點 phantomjs 有過使用經(jīng)驗绞吁,學(xué)習(xí)成本低幢痘,二進(jìn)制文件部署簡單 已經(jīng)停止維護(hù),web引擎實現(xiàn)不一定和現(xiàn)在主流一致 chromedp go語言實現(xiàn),底層使用Chrome(我們服務(wù)端主要語言是go) 性能不穩(wěn)定掀泳,社區(qū)不活躍雪隧,資料不多 puppeteer Chrome官方推薦,社區(qū)活躍 需要在服務(wù)器搭建對應(yīng)環(huán)境员舵,同時有一些學(xué)習(xí)成本 經(jīng)過實際的嘗試我們最終選擇使用Puppeter作為服務(wù)端domtree解析和服務(wù)端截圖的工具脑沿。
頁面domtree json和頁面截圖匹配
domtree json是一串描述元素位置信息和其XPath表達(dá)式的json,它通過服務(wù)器模擬訪問頁面,然后遍歷頁面的domtree生成,例如:
{
"height": 200,
"left": 400,
"top": 500,
"width": 300,
"xpath": "/html/body/div[1]"
}
的含義是: xpath表達(dá)式為/html/body/div[1]的元素,它的左上角距離視窗左上角右偏400像素, 下偏500像素马僻,同時該元素高200像素庄拇,寬300像素。根據(jù)這些信息我們可以在截圖的對應(yīng)區(qū)域進(jìn)行框選韭邓,如果在截圖上框選到的這塊區(qū)域剛好是路徑表達(dá)式/html/body/div[1]表示的區(qū)域措近,那么這個元素即匹配成功。
下面主要介紹兩種較難匹配的元素的解決: 一女淑、固定浮動元素 二瞭郑、重疊元素
固定浮動元素的匹配
固定浮動元素指的是網(wǎng)頁上一些不隨著頁面滑動而移動的元素,它們與頁面其他元素的相對位置是不固定的鸭你,比如一些懸浮球屈张,底部欄之類的元素,這類元素的位置完全取決于你的設(shè)備型號袱巨,一個懸浮球在小屏幕設(shè)備上可能位于屏幕中部阁谆,換成大屏幕后它可能就位于屏幕靠下的位置了,而且在服務(wù)端截圖的時候愉老,對于一些需要滑動的頁面截得是展開的長圖场绿。所以此時如果模擬移動設(shè)備去訪問頁面解析domtree的話,浮動元素的domtree json必然與截圖無法匹配嫉入。對于這個問題摸索出的解決方案為: 放棄chrome模擬移動設(shè)備的方法焰盗,手動設(shè)置ua,然后截圖之后,在解析domtree之前咒林,獲取頁面高度姨谷,然后設(shè)置模擬訪問的頁面視圖打開高度為頁面高度,對應(yīng)不同動態(tài)的設(shè)置視圖高度映九,由于這樣的視圖高度和頁面高度一致梦湘,所以在這樣的視圖下打開的頁面不存在滑動的情況,所以完美解決浮動元素的問題件甥。-
重疊元素的匹配
domtree json只表示了元素之間二維的位置關(guān)系捌议,但是對于三維上的重疊等情況沒有描述,所以當(dāng)一個位置出現(xiàn)兩個元素引有,到底應(yīng)該框選誰變成了問題瓣颅。這個問題解決最容易想到的就是給domtree json加上三維信息的描述,并且元素確實有z-index這個屬性表示層級關(guān)系,但是實際中發(fā)現(xiàn)z-index屬性有許多的坑譬正,不是很靠譜宫补,比如父標(biāo)簽 position屬性為relative檬姥,標(biāo)簽無position屬性,標(biāo)簽含有浮動(float)屬性等都會導(dǎo)致z-index失效(根本原因是css屬性間作用不正交)粉怕,同時發(fā)現(xiàn)巨量引擎也并沒有使用z-index屬性來進(jìn)行匹配健民。后來我們觀察了一些頁面,發(fā)現(xiàn)其實大部分頁面都存在著小元素在在大元素上層的規(guī)律贫贝,于是我們決定按照元素面積來做層級的判斷,即面積小的元素默認(rèn)在面積大的上層秉犹,這樣還意外的解決了一些有蒙層的彈窗元素導(dǎo)致整個頁面被蒙層遮蓋無法選擇的問題,并且在測試一些頁面后在使用上已經(jīng)達(dá)到類似工具的同等的水平稚晚。同時我們好奇是否同行也是使用同樣的手法來解決這個問題崇堵,于是我們制作了一個特殊的頁面,一個600400的元素在上層客燕,兩個600200的元素在下層鸳劳,上下層邊緣輪廓完全重合,這樣按照面積小的元素默認(rèn)在上的實現(xiàn)方式會導(dǎo)致實際在上層的大元素?zé)o法選中也搓,我們拿著這個頁面去類型工具嘗試棍辕,發(fā)現(xiàn)果然上層的大元素?zé)o法選中,這說明了大家用的手法都是一致的还绘!
至此楚昭,我們的XPath工具已經(jīng)達(dá)到業(yè)內(nèi)類似工具的使用水平,然后在此基礎(chǔ)上對一些業(yè)內(nèi)工具支持不太好的地方進(jìn)行了優(yōu)化拍顷,主要是:對重定向頁面的支持抚太,技術(shù)選項使用puppeteer自動解決
對于懶加載頁面的優(yōu)化,截圖解析之前服務(wù)器模擬對頁面進(jìn)行滑動昔案,使得頁面完全加載
最終元素選擇效果:
END: 更完整詳細(xì)技術(shù)及產(chǎn)品實現(xiàn)細(xì)節(jié)在:內(nèi)部分享PPT
title: XPath線索追蹤技術(shù)
date: 2020-03-05 22:33:23
tags: 線索追蹤
categories: 計算廣告
什么是XPath
? XPath全稱XML路徑語言(XML Path Language)尿贫,它是一種用來確定XML文檔中某部分位置的計算機(jī)語言。XPath基于XML的樹狀結(jié)構(gòu)踏揣,提供在數(shù)據(jù)結(jié)構(gòu)樹中找尋節(jié)點的能力庆亡。舉例來說:
? 我們有網(wǎng)頁A,他的頁面代碼為:
它對應(yīng)的domtree為
每個網(wǎng)頁的頁面結(jié)構(gòu)都可以解析為一顆domtree,每個頁面元素都是這棵樹的一個節(jié)點,那如何唯一的表示每一個節(jié)點呢捞稿?很自然的由于每個節(jié)點到根節(jié)點的路徑都是不同的又谋,所以可以用節(jié)點到根路徑的路徑來表示,比如meta元素可以用/html/head/meta來表示娱局,這樣的話有個問題彰亥,比如最右和皮皮搞笑這個兩個元素都可以表示成/html/head/h1,這樣豈不是亂了套,所以對于這樣的情況可以用/html/head/h1[0],/html/head/h1[1]來表示,至于誰是h1[0]誰是h1[1]取決于具體實現(xiàn)衰齐。這樣用路徑表達(dá)式唯一標(biāo)識一個頁面元素的方法就叫做XPath任斋。
總結(jié):XPath是我們用來唯一標(biāo)識頁面元素的一種方法和工具。
為什么要做XPath線索追蹤
? 為什么要做XPath線索追蹤?這其實可以分解為兩個問題:1耻涛、為什么要做線索追蹤 2废酷、為什么要選擇XPath做線索追蹤瘟檩。
? 首先是問題一,為什么要做線索追蹤澈蟆?這個答案很簡單墨辛,因為我們要做oCPX,需要根據(jù)轉(zhuǎn)化情況(像提交的表單、咨詢工具等)丰介,系統(tǒng)自動優(yōu)化轉(zhuǎn)化效果背蟆。它的第一步就是轉(zhuǎn)化數(shù)據(jù)收集鉴分,目前我們只對于App下載類有轉(zhuǎn)化數(shù)據(jù)的收集哮幢,而對于網(wǎng)頁線索類特別是對第三方網(wǎng)頁的線索收集是一片空白,如果無法收集到這些信息,那么對于這些類型廣告的oCPX將無從做起志珍,所以我們有必要對于這些類型的廣告做線索追蹤橙垢。這是做XPath線索追蹤的必要性。
其次是問題二伦糯,為什么選擇選擇XPath做線索追蹤柜某。對于線索追蹤目前主要有:js布碼、api回傳敛纲、XPath喂击,這三種做法。其中js布碼和api回傳都需要平臺方面和廣告主側(cè)投入較大的技術(shù)支持,而XPath只需要平臺側(cè)提供對應(yīng)功能淤翔,投放時廣告主可以自主選擇線索綁定,不需要投入技術(shù)支持,較為方便和易于推廣翰绊。另外因為業(yè)內(nèi)有已經(jīng)有應(yīng)用的比較好的先例,可以省去一些調(diào)研選型的時間旁壮,還有完整的產(chǎn)品形態(tài)可以參考监嗜,對于最終可以達(dá)到的效果也有個預(yù)期。這是做XPath線索追蹤的充分性抡谐。
總結(jié):通過問題一,二的討論裁奇,我們知道我們有充分且必要的理由做XPath線索追蹤這件事。
XPath線索追蹤技術(shù)實現(xiàn)
-
服務(wù)端domtree和截圖技術(shù)選型
通過調(diào)研可供我們選擇的有三種方案:1麦撵、基于PhantomJS的方案刽肠,2、基于ChromeDP的方案免胃,3五垮、基于Puppeteer的方案。
經(jīng)過嘗試調(diào)研后總結(jié)他們的優(yōu)缺點對比如下:優(yōu)點 缺點 phantomjs 有過使用經(jīng)驗杜秸,學(xué)習(xí)成本低放仗,二進(jìn)制文件部署簡單 已經(jīng)停止維護(hù),web引擎實現(xiàn)不一定和現(xiàn)在主流一致 chromedp go語言實現(xiàn),底層使用Chrome(我們服務(wù)端主要語言是go) 性能不穩(wěn)定撬碟,社區(qū)不活躍诞挨,資料不多 puppeteer Chrome官方推薦莉撇,社區(qū)活躍 需要在服務(wù)器搭建對應(yīng)環(huán)境,同時有一些學(xué)習(xí)成本 經(jīng)過實際的嘗試我們最終選擇使用Puppeter作為服務(wù)端domtree解析和服務(wù)端截圖的工具惶傻。
頁面domtree json和頁面截圖匹配
domtree json是一串描述元素位置信息和其XPath表達(dá)式的json,它通過服務(wù)器模擬訪問頁面,然后遍歷頁面的domtree生成,例如:
{
"height": 200,
"left": 400,
"top": 500,
"width": 300,
"xpath": "/html/body/div[1]"
}
的含義是: xpath表達(dá)式為/html/body/div[1]的元素棍郎,它的左上角距離視窗左上角右偏400像素, 下偏500像素,同時該元素高200像素银室,寬300像素涂佃。根據(jù)這些信息我們可以在截圖的對應(yīng)區(qū)域進(jìn)行框選,如果在截圖上框選到的這塊區(qū)域剛好是路徑表達(dá)式/html/body/div[1]表示的區(qū)域蜈敢,那么這個元素即匹配成功辜荠。
下面主要介紹兩種較難匹配的元素的解決: 一、固定浮動元素 二抓狭、重疊元素
固定浮動元素的匹配
固定浮動元素指的是網(wǎng)頁上一些不隨著頁面滑動而移動的元素伯病,它們與頁面其他元素的相對位置是不固定的,比如一些懸浮球否过,底部欄之類的元素午笛,這類元素的位置完全取決于你的設(shè)備型號,一個懸浮球在小屏幕設(shè)備上可能位于屏幕中部苗桂,換成大屏幕后它可能就位于屏幕靠下的位置了药磺,而且在服務(wù)端截圖的時候,對于一些需要滑動的頁面截得是展開的長圖煤伟。所以此時如果模擬移動設(shè)備去訪問頁面解析domtree的話癌佩,浮動元素的domtree json必然與截圖無法匹配。對于這個問題摸索出的解決方案為: 放棄chrome模擬移動設(shè)備的方法持偏,手動設(shè)置ua,然后截圖之后驼卖,在解析domtree之前,獲取頁面高度鸿秆,然后設(shè)置模擬訪問的頁面視圖打開高度為頁面高度酌畜,對應(yīng)不同動態(tài)的設(shè)置視圖高度,由于這樣的視圖高度和頁面高度一致卿叽,所以在這樣的視圖下打開的頁面不存在滑動的情況桥胞,所以完美解決浮動元素的問題。-
重疊元素的匹配
domtree json只表示了元素之間二維的位置關(guān)系考婴,但是對于三維上的重疊等情況沒有描述贩虾,所以當(dāng)一個位置出現(xiàn)兩個元素,到底應(yīng)該框選誰變成了問題沥阱。這個問題解決最容易想到的就是給domtree json加上三維信息的描述缎罢,并且元素確實有z-index這個屬性表示層級關(guān)系,但是實際中發(fā)現(xiàn)z-index屬性有許多的坑,不是很靠譜,比如父標(biāo)簽 position屬性為relative策精,標(biāo)簽無position屬性舰始,標(biāo)簽含有浮動(float)屬性等都會導(dǎo)致z-index失效(根本原因是css屬性間作用不正交),同時發(fā)現(xiàn)巨量引擎也并沒有使用z-index屬性來進(jìn)行匹配咽袜。后來我們觀察了一些頁面丸卷,發(fā)現(xiàn)其實大部分頁面都存在著小元素在在大元素上層的規(guī)律,于是我們決定按照元素面積來做層級的判斷,即面積小的元素默認(rèn)在面積大的上層询刹,這樣還意外的解決了一些有蒙層的彈窗元素導(dǎo)致整個頁面被蒙層遮蓋無法選擇的問題谜嫉,并且在測試一些頁面后在使用上已經(jīng)達(dá)到類似工具的同等的水平。同時我們好奇是否同行也是使用同樣的手法來解決這個問題凹联,于是我們制作了一個特殊的頁面沐兰,一個600400的元素在上層,兩個600200的元素在下層匕垫,上下層邊緣輪廓完全重合僧鲁,這樣按照面積小的元素默認(rèn)在上的實現(xiàn)方式會導(dǎo)致實際在上層的大元素?zé)o法選中虐呻,我們拿著這個頁面去類型工具嘗試象泵,發(fā)現(xiàn)果然上層的大元素?zé)o法選中,這說明了大家用的手法都是一致的斟叼!
至此偶惠,我們的XPath工具已經(jīng)達(dá)到業(yè)內(nèi)類似工具的使用水平,然后在此基礎(chǔ)上對一些業(yè)內(nèi)工具支持不太好的地方進(jìn)行了優(yōu)化朗涩,主要是:對重定向頁面的支持忽孽,技術(shù)選項使用puppeteer自動解決
對于懶加載頁面的優(yōu)化,截圖解析之前服務(wù)器模擬對頁面進(jìn)行滑動谢床,使得頁面完全加載
最終元素選擇效果:
END: 更完整詳細(xì)技術(shù)及產(chǎn)品實現(xiàn)細(xì)節(jié)在:內(nèi)部分享PPT
更多內(nèi)容:我的博客