一日一技:爬蟲如何正確從網頁中提取偽元素?
我們來看一個網頁,大家想想使用 XPath 怎么抓取。
可以看到,在源代碼里面沒有請抓取我!這段文字。難道這個網頁是異步加載?我們現在來看一下網頁的請求:
網頁也沒有發起任何的Ajax 請求。那么,這段文字是從哪里來的?
我們來看一下這個網頁對應的 HTML:
整個 HTML 里面,甚至連 JavaScript 都沒有。那么這段文字是哪里來的呢?
有點經驗的同學,可能會想到看一下這個example.css文件,其內容如下:
沒錯,文字確實在這里面。其中::after,我們稱之為偽元素(Pseudo-element)[1]。
對于偽元素里面的文字,應該如何提取呢?當然,你可以使用正則表達式來提取。不過我們今天不準備講這個。
XPath 沒有辦法提取偽元素,因為 XPath 只能提取 Dom 樹中的內容,但是偽元素是不屬于 Dom 樹的,因此無法提取。要提取偽元素,需要使用 CSS 選擇器。
由于網頁的 HTML 與 CSS 是分開的。如果我們使用 requests 或者 Scrapy,只能單獨拿到 HTML 和 CSS。單獨拿到 HTML 沒有任何作用,因為數據根本不在里面。單獨拿到 CSS,雖然有數據,但如果不用正則表達式的話,里面的數據拿不出來。所以 BeautifulSoup4的 CSS 選擇器也沒有什么作用。所以我們需要把 CSS 和 HTML 放到一起來渲染,然后再使用JavaScript 的 CSS 選擇器找到需要提取的內容。
首先我們來看一下,為了提取這個偽元素的值,我們需要下面這段Js 代碼:
window.getComputedStyle(document.querySelector('.fake_element'),':after').getPropertyValue('content')
其中,ducument.querySelector的第一個參數.fake_element就表示值為fake_element的 class 屬性。第二個參數就是偽元素:after。運行效果如下圖所示:
為了能夠運行這段 JavaScript,我們需要使用模擬瀏覽器,無論是 Selenium 還是 Puppeteer 都可以。這里以 Selenium 為例。
在 Selenium 要執行 Js,需要使用driver.execute_script()方法,代碼如下:
提取出來的內容最外層會包上一對雙引號,拿到以后移除外側的雙引號,就是我們在網頁上看到的內容了。
參考資料
[1]偽元素(Pseudo-element): https://developer.mozilla.org/zh-CN/docs/Web/CSS/Pseudo-elements
本文轉載自微信公眾號「未聞Code」,可以通過以下二維碼關注。轉載本文請聯系未聞Code公眾號。