1. 程式人生 > >python+selenium批量爬取IEEExplore論文

python+selenium批量爬取IEEExplore論文

原文出處:https://blog.csdn.net/qq_25072387/article/details/78588173

一、環境搭建

首先下載安裝selenium包,推薦直接使用pip

之後還要下載對應瀏覽器的驅動(driver),這裡使用的是chrome瀏覽器,注意驅動與瀏覽器的版本要相對應。下載的驅動直接複製到python和chrome的安裝目錄下。

python+selenium的環境搭建教程很多,這裡不做贅述。


二、觀察一下

我們以:

 http://ieeexplore.ieee.org/search/searchresult.jsp?reload=true&queryText=SLAM&ranges=2014_2018_Year&sortType=desc_p_Citation_Count

為目標頁面,爬取其中pdf。

手動下載的話,點選pdf圖示就可以進入下載頁面。



我們先隨便進入一個下載頁面,暗中觀察:



發現這個url後面有一串奇怪的引數,這個引數值和檔名一樣。再回到上一頁,右鍵→檢查元素:



發現這篇文章的pdf的圖示是一個a標籤,標籤裡也有這串數字。

再觀察一下其他論文,發現它們的下載頁面url只是替換了這個引數,而url的前半部分都是相同的:

'http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber='

也就是說,這個引數是論文的一個編號,只要拿到每篇論文的這個編號,再和以上字串拼接,就能得到下載頁面的url。

而每篇論文的pdf圖示a標籤裡,就有一個data-artnum屬性,屬性值就是我們要的論文編號。

那麼只要爬出每個data-artnum的值就行了


三、ok,開始爬蟲

我們在編輯器裡寫下這樣的程式碼:

from selenium import webdriver
import time

browser = webdriver.Chrome() # 驅動chrome
url = http://ieeexplore.ieee.org/search/searchresult.jsp?queryText=SLAM&ranges=2014_2018_Year&sortType=desc_p_Citation_Count


browser.get(url) # 跳轉到目標頁面
time.sleep(5) #象徵性地等一下

link_list = browser.find_elements_by_xpath("//*[@data-artnum]") #使用selenium的xpath定位到每個具有data-artnum元素
for link in link_list:
ele_num = link.get_attribute(‘data-artnum’)
print(ele_num)

執行一下,chrome自動啟動並跳轉到了ieeexplore,控制檯也打出了一堆數字:



誒,不對啊,怎麼每個編號都重複了一次,而且只爬出了10個編號,第一頁明明有25篇論文呢。

再去目標頁面檢查一下元素:



原來pdf圖示前面還有個html圖示,裡面也有data-artnum屬性,爬蟲的時候把html圖示的這個屬性也給爬進來了。

這個問題解決起來很容易,我們只要在結果中做一下去重,或者加一些其他的判別條件,不爬html圖示就好了。

那什麼會少15篇論文呢?

觀察了一下滾動條,終於發現

滾動條向下滾動的時候,變短了!

這就說明,後面的論文是一邊滾動一邊動態載入的,也就是採用的“懶載入”的方式。

我們用selenium開啟頁面後,沒有去做拖動滾動條的操作,後面的論文當然不會載入啦。

要解決這個問題,也很簡單,我們可以在頁面開啟後,在time.sleep的時間裡手動把滾動條滾動到底。

當然不推薦這麼做,要是我爬60頁,每重新整理一次頁面,都要自己滾來滾去的,那也太傻了。我們還是用selenium執行js操作來控制滾動條。

在程式碼中加上這麼幾句(加在開啟頁面後和使用xpath定位之前):

time.sleep(5)
js = 'window.scrollTo(0, document.body.scrollHeight);'
browser.execute_script(js)
time.sleep(5)
browser.execute_script(js)
這裡要執行兩次滾動操作,第一次滾動加載出20條內容,第二次滾動加載出全部25條。

這次就沒問題了,已經能跑出第一頁的所有論文的編號了。

有了編號還要下載,於是稍微修改一下程式碼,變成這樣:

# -*- coding: utf-8 -*-
import requests
from bs4 import BeautifulSoup
from selenium import webdriver
import time

# 執行函式
def work(browser,url):

browser.get(url)
ele_nums = []
time.sleep(<span style="color:#6897bb;">10</span>)
js = <span style="color:#008080;">'window.scrollTo(0, document.body.scrollHeight);'

browser.execute_script(js)
time.sleep(5)
browser.execute_script(js)

<span style="color:#cc7832;"><strong>try</strong></span>:
    <span style="color:#cc7832;"><strong>for </strong></span>link <span style="color:#cc7832;"><strong>in </strong></span>browser.find_elements_by_xpath(<span style="color:#008080;">"//*[@data-artnum]"</span>):
        <span style="color:#cc7832;"><strong>if </strong></span>isContainClass(link.get_attribute(<span style="color:#008080;">'className'</span>)<span style="color:#cc7832;">,</span><span style="color:#008080;">'icon-pdf'</span>):
            ele_num = link.get_attribute(<span style="color:#008080;">'data-artnum'</span>)
            ele_nums.append(ele_num)

    <span style="color:#cc7832;"><strong>return </strong></span>ele_nums

<span style="color:#cc7832;"><strong>except</strong></span>:
    <span style="color:#8888c6;">print</span>(<span style="color:#008080;">"failure"</span>)

#用於判斷某元素是否具有某class
def isContainClass(allClass,targetClass):
#解析allClass,判斷是否包含targetClass
classArr = allClass.split(’ ')
result = False
for str in classArr:
if str == targetClass:
result = True
break
return result

def getHtml(url):
# Mozilla/5.0 (Windows NT 10.0; WOW64; rv:57.0) Gecko/20100101 Firefox/57.0
headers = {‘user-agent’: ‘Mozilla/5.0 (Windows NT 10.0; WOW64; rv:57.0) Gecko/20100101 Firefox/57.0’}
try:
response = requests.get(url,timeout=40,headers=headers)
response.raise_for_status()

    response.encoding = response.apparent_encoding

    <span style="color:#cc7832;"><strong>return </strong></span>response.text
<span style="color:#cc7832;"><strong>except</strong></span>:
    <span style="color:#cc7832;"><strong>import </strong></span>traceback
    traceback.print_exc()

def getSoup(html):
soup = BeautifulSoup(html,‘html.parser’)
print(soup.body.find_all(‘a’,attrs={‘class’:r’icon-pdf’}))

def downloadPaper(url):
try:
soup = BeautifulSoup(getHtml(url), ‘html.parser’)
result = soup.body.find_all(‘iframe’)

    downloadUrl = result[-<span style="color:#6897bb;">1</span>].attrs[<span style="color:#008080;">'src'</span>].split(<span style="color:#008080;">'?'</span>)[<span style="color:#6897bb;">0</span>]

    headers = {<span style="color:#008080;">'user-agent'</span>: <span style="color:#008080;">'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:57.0) Gecko/20100101 Firefox/57.0'</span>}
    response = requests.get(downloadUrl<span style="color:#cc7832;">, </span><span style="color:#aa4926;">timeout</span>=<span style="color:#6897bb;">80</span><span style="color:#cc7832;">, </span><span style="color:#aa4926;">headers</span>=headers)

    fname = downloadUrl[-<span style="color:#6897bb;">12</span>:]
    <span style="color:#8888c6;">print</span>(fname)

    <span style="color:#cc7832;"><strong>with </strong></span><span style="color:#8888c6;">open</span>(fname<span style="color:#cc7832;">,</span><span style="color:#008080;">'ab+'</span>) <span style="color:#cc7832;"><strong>as </strong></span>f:
        <span style="color:#8888c6;">print</span>(<span style="color:#008080;">'start download file '</span><span style="color:#cc7832;">,</span>fname)
        f.write(response.content)
<span style="color:#cc7832;"><strong>except</strong></span>:
    <span style="color:#cc7832;"><strong>import </strong></span>traceback
    <span style="color:#cc7832;"><strong>with </strong></span><span style="color:#8888c6;">open</span>(<span style="color:#008080;">'errorLog'</span><span style="color:#cc7832;">,</span><span style="color:#008080;">'ab+'</span>) <span style="color:#cc7832;"><strong>as </strong></span>f:
        traceback.print_exc(<span style="color:#aa4926;">file</span>=f)

if name == main:

url = <span style="color:#008080;">'http://ieeexplore.ieee.org/search/searchresult.jsp'</span>+\
      <span style="color:#008080;">'?queryText=SLAM&amp;ranges=2014_2018_Year&amp;sortType=desc_p_Citation_Count'

baseUrl = http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=
maxPageNumber = 3
browser = webdriver.Chrome()

<span style="color:#cc7832;"><strong>if </strong></span>maxPageNumber &gt;= <span style="color:#6897bb;">1</span>:
    eleNums = work(browser<span style="color:#cc7832;">,</span>url)
    eleNums = <span style="color:#8888c6;">list</span>(<span style="color:#8888c6;">set</span>(eleNums))
    <span style="color:#cc7832;"><strong>for </strong></span>eleNum <span style="color:#cc7832;"><strong>in </strong></span>eleNums:
        newUrl = baseUrl+<span style="color:#8888c6;">str</span>(eleNum)
        downloadPaper(newUrl)

<span style="color:#cc7832;"><strong>else</strong></span>:
    <span style="color:#cc7832;"><strong>for </strong></span>i <span style="color:#cc7832;"><strong>in </strong></span><span style="color:#8888c6;">range</span>(<span style="color:#6897bb;">2</span><span style="color:#cc7832;">,</span>maxPageNumber+<span style="color:#6897bb;">1</span>):
        url = url+<span style="color:#008080;">'&amp;pageNumber='</span>+<span style="color:#8888c6;">str</span>(i)
        eleNums = work(browser<span style="color:#cc7832;">,</span>url)
        eleNums = <span style="color:#8888c6;">list</span>(<span style="color:#8888c6;">set</span>(eleNums))
        <span style="color:#cc7832;"><strong>for </strong></span>eleNum <span style="color:#cc7832;"><strong>in </strong></span>eleNums:
            newUrl = baseUrl + <span style="color:#8888c6;">str</span>(eleNum)
            downloadPaper(newUrl)

就可以爬取指定頁數的論文編號,並下載了!