中国知网爬虫(CNKI) 批量下载PDF格式论文
本文作者:左从江(投稿)
文字编辑:钱梦璇
总思路
首先,获取源码,涉及库:selenium,time。通过webdriver搜索按钮和输入栏,通常用requests无法获得包含论文信息的源码,其原因是知网的查询页面嵌套了一个子页面(iframe),requests请求得到的只是父页面。
其次,从源码中解析出作者、时间、Title以及下载链接,并储存到Excel中留存,其中涉及库re和pandas.
获取网页源码
from selenium import webdriver
import time
import pandas as pd
from bs4 import BeautifulSoup
import random
url = r'http://new.gb.oversea.cnki.net/kns/brief/result.aspx?dbprefix=CJFQ' #给出链接
driver = webdriver.Firefox()
driver.get(url)
blank_ISSN = driver.find_element_by_id('magazine_value1')
#id是在源码中搜索而来
blank_ISSN.send_keys('0577-9154') #输入内容,期刊的ISSN号码
buttom_search = driver.find_element_by_id('btnSearch') #找到搜索按钮
buttom_search.click() #点击搜索
time.sleep(2) #停一小会儿
driver.switch_to.default_content() #找到iframe子页面
driver.switch_to.frame('iframeResult') #切换到iframe子页面
#一次请求50篇论文信息
button_50=driver.find_element_by_xpath(r'/html/body/form/table/tbody/tr[1]/td/table/tbody/tr[1]/td/table/tbody/tr/td[2]/div[2]/a[3]')
button_50.click()
htmls = [] #遍历所有子页面,储存到此列表
b = 1
while True:
try:
soup = BeautifulSoup(driver.page_source,'html.parser')
htmls.append(soup)
#储存完成,点击下一页
time.sleep(random.randint(3,6)) #暂停3~6s,这样封IP概率更小
button_next = driver.find_element_by_id('Page_next')
button_next.click()
except :
print('Error{}'.format(b))
time.sleep(60)
b = b+1
提交请求时,可能遇到输入验证码的情况,手动输入即可,笔者输入了8次验证码,获取到6000条论文信息。
需要注意的是,每次知网只能给出6000条信息,但如下,共检索到8129条结果。此时可以通过限定时间范围将检索结果数量限制在6000条以内,就可以保证获取到全部的结果了。
进行解析
一个tr标签的结构如下,其包含了一篇文章的全部信息:
transfer_list=[] #存储html源码的中转列表
for soups in htmls:
for i in soups.find_all('tr')[7:57]: #在soup搜索出来的tr标签中,列表头尾都有冗余信息,删掉不要
transfer_list.append(i)
raw_paper_infos = [] #使用正则匹配的思路:第一步,缩小信息所在的范围;第二步,精确搜索并删除多余的字符。下面进行第一步
for i in transfer_list: #遍历transfer_list中的每一个tr标签,其结构:[[一个tr标签包含的源码],[].……]
paper = str(i)
title = re.findall('target="_blank">.*</a>',paper)
authors = re.findall('target="knet">.*</a>',paper)
pub_year = re.findall('....-..-..',paper)
download_url = re.findall('briefDl_D" href=".*pdfdown',paper)
quoted_num1 = re.findall('scrollbars=yes.*</span',paper)
download_num = re.findall('onclick="SubCountDownLoad.*</a>',paper)
raw_paper_infos.append([title,authors,pub_year,download_url,quoted_num1,download_num]) #储存了初步的匹配结果
接下来继续匹配工作,精确匹配和删除多余字符:
papers = [] #用于存放最终干净的匹配结果
illegal_word = ['/','\',''',':','|','?','*'] #考虑到后续下载时,保存文件时会有一些非法字符导致文件名生成失败(windows不允许这些字符出现在文件名中)
for i in raw_paper_infos:
if i!=[[], [], [], [], [], []]: #初步搜索时候,会有一些tr标签不是我们的论文标签,不符合初步搜索的要求,其结果就是空列表,通过判断过滤掉
title2 = i[0][0].strip('target="_blank>~</a>')
for x in illegal_word:
title2.replace(x,"")
authors2 = ','.join(j for j in re.findall('[\u2E80-\u9FFF]+',str(i[1])))
pub_year2 = i[2][0]
download_url2 = (i[3][0].strip('briefDl_D" href="..')).replace(';','&') #按照';'连接为caj格式,'&'连接为pdf格式
if i[4] == []:
quoted_num2 = int(0)
else:
quoted_num2 = int(re.findall(r'>.*</a',str(i[4][0]))[0].strip('></a'))
#被引次数对于发表不久的论文,可能没有这一项的数据,因此对于匹配不到的赋值0
download_num2 = int(re.findall(r'>.*<',i[5][0])[0].strip('><')) #论文得下载次数
papers.append([title2,authors2,pub_year2,download_url2,quoted_num2,download_num2])
到此为止,我们有了全部所需要的论文信息。
#储存到excel
pd.DataFrame(papers).to_excel(r'.\JJYJ论文信息汇总.xlsx')
上述结果的Excel截图:
(注:和代码部分略有不同,笔者自行输入了标题行,并且按照发表日期排序)
注意:如上图所示,Excel表中的下载链接是不完整的,下载时需要在前面加上:http://new.gb.oversea.cnki.net/kns.
到此为止,就得到了每篇文章的信息,可利用request库请求链接,下载论文,利用open函数储存到pdf格式。在实践中发现,如果直接用解析的链接获取,下载得到的往往是caj格式文件,但是把链接中的“;”换为“&”就可以正常下载pdf格式的文件了。
NBA球员薪资分析——基于随机森林算法(二)
关于我们
微信公众号“Stata and Python数据分析”分享实用的stata、python等软件的数据处理知识,欢迎转载、打赏。我们是由李春涛教授领导下的研究生及本科生组成的大数据处理和分析团队。
1)必须原创,禁止抄袭;
2)必须准确,详细,有例子,有截图;
注意事项:
1)所有投稿都会经过本公众号运营团队成员的审核,审核通过才可录用,一经录用,会在该推文里为作者署名,并有赏金分成。
2)邮件请注明投稿,邮件名称为“投稿+推文名称”。
3)应广大读者要求,现开通有偿问答服务,如果大家遇到有关数据处理、分析等问题,可以在公众号中提出,只需支付少量赏金,我们会在后期的推文里给予解答。