還有 Selenium 抓不到的內(nèi)容?
今天我們不討論字體反爬蟲和 CSS 反爬蟲這兩種情況。我們來看一段非常簡單的網(wǎng)頁。這個網(wǎng)頁只有一個HTML 文件,不加載特殊字體,不加載 CSS 文件。

這個網(wǎng)頁的奇怪之處在哪里呢?我們試一試使用 XPath Helper 來提取網(wǎng)頁上面的紅色文字,發(fā)現(xiàn)XPath 竟然無法找到這段文字,如下圖所示:

然后我們使用 Selenium 來試一試:

Selenium果然無法獲取 紅字到內(nèi)容。我們再打印一下網(wǎng)頁的源代碼:

這一次,Selenium 獲取到的源代碼,竟然跟 Chrome 開發(fā)者工具里面顯示的源代碼不一樣?
這個問題的關(guān)鍵,就在開發(fā)者工具里面的這樣一段文字:

因?yàn)檫@個節(jié)點(diǎn)是一個shadow DOM[1]。shadow DOM 的行為跟 iframe很像,都是把一段HTML 信息嵌入到另一個 HTML 中。但不同的是,iframe被嵌入的地址需要額外再搭建一個 HTTP服務(wù),而 shadow DOM 可以只嵌入一段 HTML 代碼,所以它比 iframe 更節(jié)省資源。
在上面的截圖中,通過下面這三行代碼,我們把一個新的<p>標(biāo)簽嵌入到了原來的 HTML 中:
var content = document.querySelector('.content');
var root = content.attachShadow({mode: 'open'});
root.innerHTML = '<p class="real_content" style="color: red">你抓不到這段文字的!</p>'
而這個被嵌入的影子標(biāo)簽,就像 iframe 一樣,是無法直接使用 Selenium 提取的。如果強(qiáng)行提取,那么,我們需要使用 JavaScript 獲取 shadow DOM,然后再進(jìn)行提取。我們來看一段可以正常工作的代碼:
shadow = driver.execute_script('return document.querySelector(".content").shadowRoot')
content = shadow.find_element_by_class_name('real_content')
print(content.text)
運(yùn)行效果如下圖所示:

這段代碼,首先通過 JavaScript 找到shadow-root的父節(jié)點(diǎn)元素,然后返回這個元素的.shadowRoot屬性。在 Python 里面拿到這個屬性以后,使用.find_element_by_class_name()方法獲取里面的內(nèi)容。
要特別注意的是,拿到shadow-root節(jié)點(diǎn)以后,只能通過 CSS 選擇器進(jìn)一步篩選里面的內(nèi)容,不能用 XPath,否則會導(dǎo)致報錯。
參考資料
shadow DOM: https://developer.mozilla.org/zh-CN/docs/Web/Web_Components/Using_shadow_DOM
推薦閱讀:
入門: 最全的零基礎(chǔ)學(xué)Python的問題 | 零基礎(chǔ)學(xué)了8個月的Python | 實(shí)戰(zhàn)項(xiàng)目 |學(xué)Python就是這條捷徑
干貨:爬取豆瓣短評,電影《后來的我們》 | 38年NBA最佳球員分析 | 從萬眾期待到口碑撲街!唐探3令人失望 | 笑看新倚天屠龍記 | 燈謎答題王 |用Python做個海量小姐姐素描圖 |
趣味:彈球游戲 | 九宮格 | 漂亮的花 | 兩百行Python《天天酷跑》游戲!
AI: 會做詩的機(jī)器人 | 給圖片上色 | 預(yù)測收入 | 碟中諜這么火,我用機(jī)器學(xué)習(xí)做個迷你推薦系統(tǒng)電影
年度爆款文案
點(diǎn)閱讀原文,領(lǐng)廖雪峰視頻資料!


