【Python3】利用selenium抓取知乎用戶的文章
來自專欄 Python程序員24 人贊了文章
【背景】
前段時間,閱讀知乎上一些用戶寫的文章的時候覺得閱讀起來比較麻煩,不符合我的閱讀感受。比如下邊這個,我想閱讀牛客網的文章(如圖1所示),我會通過標題先進行篩選,但是這樣滾動下滑太麻煩了,所以想著不如將標題信息爬下來,另外,點贊數和評論數也順便抓取下來,這樣還能看該用戶被點贊數最多的文章是哪一篇。說干就干!
【思路】
利用selenium抓取知乎用戶的文章頁面源碼,接著用pyquery庫來解析文章相關信息,並將其保存到MongoDB資料庫中,通過MongoDB Compass這個可視化工具可以可視化的操作資料庫,還可以進行數據的導入導出。
【涉及知識點】
- 基本庫的使用
- selenium庫、pyquery庫、pymongo庫的使用
- CSS selector的使用
- 正則表達式
【預裝庫及軟體】
- 首先確保自己的電腦安裝了MongoDB資料庫。
- MongoDB Compass軟體自己視情況而定,如果常用命令行操作資料庫的話,這個可以不安裝,對我們的數據抓取沒有影響。
- 確保你的Python3環境中有下邊幾個庫,pymongo、selenium和pyquery要自己安裝,可以直接用pip進行安裝。
import reimport timeimport pymongofrom selenium import webdriverfrom selenium.common.exceptions import TimeoutExceptionfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support import expected_conditions as ECfrom selenium.webdriver.support.wait import WebDriverWaitfrom pyquery import PyQuery as pq
【網頁分析】
- 首先找到知乎用戶牛客網的文章列表的鏈接(如圖2所示),可以看到總共280篇文章。拉到頁面底部可以看到文章列表共有14頁(如圖3所示)。
- 當我們點下一頁,頁面跳轉到第二頁時,可以看到網頁鏈接變成「/org/niu-ke-wang-53/posts?page=2」,這樣的話,我們可以通過改變傳入參數「page」的值來請求這14個頁面。
- 我們使用selenium來模擬瀏覽器打開網頁,這裡使用 WebDriverWait 來等待頁面載入完網頁之後再進行別的處理工作。還可以注意到這樣一件事,頁面載入完成的時候頁面是沒有全部顯示的,隨著滑鼠向下滾動才載入出來頁面的全部信息。通過如下代碼可以模仿滑鼠向下滾動到頁面底部。
browser.execute_script("window.scrollTo(0, document.body.scrollHeight)")
- 載入出來頁面之後就可以抓取信息了。信息提取這部分主要有函數「get_posts()」來負責。我選擇抓取了文章標題、文章鏈接、文章作者、文章作者主頁鏈接、點贊人數以及評論數。
- 最後由函數「save_to_mongo()」來將信息存儲進MongoDB資料庫中。
- 用下邊的代碼來取代「browser = webdriver.Chrome()」可以實現瀏覽器不打開,在後台進行抓取工作。
chrome_options = webdriver.ChromeOptions()chrome_options.add_argument(--headless)browser = webdriver.Chrome(chrome_options=chrome_options)
- 最後打開MongoDB Compass軟體可以看到「Documents」值為280,總共抓取了280篇文章的信息。
【代碼實現】
MONGO_URL = localhostMONGO_DB = zhihuMONGO_COLLECTION = niukewang_postsMAX_PAGE = 14chrome_options = webdriver.ChromeOptions()chrome_options.add_argument(--headless)browser = webdriver.Chrome(chrome_options=chrome_options)# browser = webdriver.Chrome()wait = WebDriverWait(browser, 10)client = pymongo.MongoClient(MONGO_URL)db = client[MONGO_DB]def index_page(page): """ 抓取索引頁 :param page: 頁碼 """ print(正在爬取第, page, 頁) try: url = https://www.zhihu.com/org/niu-ke-wang-53/posts?page= + str(page) browser.get(url) wait.until( EC.text_to_be_present_in_element((By.CSS_SELECTOR, .Pagination .PaginationButton--current), str(page))) wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, .Profile-mainColumn .List .List-item))) browser.execute_script("window.scrollTo(0, document.body.scrollHeight)") time.sleep(3) get_posts() except TimeoutException: index_page(page)def get_posts(): """ 提取文章數據 """ html = browser.page_source doc = pq(html) items = doc(#Profile-posts .List-item).items() for item in items: urlstr = item.find(.ContentItem.ArticleItem).attr(data-zop) pattern = re.compile("itemId":(.*?),) urlid = re.findall(pattern, urlstr) commentstr = item.find(.ContentItem-actions .ContentItem-action.Button--plain).text() pattern = re.compile((d+)) commentnum = re.findall(pattern, commentstr) if len(commentnum) == 0: commentnum.append(0) niukewang_posts = { title: item.find(.ContentItem-title).text(), url: https://zhuanlan.zhihu.com/p/+urlid[0], authorname: item.find(.ContentItem-meta .AuthorInfo-content .UserLink-link).text(), authorurl: https:+str(item.find(.ContentItem-meta .AuthorInfo-content .UserLink-link).attr(href)), like: int(item.find(.ContentItem-actions .LikeButton).text()), commentnum: int(commentnum[0]) } print(niukewang_posts) save_to_mongo(niukewang_posts)def save_to_mongo(result): """ 保存至MongoDB :param result: 結果 """ try: if db[MONGO_COLLECTION].insert(result): print(存儲到MongoDB成功) except Exception: print(存儲到MongoDB失敗)def main(): """ 遍歷每一頁 """ for i in range(1, MAX_PAGE + 1): index_page(i) browser.close()if __name__ == __main__: main()
【成果展示】
下載好的信息按照條目存放到了本地MongoDB資料庫里(如圖5所示)。
用點贊數作為關鍵詞進行降序排列(如圖6所示),其中,點贊數最多的是「十面阿里,七面頭條,六個Offer,春招結束」這篇文章,有710個贊和83條評論。
【後記】
寫文章的初衷也算是將自己的學習成果傳播給大家,來幫助大家學習,所以對我寫的這篇文章有什麼問題的歡迎詢問,同時,有錯誤的地方也歡迎批評指正~
後邊寫的多的話,會將代碼一一整理出來放到GitHub上,分享給大家~
推薦閱讀: