python+selenium批量爬取ieeexplore论文

来源:互联网 发布:医院网络拓扑结构图 编辑:程序博客网 时间:2024/06/07 17:41

一、环境搭建

首先下载安装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 webdriverimport timebrowser = webdriver.Chrome()  # 驱动chromeurl = "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 requestsfrom bs4 import BeautifulSoupfrom selenium import webdriverimport 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")#用于判断某元素是否具有某classdef isContainClass(allClass,targetClass):    #解析allClass,判断是否包含targetClass    classArr = allClass.split(' ')    result = False    for str in classArr:        if str == targetClass:            result = True            break    return resultdef 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)

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

原创粉丝点击