皖渝 凹凸數據
你們好,我是小五
寫博客也快一年了,忽然想了解下同層次的博主的平均水平應該是什麼樣的(本身寫的博客咋樣沒點B數麼 ),今天就來分享下CSDN的博主信息數據的爬取方法~
咱們將採用兩種非傳統爬蟲:Selenium爬取、Webscraper爬取javascript
爬取網址:CSDN首頁的Python、Java、前端、架構以及數據庫欄目,各欄目網址以下:
簡單分析其各自的URL不難發現,都是https://www.csdn.net/nav/+欄目名樣式,這樣咱們就能夠爬取不一樣欄目了。
以Python目錄頁爲例,以下圖所示:
爬取內容:每篇文章的博主信息,如博主姓名、碼齡、原創數、訪問量、粉絲數、獲贊數、評論數、收藏數
(考慮到周排名、總排名、積分都是根據上述信息綜合獲得的,對後續分析沒實質性的做用,這裏暫不爬取。)
不想看代碼的朋友可直接跳到第三部分~css
分析目錄頁可知文章是須要動態加載的,此時須要selenium模擬瀏覽器不斷下拉才能獲取新的文章。文章的連接以下所示:前端
思路圖以下:
執行的關鍵代碼以下:java
from selenium import webdriver import time driver = webdriver.Chrome() driver.get('https://www.csdn.net/nav/python') #下拉若干次 for i in range(10): driver.execute_script('window.scrollTo(0,document.body.scrollHeight)') time.sleep(1) #定位全部連接 blog_url = driver.find_elements_by_css_selector('div.title > h2 > a') #注意:這裏保存的是全部element對象 for i in range(len(blog_url)): url = blog_url[i].get_attribute('href') driver.get(url) #------------相關信息爬取(省略)---------- driver.back() #返回目錄頁
理論上,這段代碼看起來是能夠實現要求的,但實際上會遇到如下兩個問題!python
報錯的緣由:selenium當打開新的頁面後,原來定位過的元素都會失效,須要從新定位元素。上面的driver.back()至關於打開的新的頁面(可是對於咱們來講只是返回原來的頁面)
詳細內容可參考這篇博客的內容:https://blog.csdn.net/qq_43251443/article/details/82819887
解決方式:只要每次返回目錄頁後從新定位元素便可,以下所示:web
for i in range(len(blog_url)): blog_refind_url = driver.find_elements_by_css_selector('div.title > h2 > a') #從新定位 url = blog_refind_url[i].get_attribute('href') driver.get(url) #------------相關信息爬取(省略)---------- driver.back() #返回目錄頁
從新定位後,不難發現,這必需要求blog_url和blog_refind_url這兩個列表的長度一致啊!那也就是:每次返回目錄頁後,須要保持在上一次瀏覽的位置! 由此引起了第二個問題:定位元素的不一致。數據庫
咱們在獲取全部的文章連接以前,首先進行的下滑頁面的操做。而每次driver.back()以後,頁面都會回到最初的位置!這就很頭疼,若是要保持同樣的瀏覽位置,難道每次返回後都要下拉相同次數的頁面麼?那麼此時咱們須要解決的問題則是:如何保持上一級頁面的瀏覽位置。emm,查了一些資料,發現這個需求是和javascript相關的。詳細可參考這篇博客:https://blog.csdn.net/chu782729918/article/details/59489616
大體解決思路:保存每次下滑的位置,而後最終調用最後一次下滑的位置。但歸根到底,仍是須要每次滑動頁面,依舊很麻煩,這種思路到這也只能不了了之了。(會javascript的朋友能夠嘗試如何讓頁面直接恢復到上一級頁面瀏覽的位置)瀏覽器
不過,仔細思考一下,上面兩個問題的來源關鍵在於selenium訪問頁面後,元素會從新定位。而咱們第一步定位全部文章連接時保存的列表,裏面的元素都是element對象(它是會隨着頁面變化而改變的!)。因此,咱們只要保存每一個文章的url到一個列表,挨個訪問每一個url,不就能夠了?
思路圖以下:
兩種思路的對比與思考:前者裝有全部文章的列表裏都是element對象,然後者裝有全部文章的列表裏都是url。後者免去了再返回頁面這一操做,至關於將一個爬取二級頁面問題轉化爲一級頁面問題!
爬取過程:
若是你們對完整爬蟲代碼感興趣,掃碼關注「快學Python」後臺回覆「CSDN」
後臺回覆「CSDN」獲取數據&代碼
爬取結果以下:架構
以前的博客分享過Webscraper是一種輕量級的爬取軟件。不想看代碼的朋友能夠用它來複現上述爬取過程。(注:如下爬取過程只是針對首頁的某一個欄目)
最終的爬取線路圖以下:
依舊以首頁的Python欄爲例:ide
這個container只是一個ID,它能夠取任意名字的。其餘的設置以下圖所示:
保存container的selector後,點擊進入下一層,建立以下selector
具體內容以下:
同理,保存完inf的selector後,再點擊進入下一層,依次建立各種信息的selector,以下所示:
以name爲例,其內容以下:
type選擇text,相應的選擇器內容只要鼠標點擊博主姓名便可得到。
這樣,咱們就完成了全部的準備工做,接下來就可爬取啦~全部延遲時間均設置爲2000ms
最終爬取結果以下(這裏僅做演示,只爬取了七條):
本次建立的sitemap以下,有興趣的朋友能夠本身實驗下,只須要import sitemap便可
{"startUrl":"https://blog.csdn.net/nav/python","selectors":[{"parentSelectors": ["_root"],"type":"SelectorElementScroll","multiple":true,"id":"container","selector":"ul.feedlist_mod li.clearfix:nth-of-type(-n+300)","delay":"2000"},{"parentSelectors": ["container"],"type":"SelectorLink","multiple":false,"id":"inf","selector":"h2 a","delay":""},{"parentSelectors": ["inf"],"type":"SelectorText","multiple":false,"id":"name","selector":"div.profile-intro-name-boxTop span.name","regex":"","delay":""},{"parentSelectors": ["inf"],"type":"SelectorText","multiple":false,"id":"blog_num","selector":"dl.text-center:nth-of-type(1) a span.count","regex":"","delay":""},{"parentSelectors": ["inf"],"type":"SelectorText","multiple":false,"id":"code_time","selector":"span.personal-home-page.personal-home-years","regex":"","delay":""},{"parentSelectors": ["inf"],"type":"SelectorText","multiple":false,"id":"views_num","selector":"div.data-info:nth-of-type(2) dl.text-center > dt span.count","regex":"","delay":""},{"parentSelectors": ["inf"],"type":"SelectorText","multiple":false,"id":"fans","selector":"dl#fanBox.text-center span.count","regex":"","delay":""},{"parentSelectors": ["inf"],"type":"SelectorText","multiple":false,"id":"agreement","selector":"dl.text-center:nth-of-type(3) > dt span.count","regex":"","delay":""},{"parentSelectors": ["inf"],"type":"SelectorText","multiple":false,"id":"comment","selector":"div.data-info:nth-of-type(4) dl.text-center:nth-of-type(4) span.count","regex":"","delay":""},{"parentSelectors":["inf"],"type":"SelectorText","multiple":false,"id":"collection_num","selector":"dl.text-center:nth-of-type(5) span.count","regex":"","delay":""}],"_id":"csdn"}
總結:Webscraper雖然簡單易操做,速度也和selenium差很少,但每次只能爬一個網址,須要連續爬取多個網址,仍是得碼代碼~