原文出处: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&ranges=2014_2018_Year&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 >= <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;">'&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)
就可以爬取指定页数的论文编号,并下载了!