python+selenium批量爬取ieeexplore论文

一、环境搭建

首先下载安装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(10)
    js = 'window.scrollTo(0, document.body.scrollHeight);'
    browser.execute_script(js)
    time.sleep(5)
    browser.execute_script(js)

    try:
        for link in browser.find_elements_by_xpath("//*[@data-artnum]"):
            if isContainClass(link.get_attribute('className'),'icon-pdf'):
                ele_num = link.get_attribute('data-artnum')
                ele_nums.append(ele_num)

        return ele_nums

    except:
        print("failure")


#用于判断某元素是否具有某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

        return response.text
    except:
        import 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[-1].attrs['src'].split('?')[0]

        headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:57.0) Gecko/20100101 Firefox/57.0'}
        response = requests.get(downloadUrl, timeout=80, headers=headers)

        fname = downloadUrl[-12:]
        print(fname)

        with open(fname,'ab+') as f:
            print('start download file ',fname)
            f.write(response.content)
    except:
        import traceback
        with open('errorLog','ab+') as f:
            traceback.print_exc(file=f)

if __name__ == '__main__':

    url = 'http://ieeexplore.ieee.org/search/searchresult.jsp'+\
          '?queryText=SLAM&ranges=2014_2018_Year&sortType=desc_p_Citation_Count'
    baseUrl = 'http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber='
    maxPageNumber = 3
    browser = webdriver.Chrome()

    if maxPageNumber >= 1:
        eleNums = work(browser,url)
        eleNums = list(set(eleNums))
        for eleNum in eleNums:
            newUrl = baseUrl+str(eleNum)
            downloadPaper(newUrl)

    else:
        for i in range(2,maxPageNumber+1):
            url = url+'&pageNumber='+str(i)
            eleNums = work(browser,url)
            eleNums = list(set(eleNums))
            for eleNum in eleNums:
                newUrl = baseUrl + str(eleNum)
                downloadPaper(newUrl)

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

  • 9
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值