动态网页抓取——学习笔记
目錄
1 動(dòng)態(tài)抓取技術(shù)簡(jiǎn)介
2 解析真實(shí)地址抓取
3 通過(guò)Selenium模擬瀏覽器抓取
3.1 Selenium的基本介紹
3.2 Selenium實(shí)踐案例
3.3 Selenium獲取文章的所有評(píng)論
3.4 Selenium的高級(jí)操作
3.4.1 控制CSS
3.4.2 限制圖片的加載
3.4.3 控制JavaScript的運(yùn)行
參考資料
1 動(dòng)態(tài)抓取技術(shù)簡(jiǎn)介
- 異步更新技術(shù)——AJAX
AJAX(Asynchronous Javascript And XML,異步JavaScript和XML)的價(jià)值在于通過(guò)在后臺(tái)與服務(wù)器進(jìn)行少量的數(shù)據(jù)交換就可以使網(wǎng)頁(yè)實(shí)現(xiàn)異步更新。這意味著可以在不重新加載整個(gè)網(wǎng)頁(yè)的情況下對(duì)網(wǎng)頁(yè)的某部分進(jìn)行更新。一方面減少了網(wǎng)頁(yè)重復(fù)內(nèi)容的下載,另一方面節(jié)省了流量,因此AJAX得到了廣泛的使用。
爬取使用AJAX加載的動(dòng)態(tài)網(wǎng)頁(yè)里的動(dòng)態(tài)加載的內(nèi)容有兩種動(dòng)態(tài)網(wǎng)頁(yè)抓取的方法:
- 通過(guò)瀏覽器審查元素解析真實(shí)網(wǎng)頁(yè)地址
- 使用Selenium模擬瀏覽器的方法
2 解析真實(shí)地址抓取
以《Python網(wǎng)絡(luò)爬蟲(chóng)從入門(mén)到實(shí)踐(第2版)》作者博客的Hello World文章為例,目標(biāo)是抓取文章下的所有評(píng)論。文章網(wǎng)址為:
http://www.santostang.com/2018/07/04/hello-world/
步驟01 打開(kāi)“檢查”功能。用Chrome瀏覽器打開(kāi)Hello World文章。右擊頁(yè)面的任意位置,在彈出的快彈菜單中單擊“檢查”命令。
步驟02 找到真實(shí)的數(shù)據(jù)地址。單擊頁(yè)面中的Network選項(xiàng),然后刷新網(wǎng)頁(yè)。此時(shí),Network會(huì)顯示瀏覽器從網(wǎng)頁(yè)服務(wù)器中得到的所有文件,一般這個(gè)過(guò)程成為“抓包”。
從文件中快速找到評(píng)論數(shù)據(jù)所在文件的方法:search評(píng)論內(nèi)容可以快速定位具體的評(píng)論所在位置的文件。
步驟03 爬取真實(shí)評(píng)論數(shù)據(jù)地址。既然找到了真實(shí)的地址,接下來(lái)就可以直接用requests請(qǐng)求這個(gè)地址獲取數(shù)據(jù)了。
步驟04 從json數(shù)據(jù)中提取評(píng)論。可以使用json庫(kù)解析數(shù)據(jù),從中提取想要的數(shù)據(jù)。
import requests import jsonlink = "https://api-zero.livere.com/v1/comments/list?callback=jQuery112408626354130815113_1646567623361&limit=10&repSeq=4272904&requestPath=/v1/comments/list&consumerSeq=1020&livereSeq=28583&smartloginSeq=5154&code=&_=1646567623363" headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36'} r = requests.get(link, headers=headers) # 獲取json的string json_string = r.text json_string = json_string[json_string.find('{'):-2] # 從第一個(gè)左大括號(hào)提取,最后的兩個(gè)字符-括號(hào)和分號(hào)不取 json_data = json.loads(json_string) comment_list = json_data['results']['parents'] for eachone in comment_list:message = eachone['content']print(message)接下來(lái)可以用for循環(huán)爬取多頁(yè)評(píng)論數(shù)據(jù),可以通過(guò)對(duì)比不同頁(yè)面真實(shí)地址,發(fā)現(xiàn)其參數(shù)的不同之處,通過(guò)改變折現(xiàn)參數(shù)值實(shí)現(xiàn)換頁(yè)。
import requests import jsondef single_page_comment(link):headers = {'User-Agent': 'https://api-zero.livere.com/v1/comments/list?callback=jQuery112407919796508302595_1646571637355&limit=10&offset=2&repSeq=4272904&requestPath=/v1/comments/list&consumerSeq=1020&livereSeq=28583&smartloginSeq=5154&code=&_=1646571637361'}r = requests.get(link, headers=headers)# 獲取json的stringjson_string = r.textjson_string = json_string[json_string.find('{'):-2] # 從第一個(gè)左大括號(hào)提取,最后的兩個(gè)字符-括號(hào)和分號(hào)不取json_data = json.loads(json_string)comment_list = json_data['results']['parents']for eachone in comment_list:message = eachone['content']print(message)max_comments = 50 # 設(shè)置要爬取的最大評(píng)論數(shù) for page in range(1,max_comments // 10 + 1):link1 = "https://api-zero.livere.com/v1/comments/list?callback=jQuery112407919796508302595_1646571637355&limit=10&offset="link2 = "&repSeq=4272904&requestPath=/v1/comments/list&consumerSeq=1020&livereSeq=28583&smartloginSeq=5154&code=&_=1646571637361"page_str = str(page)link = link1 + page_str + link2print(link)single_page_comment(link)3 通過(guò)Selenium模擬瀏覽器抓取
有些網(wǎng)站非常復(fù)雜,使用“檢查”功能很難找到調(diào)用的網(wǎng)頁(yè)地址。除此之外,有些數(shù)據(jù)的真實(shí)地址的URL也十分復(fù)雜,有些網(wǎng)站為了規(guī)避這些抓取會(huì)對(duì)地址進(jìn)行加密,造成其中的一些變量讓人摸不著頭腦,因此,這里介紹另一種方法,即使用瀏覽器渲染引擎。直接使用瀏覽器在顯示網(wǎng)頁(yè)時(shí)解析HTML、應(yīng)用CSS樣式并執(zhí)行JavaScript的語(yǔ)句。通俗來(lái)講就是使用瀏覽器渲染方法將爬取動(dòng)態(tài)頁(yè)面變成爬取靜態(tài)頁(yè)面。
在這里,使用Python的Selenium庫(kù)模擬瀏覽器完成抓取。Selenium是一個(gè)用于Web應(yīng)用程序測(cè)試的工具。
3.1 Selenium的基本介紹
瀏覽器驅(qū)動(dòng)下載地址:
Chrome: https://sites.google.com/chromium.org/driver/
Edge: Microsoft Edge Driver - Microsoft Edge Developer
Firefox: Releases · mozilla/geckodriver · GitHub
Safari: WebDriver Support in Safari 10 | WebKit
使用Selenium打開(kāi)瀏覽器和一個(gè)網(wǎng)頁(yè),代碼如下:
from selenium import webdriverdriver = webdriver.Firefox() driver.get("http://www.santostang.com/2018/07/04/hello-world/")3.2 Selenium實(shí)踐案例
步驟01 找到評(píng)論的HTML代碼標(biāo)簽。使用Chrome打開(kāi)文章頁(yè)面,右擊頁(yè)面,在彈出的快捷菜單中單擊“檢查”命令。
步驟02 嘗試獲取一條評(píng)論數(shù)據(jù)。在原來(lái)打開(kāi)頁(yè)面的代碼數(shù)據(jù)上使用以下代碼,獲取第一條評(píng)論數(shù)據(jù)。
from selenium import webdriverdriver = webdriver.Firefox() driver.get("http://www.santostang.com/2018/07/04/hello-world/") # 轉(zhuǎn)化iframe driver.switch_to.frame(driver.find_element(by='css selector', value='iframe[title="livere-comment"]')) # 獲取css標(biāo)簽為div.reply-content comment = driver.find_element(by='css selector', value='div.reply-content') content = comment.find_element(by='tag name', value='p')print(content.text)3.3 Selenium獲取文章的所有評(píng)論
如果要獲取所有評(píng)論,需要腳本程序能夠自動(dòng)點(diǎn)擊“+10查看更多”,這樣才能將所有評(píng)論顯示出來(lái)。因此,我們需要找到“+10查看更多”的元素地址,然后讓Selenium模擬單擊并加載評(píng)論。具體代碼如下:
from selenium import webdriver import timedriver = webdriver.Firefox() driver.implicitly_wait(10) # 隱性等待,最長(zhǎng)等10秒 driver.get("http://www.santostang.com/2018/07/04/hello-world/") time.sleep(5) # 下滑到頁(yè)面底部(左下角) driver.execute_script("window.scrollTo(0,document.body.scrollHeight);") print("wait for 3 seconds") time.sleep(3) for i in range(1, 19):# 轉(zhuǎn)換iframe,再找到查看更多,點(diǎn)擊driver.switch_to.frame(driver.find_element(by="css selector", value="iframe[title='livere-comment']"))# load_more = driver.find_element(by="css selector", value="button[data-page=\'%d\']'%i")if i > 11:x_path = './/div[@class="more-wrapper"]/button[' + str(i - 9) + ']'else:x_path = './/div[@class="more-wrapper"]/button[' + str(i) + ']'load_more = driver.find_element(by="xpath", value=x_path)load_more.send_keys("Enter") # 點(diǎn)擊前先按下Enter,可以解決因跳轉(zhuǎn)點(diǎn)擊時(shí)出現(xiàn)失去焦點(diǎn)而導(dǎo)致的click單擊無(wú)效的情況load_more.click()# 把iframe又轉(zhuǎn)回去driver.switch_to.default_content()print("Click and waiting loading --- please waiting for 5s")time.sleep(5)driver.switch_to.frame(driver.find_element(by="css selector", value="iframe[title='livere-comment']"))comments = driver.find_elements(by="css selector", value="div.reply-content")for each_comment in comments:content = each_comment.find_element(by="tag name", value="p")print(content.text)driver.switch_to.default_content()driver.execute_script("window.scrollTo(0,document.body.scrollHeight);")time.sleep(2)Selenium的常見(jiàn)操作元素方法如下:
- Clear:清除元素的內(nèi)容
- send_keys:模擬按鍵輸入
- Click:單擊元素
- Submit:提交表單
Selenium除了可以實(shí)現(xiàn)簡(jiǎn)單的鼠標(biāo)操作,還可以實(shí)現(xiàn)復(fù)雜的雙擊、拖拽等操作。此外,Selenium還可以獲得網(wǎng)頁(yè)中各個(gè)元素的大小,甚至可以進(jìn)行模擬鍵盤(pán)的操作。
3.4 Selenium的高級(jí)操作
常用的加快Selenium的爬取速度的方法有:
- 控制CSS的加載
- 控制圖片文件的顯示
- 控制JavaScript的運(yùn)行
3.4.1 控制CSS
在抓取過(guò)程中僅僅抓取頁(yè)面的內(nèi)容,CSS樣式文件是用來(lái)控制頁(yè)面的外觀(guān)和元素放置位置的,對(duì)內(nèi)容并沒(méi)有影響,所以我們可以通過(guò)限制網(wǎng)頁(yè)加載CSS,從而較少抓取時(shí)間,其代碼如下:
# 控制CSS from selenium import webdriver# 使用fp控制CSS的加載 fp = webdriver.FirefoxOptions() fp.set_preference("permissions.default.stylesheet", 2) driver = webdriver.Firefox(options=fp) driver.get("http://www.santostang.com/2018/07/04/hello-world/")3.4.2 限制圖片的加載
如果不需要抓取網(wǎng)頁(yè)上的圖片,最好可以禁止圖片加載,限制圖片的加載可以幫助我們極大地提高網(wǎng)絡(luò)爬蟲(chóng)的效率。
# 限制圖片的加載 from selenium import webdriverfp = webdriver.FirefoxOptions() fp.set_preference("permissions.default.image", 2) driver = webdriver.Firefox(options=fp) driver.get("http://www.santostang.com/2018/07/04/hello-world/")3.4.3 控制JavaScript的運(yùn)行
如果需要抓取的內(nèi)容不是通過(guò)JavaScript動(dòng)態(tài)加載得到的,我們可以通過(guò)禁止JavaScript的執(zhí)行來(lái)提高抓取的效率。因?yàn)榇蠖鄶?shù)網(wǎng)頁(yè)都會(huì)利用JavaScript異步加載很多的內(nèi)容,這些內(nèi)容不僅是我們不需要的,它們的加載還浪費(fèi)了時(shí)間。
# 限制JavaScript的執(zhí)行 from selenium import webdriver fp=webdriver.FirefoxOptions() fp.set_preference("javascript.enabled",False) driver=webdriver.Firefox(options=fp) driver.get("http://www.santostang.com/2018/07/04/hello-world/")參考資料
[1] 唐松.2019.Python網(wǎng)絡(luò)爬蟲(chóng)從入門(mén)到實(shí)踐(第2版)[M].北京:機(jī)械工業(yè)出版社
總結(jié)
以上是生活随笔為你收集整理的动态网页抓取——学习笔记的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: vue项目token放在哪里_关于vue
- 下一篇: 百度智能云金融安全计算平台有多强?安排!