Python爬蟲,批量獲取知網文獻信息

2021-02-19 不冷不熱正合適
一、前言

最近臨近畢業,寫畢業論文需要從知網查找大量的文獻。但去知網一條一條進去看摘要又略顯麻煩和浪費時間。於是,反手寫一個爬蟲,批量獲取基本信息,豈不美哉?

在開始這個項目之前,我抱著不重複造輪子的心態,尋思著去Github先找找。結果發現基本上都是幾年前的項目,現在早已不能使用。最後證實了,靠別人不如靠自己,擼起袖子就開幹!

1. 爬蟲基礎網絡爬蟲就是模擬瀏覽器發送網絡請求,接收請求響應,一種按照一定的規則,自動地抓取網際網路信息的程序。
目前爬蟲主要分為以 requests 庫為代表的模擬請求類爬蟲和以 selenium 為代表的模擬瀏覽器用戶行為的爬蟲兩類。:Requests 是用Python語言編寫,基於 urllib,採用 Apache2 Licensed 開源協議的 HTTP 庫。它比 urllib 更加方便,可以節約我們大量的工作,完全滿足 HTTP 測試需求。Requests 的哲學是以 PEP 20 的習語為中心開發的,所以它比 urllib 更加 Pythoner。Selenium 是一個用於Web應用程式測試的工具。Selenium測試直接運行在瀏覽器中,就像真正的用戶在操作一樣。支持的瀏覽器包括IE,Mozilla Firefox,Safari,Google Chrome,Opera等。中國知網作為國內最知名的文獻資料庫之一,有著複雜的反爬蟲機制,包括:動態JS、iframe、驗證碼等等。直接模擬請求難度較大,且容易被封IP位址,所以本文主要介紹如何使用Selenium來爬取知網。2. Selenium基本用法Selenium支持非常多的瀏覽器,如Chrome、Firefox、Edge等,我們只要首先下載好相應瀏覽器的webdriver到python主目錄中,或者加入環境變量即可。

不同瀏覽器的初始化:

from selenium import webdriver

browser = webdriver.Chrome()
browser = webdriver.Firefox()
browser = webdriver.Edge()
browser = webdriver.Safari()

我們可以用get()方法來請求一個網頁,傳入參數連結URL

browser.get('https://www.bing.com')

find_element_by_id()
find_element_by_name()
find_element_by_class_name()
find_element_by_tag_name()
find_element_by_link_text()
find_element_by_partial_link_text()
find_element_by_xpath()
find_element_by_css_selector()

在element變成elements就是找所有滿足的條件,返回數組。
另外,我經常使用的查找元素方法為selenium中selenium.webdriver.common.by的By, 聯合隱士等待EC
用法如下:

# 單個元素
WebDriverWait( driver, 10 ).until( EC.presence_of_element_located((By.XPATH ,"") ) )
# 多個元素
WebDriverWait( driver, 10 ).until( EC.presence_of_all_elements_located( (By.CLASS_NAME ,"fz14") ) )

# 元素類型有:
CLASS_NAME = 'class name'
CSS_SELECTOR = 'css selector'
ID = 'id'
LINK_TEXT = 'link text'
NAME = 'name'
PARTIAL_LINK_TEXT = 'partial link text'
TAG_NAME = 'tag name'
XPATH = 'xpath'

在找到相應元素位置後,我們常用的交互動作包括:點擊、輸入、清楚、獲取屬性、獲取文本等

element = find_element_by_id(''id)

element.send_keys('Hello') # 傳入Hello
element.clear() # 清除輸入框
element.click() # 點擊元素
element.text # 獲取元素文本信息
element.get_attribute('href') # 獲取元素屬性

還有大量的方法這裡沒有提及,不過有了以上基本知識,我們就可以開始項目了!二、知網爬蟲實戰1. 知網頁面元素分析知網首頁中,我們僅需要先在輸入框中鍵入主題詞,然後點擊搜索圖標,即可跳轉到結果頁面。

我們通過瀏覽器的檢查頁面,得到輸入框和搜索圖標的XPATH分別為:

input_xpath = '/html[1]/body[1]/div[1]/div[2]/div[1]/div[1]/input[1]'
button_xpath = '/html[1]/body[1]/div[1]/div[2]/div[1]/div[1]/input[2]'

只需要在輸入框鍵入我們要搜索的主題,然後操作搜索按鈕即可轉到結果頁。以搜索Python為例,結果頁如下所示,共找到15,925條,300頁。每頁中包含20個條目,每個條目包含題目、作者、來源等信息。

通過對當前頁面分析,發現每個條目對應的的xpath的規律。

/html[1]/body[1]/div[5]/div[2]/div[2]/div[2]/form[1]/div[1]/table[1]/tbody[1]/tr[1]/td[2]

即倒數第二個標籤數字代表本頁的第幾個條目,最後一個標籤 2 - 6 分別代表題目、作者、來源、發表時間和資料庫。

在當前頁面無法或者文獻的摘要信息,下載連結等等,需要進一步點擊進入相關文獻條目。

進入詳情頁面後,我們根據class name:abstract-text 能夠很容易定位到摘要的文本,class name: btn-dlcaj 定位到下載連結,其他元素同理。


完成以上知網頁面的分析後,我們就可以根據需求開始寫代碼了!

2. 代碼示例

import time
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from urllib.parse import urljoin

這裡我們創建一個Chrome瀏覽器的窗口,並設置相關參數:

#get直接返回,不再等待界面加載完成
desired_capabilities = DesiredCapabilities.CHROME
desired_capabilities["pageLoadStrategy"] = "none"

# 設置谷歌驅動器的環境
options = webdriver.ChromeOptions()
# 設置chrome不加載圖片,提高速度
options.add_experimental_option("prefs", {"profile.managed_default_content_settings.images": 2})
# 設置不顯示窗口
#options.add_argument('--headless')
# 創建一個谷歌驅動器
driver = webdriver.Chrome(options=options)
# 設置搜索主題
theme = "Python"
# 設置所需篇數
papers_need = 100

# 打開頁面
driver.get("https://www.cnki.net")
# 傳入關鍵字
WebDriverWait( driver, 100 ).until( EC.presence_of_element_located( (By.XPATH ,'''//*[@id="txt_SearchText"]''') ) ).send_keys(theme)
# 點擊搜索
WebDriverWait( driver, 100 ).until( EC.presence_of_element_located( (By.XPATH ,"/html/body/div[1]/div[2]/div/div[1]/input[2]") ) ).click()
time.sleep(3)

# 點擊切換中文文獻
WebDriverWait( driver, 100 ).until( EC.presence_of_element_located( (By.XPATH ,"/html/body/div[5]/div[1]/div/div/div/a[1]") ) ).click()
time.sleep(1)
# 獲取總文獻數和頁數
res_unm = WebDriverWait( driver, 100 ).until( EC.presence_of_element_located( (By.XPATH ,"/html/body/div[5]/div[2]/div[2]/div[2]/form/div/div[1]/div[1]/span[1]/em") ) ).text
# 去除千分位裡的逗號
res_unm = int(res_unm.replace(",",''))
page_unm = int(res_unm/20) + 1
print(f"共找到 {res_unm} 條結果, {page_unm} 頁。")

# 賦值序號, 控制爬取的文章數量
count = 1
# 當,爬取數量小於需求時,循環網頁頁碼
while count <= papers_need:
# 等待加載完全,休眠3S
time.sleep(3)

title_list = WebDriverWait( driver, 10 ).until( EC.presence_of_all_elements_located( (By.CLASS_NAME ,"fz14") ) )

# 循環網頁一頁中的條目
for i in range(len(title_list)):
try:
term = count%20 # 本頁的第幾個條目
title_xpath = f"/html[1]/body[1]/div[5]/div[2]/div[2]/div[2]/form[1]/div[1]/table[1]/tbody[1]/tr[{term}]/td[2]"
author_xpath = f"/html[1]/body[1]/div[5]/div[2]/div[2]/div[2]/form[1]/div[1]/table[1]/tbody[1]/tr[{term}]/td[3]"
source_xpath = f"/html[1]/body[1]/div[5]/div[2]/div[2]/div[2]/form[1]/div[1]/table[1]/tbody[1]/tr[{term}]/td[4]"
date_xpath = f"/html[1]/body[1]/div[5]/div[2]/div[2]/div[2]/form[1]/div[1]/table[1]/tbody[1]/tr[{term}]/td[5]"
database_xpath = f"/html[1]/body[1]/div[5]/div[2]/div[2]/div[2]/form[1]/div[1]/table[1]/tbody[1]/tr[{term}]/td[6]"
title = WebDriverWait( driver, 10 ).until( EC.presence_of_element_located((By.XPATH ,title_xpath) ) ).text
authors = WebDriverWait( driver, 10 ).until( EC.presence_of_element_located((By.XPATH ,author_xpath) ) ).text
source = WebDriverWait( driver, 10 ).until( EC.presence_of_element_located((By.XPATH ,source_xpath) ) ).text
date = WebDriverWait( driver, 10 ).until( EC.presence_of_element_located((By.XPATH ,date_xpath) ) ).text
database = WebDriverWait( driver, 10 ).until( EC.presence_of_element_located((By.XPATH ,database_xpath) ) ).text

# 點擊條目
title_list[i].click()
# 獲取driver的句柄
n = driver.window_handles
# driver切換至最新生產的頁面
driver.switch_to_window(n[-1])
# 開始獲取頁面信息
# title = WebDriverWait( driver, 10 ).until( EC.presence_of_element_located((By.XPATH ,"/html/body/div[2]/div[1]/div[3]/div/div/div[3]/div/h1") ) ).text
# authors = WebDriverWait( driver, 10 ).until( EC.presence_of_element_located((By.XPATH ,"/html/body/div[2]/div[1]/div[3]/div/div/div[3]/div/h3[1]") ) ).text
institute = WebDriverWait( driver, 10 ).until( EC.presence_of_element_located((By.XPATH ,"/html[1]/body[1]/div[2]/div[1]/div[3]/div[1]/div[1]/div[3]/div[1]/h3[2]") ) ).text
abstract = WebDriverWait( driver, 10 ).until( EC.presence_of_element_located((By.CLASS_NAME ,"abstract-text") ) ).text
try:
keywords = WebDriverWait( driver, 10 ).until( EC.presence_of_element_located((By.CLASS_NAME ,"keywords") ) ).text[:-1]
except:
keywords = '無'
url = driver.current_url
# 獲取下載連結
# link = WebDriverWait( driver, 10 ).until( EC.presence_of_all_elements_located((By.CLASS_NAME ,"btn-dlcaj") ) )[0].get_attribute('href')
# link = urljoin(driver.current_url, link)

# 寫入文件
res = f"{count}\t{title}\t{authors}\t{institute}\t{date}\t{source}\t{database}\t{keywords}\t{abstract}\t{url}".replace("\n","")+"\n"
print(res)
with open('CNKI_res.tsv', 'a', encoding='gbk') as f:
f.write(res)

except:
print(f" 第{count} 條爬取失敗\n")
# 跳過本條,接著下一個
continue
finally:
# 如果有多個窗口,關閉第二個窗口, 切換回主頁
n2 = driver.window_handles
if len(n2) > 1:
driver.close()
driver.switch_to_window(n2[0])
# 計數,判斷需求是否足夠
count += 1
if count == papers_need:break


# 切換到下一頁
WebDriverWait( driver, 10 ).until( EC.presence_of_element_located( (By.XPATH ,"//a[@id='PageNext']") ) ).click()

# 關閉瀏覽器
driver.close()

至此,所有功能都已實現,代碼中寫了詳細的注釋。需要獲得完整代碼的可以直達我的Github下載,CNKI_Spider.py(https://github.com/byemaxx/BioTools)。結果展示結果是一個以制表符分隔的表格文件,其中包含了論文的基本信息,包括:題目、作者、來源、摘要、連結等

三、遇到的一些坑1. 網頁加載太慢導致元素查找出錯有時候我們並不需要網頁完全,我們想要的信息已經加載出來,於是加上以下設置:

#get直接返回,不再等待界面加載完成
desired_capabilities = DesiredCapabilities.CHROME
desired_capabilities["pageLoadStrategy"] = "none"

另一方面,在適當的地方加上 time.sleep(3) 延時幾秒,既可以等待頁面加載,也可以防止爬取太快被封IP。2. 編碼不同導致的文件寫入失敗在寫入文件時,由於存在不同的編碼,常常導致文件寫入失敗,在最開始我轉換編碼為 utf-8 ,後來發現這個編碼在excel裡面居然是亂碼,於是改為 gbk 編碼。

with open('CNKI_res.tsv', 'a', encoding='gbk') as f:
f.write(res)

3. xpath 地址經常發生改變由於知網中包含著不同類型的文獻,如期刊、碩博、會議、專利 等,xpath的位置不是一成不變的,雖然xpath唯一定位的特性便於我們找到相應的標籤。但偶爾class name 或許是更好的選擇。四、後記

在數據分析中,往往花費時間的事數據的獲取和數據清洗,怎樣從網際網路海量的數據中高效獲取我們想要的部分?無疑網絡爬蟲是最佳的選擇之一。學習好爬蟲的相關庫的運用,不論是從或聯網上獲取相關的數據,還是設置某些東東提交任務,甚至是寫一些搶票軟體都不是什麼困難的事情。

另一方面,爬蟲與網站的反爬系統一直都是攻防的雙方,Selenium 這類軟體能夠直接模擬瀏覽器操作,進而繞過一些反爬機制,但並不是不能夠被網站識別。在真實的情況中,我們往往需要結合多種手段爬取網頁。

在這場爬蟲和反爬蟲的軍備競賽中;在人與計算機的競賽中,我們只有不斷地學習新的東西,才能在這場進化中不被淘汰。

寫留言

相關焦點

  • python爬蟲-知網(CNKI)主題文獻
    本文介紹使用Python爬蟲技術快速獲取知網1000多篇某個主題的文章的題目,作者,作者單位,引用次數,下載次數,發表刊物,發表時間
  • 批量下載文獻法寶①——關鍵詞篇
    前兩天,因為要開一個新的課題關於肺癌的,我要看很多相關的文獻,需要批量下載關鍵詞為lung cancer的文獻。但是我用endnote關鍵詞查找,我發現,我的endnote不能點擊查找全文。這可把我愁壞了,但是我Trouble Breaker不是浪得虛名,經過我的不懈探索,終於找到了批量下載文獻的兩法寶。
  • 進階版python獲取天氣信息——爬蟲入門
    python定時獲取天氣數據並自動發送到郵箱中,調用了其它網站的天氣接口來獲取天氣。瀏覽器基於這些問題,今天我們就來個進階版的獲取天氣信息方法——爬蟲獲取,同時該例子也是理解入門爬蟲的最好例子。1.爬蟲先來講講爬蟲是什麼?爬蟲,又叫網絡蜘蛛,是一個探測的機器。它模擬人的行為去各個網站溜達,看到有用的信息就想自己下載下來保存一份。簡答一句話就是在網頁上提取我們想要的信息。
  • Python爬蟲: 《經濟研究》研究熱點和主題分析
    背景使用 Python 爬蟲的好處爬蟲,顧名思義,指我們沿著網絡抓取自己的獵物(數據)。使用這種方法,我們可以向網站發起請求,獲取資源後分析並提取有用數據。本文目標本文目標為模擬知網的高級搜索,獲取特定學術期刊的歷史論文信息。以國內經濟學頂刊《經濟研究》為例,獲取其 2000-2018 年的全部文章數據。具體包括摘要頁的題名、作者、來源、發表時間、資料庫、被引、下載,以及詳細頁面的單位、關鍵字、摘要等信息,以探究近二十年來國內核心期刊發文概況及研究熱點的變動趨勢。
  • python爬蟲之selenium抓取淘寶商品信息
    簡介本節採用python爬蟲相關技術獲取淘寶商品信息。採用的技術有selenium、pyquery及urllib.parse等。selenium可以模擬用戶執行的操作,是一個自動化測試工具,我們可以根據自己的需要預先設置selenium按照我們設置好的步驟進行操作,而在爬蟲中我們使用selenium可以解決javascript動態執行代碼的問題,不用費心去解析js如何運行,運行後產生的信息,直接使用selenium模擬實際登陸網頁的操作,獲取我們需要的信息進行分析,成功幫我們避開一系列複雜的通信過程,方便使用者。
  • 如何從知網、百度學術批量導出文獻到endnote
    今天給大家分享一下如何從百度學術和知網批量導出文獻到endnote,初學者可以真正看看,老司機可以跳過,當然可以在文末點個讚再走,謝謝支持!一、從知網中批量導出文獻1.首先打開知網,輸入關鍵詞:石墨烯,然後勾選你想要導出的文獻,或者全選→【導出文獻】→【endnote】,如下圖所示。2.
  • 從零開始的python爬蟲速成指南
    在前言:最近後臺有人留言問:有沒有python爬蟲的相關教程,爬蟲不是我專業方向,很多不是很熟悉,而網上很多資料講的過於散亂,不能很好的系統性學習爬蟲,而且水平參差不齊。特委託一位熟悉爬蟲的小夥伴,幫忙把關,將網上現有資料進行整合,整理了一份相對比較系統的資料。
  • Python爬蟲實戰 批量下載高清美女圖片
    彼岸圖網站裡有大量的高清圖片素材和壁紙,並且可以免費下載,讀者也可以根據自己需要爬取其他類型圖片,方法是類似的,本文通過python爬蟲批量下載網站裡的高清美女圖片
  • python網頁爬蟲實戰:PEER資料庫地震波批量下載
    2019年6月TIOBE程式語言排行榜在地震工程領域,地震波數據的獲取可謂是研究的基礎,無論是動力時程分析和動力增量分析還是振動臺試驗都需要大量地震波數據。抗震紐西蘭今年2月曾推出兩期連載介紹如何使用PEER資料庫(詳見PEER地面運動資料庫使用教程Ⅰ:搜索原始數據和PEER地面運動資料庫使用教程Ⅱ:創建反應譜),但當需要大量地震波數據時,手動下載就顯得費時費力,此時python就能發揮出巨大優勢批量下載數據。
  • Python 爬蟲「學前班」!學會免踩坑!
    智能爬蟲目前有三種:1. 基於網頁內容的爬蟲當網頁含有大量需要提取的信息時,我們就需要用到基於網頁內容的爬蟲。該爬蟲會將 HTML 視為文本並利用 NLP 技術進行處理。基於DOM結構的爬蟲基於DOM結構的爬蟲相對來說比較簡單,就是將 HTML 解析為 DOM 樹,然後根據語法結構進行提取信息,這種方法效率和準確性都比前一種方法高。3.
  • 知網如何批量導出參考文獻
    我們使用寫論文的時候總是需要填寫參考文獻,還要使用固定的格式,要是自已手打的話難免有些繁瑣,下面就教大家一個方法直接從知網導出標準格式的參考文獻。搜索中國知網,找到中國知網的官方網站後點擊進入網站。在搜索框中輸入要查找的關鍵詞,點擊檢索按鈕開始檢索,下面會顯示搜索好的文獻。在自己要導出的文獻前面勾選上對號,點擊題名左邊的小方框即可。點擊上方的導出參考文獻按鈕,這時會跳轉到文獻管理中心頁面。點擊文獻檢索中心裏面的生成檢索報告按鈕。
  • 從零開始的Python爬蟲教程(一):獲取HTML文檔
    在接下來的教程中,需要大家提前安裝python3.x版本,大家不必拘泥於具體的版本,不管安裝的是3.0還是最新的3.7,都不影響接下來的操作。至於安裝教程,這裡就不過多贅述了,讀者可自行搜索到詳細的教程。
  • 初學者如何用「python爬蟲」技術抓取網頁數據?
    想要入門Python 爬蟲首先需要解決四個問題:1.熟悉python編程2.了解HTML3.了解網絡爬蟲的基本原理4.學習使用python爬蟲庫1、熟悉python編程剛開始入門爬蟲,初學者無需學習python的類,多線程,模塊和其他稍微困難的內容。
  • Python爬蟲入門教程:超級簡單的Python爬蟲教程
    這是一篇詳細介紹 Python 爬蟲入門的教程,從實戰出發,適合初學者。讀者只需在閱讀過程緊跟文章思路,理清相應的實現代碼,30 分鐘即可學會編寫簡單的 Python 爬蟲。;今天給大家講第一課了解網頁;以中國旅遊網首頁為例,抓取中國旅遊網首頁首條信息(標題和連結),數據以明文的形式出面在源碼中。
  • Python開發簡單爬蟲【學習資料總結】
    一、簡單爬蟲架構 方法2:添加data,http header 向伺服器提交http的頭信息,形成一個data,可以向伺服器提交需要用戶輸入的數據。
  • python爬蟲-- Scrapy入門
    前言轉行做python程式設計師已經有三個月了,這三個月用Scrapy爬蟲框架寫了兩百多個爬蟲,不能說精通了Scrapy,但是已經對Scrapy有了一定的熟悉
  • Python 爬蟲基礎入門篇——Requests模塊
    )、PUT(更新)、DETELE(刪除)、HEAD(獲取相應頭信息)、OPTIONS(獲取指定資源所支持HTTP請求方法)以及PATCH(新引入的,是對PUT方法的補充,用來對已知資源進行局部更新)常用到的是GET與POST.
  • Python爬蟲學習的完整路線推薦
    大數據時代,網際網路成為大量信息的載體,機械的複製粘貼不再實用,不僅耗時費力還極易出錯,這時爬蟲的出現解放了大家的雙手,以其高速爬行、定向抓取資源的能力獲得了大家的青睞。爬蟲變得越來越流行,不僅因為它能夠快速爬取海量的數據,更因為有python這樣簡單易用的語言使得爬蟲能夠快速上手。
  • Python爬蟲與文本分析應用案例研討會
    Python作為一門面向對象的程式語言,簡潔的語法使得編寫數十行代碼即可實現爬蟲功能,獲取海量網際網路數據。本課程的授課方式是通過python和knime編程的方式,課程最終目的是實現各種分析的自動化流程,課程成果可以在今後工作中復用。   為什麼要學爬蟲技術,學了以後有什麼好處?
  • Python 爬蟲必殺技:XPath
    小夥伴、大夥伴們,大家好~今天要給大家介紹的是Python 爬蟲必殺技:XPath。1. 簡介一提到網絡爬蟲,就不得不提到Xpath Helper,我們常常用它來對所要提取的文本內容進行定位,詳情可參考推文《Xpath Helper助Xpath爬蟲一臂之力》。除了這一利器外,了解Xpath定位的原理及其基本用法可以大幅提高我們的爬蟲技巧。