原文連接 blog.rosuh.me/2019/02/web…javascript
查豆瓣 使用的是 WebView 加載頁面,在豆瓣的移動頁面中存在兩到三個的廣告輪播圖,比較影響閱讀體驗。因此開始着手看看怎麼屏蔽掉廣告。html
在 WebView 中有如下三個方法能夠考慮:java
fun onPageFinished(view: WebView, url: String)
fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse?
fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean
複製代碼
onPageFinished
方法會在頁面加載完畢後回調android
shouldInterceptRequest
方法會通知 host Application
,也就是啓動 WebView 的應用返回WebResourceResponse
。若是本地應用返回null
,則webView
會正常加載資源git
shouldOverrideUrlLoading
會在Url
被加載前被回調。實現此方法,返回true
時WebView
將不會加載該Url
,不然將會正常加載Url
github
WebView.load(url)
方法時纔會回調,而頁面中的資源加載時是不會被回調的
webview.load(url)
POST
請求基於上述三個方法,咱們看看可否作到:web
div
或相似元素根據shouldOverrideUrlLoading()
方法的特性,咱們幾乎沒法用之來屏蔽頁面中加載的廣告。ide
在實踐中,通常在這處理網頁對本地資源的調用,好比最多見的拉起 APP 的操做。ui
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
val url = request.url.toString()
if (url.startsWith("douban:")) {
// 拉起豆瓣 APP
handleAppRequest(view, url)
return true
}
return super.shouldOverrideUrlLoading(view, request)
}
複製代碼
此方法看起來應該是不行了。這一步也應該無法輕易辦到。lua
咱們把目光彙集到了shouldInterceptRequest()
方法,實際上這個方法的功勞最大。咱們很輕易就是實現了廣告攔截。
override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
return if (isAdDomain(request.url.toString())) {
createEmptyResource()
} else super.shouldInterceptRequest(view, request)
}
fun createEmptyResource(): WebResourceResponse {
return WebResourceResponse("text/plain", "utf-8", ByteArrayInputStream("".toByteArray()))
}
fun isAdDomain(url: String): Boolean {
return (!url.contains("douban")) or url.contains("baidu")
}
複製代碼
前面提起的,此方法會在請求數據前回調。因此咱們能夠本身構建WebResourceResponse
對象返回。
豆瓣的移動端對接的是百度的推廣,因此基本上廣告域名都帶有baidu
的關鍵字。因此我這樣就已經足夠了。
更通常的狀況,咱們能夠本身維護規則列表或者,使用一些公開的規則列表。或者本身收集一下常見的大的推廣聯盟的連接就能夠了。
咱們給廣告請求返回了空數據,可是原有的廣告佔位元素依然存在。因此咱們要用到
onPageFinished()
方法,來刪除廣告佔位標籤。
override fun onPageFinished(view: WebView, url: String) {
webView.evaluateJavascript(
"javascript:(" +
" function() {" +
" var len = document.getElementsByClassName('Advertisement').length; " +
" for(var i = 0; i < len; i ++){" +
" document.getElementsByClassName('Advertisement')[i].style.display = 'none'" +
" }" +
" }" +
")()"
) {
print(it)
}
}
複製代碼
這裏利用了WebView.evaluateJavascript()
方法,執行了一段 JavaScript 代碼:
javascript:(
function() {
var len = document.getElementsByClassName('Advertisement').length;
for(var i = 0; i < len; i ++ ){
document.getElementsByClassName('Advertisement')[i].style.display = 'none'
}
}
)()
複製代碼
這裏的代碼須要你根據不一樣的頁面來維護規則。好比豆瓣的移動端廣告都用Advertisement
做爲類名。
因此獲取了個數以後,降之隱藏。
至此,咱們簡單地實現了對豆瓣移動端網頁的攔截。
參考連接: