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)

就可以爬取指定页数的论文编号,并下载了!

猜你喜欢

转载自blog.csdn.net/SL_World/article/details/84863702