👇 连享会 · 推文导航 | www.lianxh.cn
🍓 课程推荐:连享会:2025生成式人工智能专题·网络直播 嘉宾:杨阳 (香港浸会大学) 时间:2025 年 9 月 13, 14, 20 日 咨询:王老师 18903405450(微信)
作者:左从江 邮箱:zuocj9700@163.com
温馨提示: 文中链接在微信中无法生效。请点击底部 「阅读原文」 。或直接长按/扫描如下二维码,直达原文:
目录
1. 总体思路
2. 解析前奏:获取页面的 html
3. 解析
4. 下载论文的代码
这篇文章介绍获取 PDF 格式的论文。
在知网页面的 html 中有下载链接,复制到搜索栏,确实是可以下载论文的,只需要获得作者,时间,题目以及下载链接就可以用循环结构批量下载论文。
当然前提是,您本来就可以下载论文,不管是用 VPN 还是校园网。
爬取网页后,只需要解析出来即可。我选择的方法是 正则搜索 ,虽然有点笨拙,但好在不管是什么信息,只要想搜索,总可以搜索到。
1. 总体思路 首先 ,获取源码,库:selenium,time ,用 webdriver 搜索按钮和输入栏,提交等等,遇到验证码手动输入即可,笔者输入了 8 次验证码,获取 6000 条论文 其次 ,从源码中解析出作者,时间,Title,下载链接,储存到 Excel 中留存,日后可能有用,用到 re,pandas 再次 ,利用 pandas,读取论文的链接,Title,用 requests 获取论文,利用 open 函数储存到 PDF 格式,在实践中发现,如果直接用解析的链接获取,下载得到的往往是 caj 格式文件,但是把 url 中的 ';' 换为 '&' 就可以正常下载 PDF 格式的文件了。用到 re,pandas 有了总的思路 ,相信各位也可以自己写出定制的爬虫
2. 解析前奏:获取页面的 html from selenium import webdriver import time import pandas as pd 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是我手动打开html,查看输入框源代码找到的,想提交别的条件一样操作即可 blank_ISSN.send_keys( '0577-9154' ) #输入内容,期刊得SSN号码 buttom_search = driver.find_element_by_id( 'btnSearch' ) #找到搜索按钮 buttom_search.click() #点击搜索 time.sleep( 2 ) #停一小会儿 driver.switch_to.default_content() #找到子页面 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 )) #暂停一小会儿,这样封IP的概率会小一点,也少输入几次验证码 button_next = driver.find_element_by_id( 'Page_next' ) button_next.click() except : print( 'Error{}' .format(b)) time.sleep( 60 ) b = b+ 1
3. 解析 一个 tr 标签的结构如下,其包含了一篇文章的全部信息:
在这里插入图片描述 transfer_list=[] #存储html源码的中转列表 for soups in htmls: text = str(soups) for i in soups.find_all(
'tr' )[ 7 : 57 ]: #在soup搜索出来的tr标签中,列表头尾都有冗余信息,删掉不要 transfer_list.append(i) len(htmls) #看一下爬出来多少的html,我的结果是135个html页面 raw_paper_infos = [] #用re匹配的思路是,第一步先缩小范围,第二步,精确搜索并删除多余的字符,下面是第一步 for i in transfer_list: #遍历transfer_list中的每一个tr标签,其结构:[[一个tr标签包含的源码],[].……] o=[] #中转列表,储存第一步搜索出来的title,authors,发布时间,下载链接四个大致的匹配结果 paper = str(i) #下面正则的表达式,都是我自己试出来的,有更好的方法欢迎留言 title = re.findall( 'target="_blank">.*' ,paper) authors = re.findall( 'target="knet">.*' ,paper) pub_year = re.findall( '....-..-..' ,paper) download_url = re.findall( 'briefDl_D" href=".*PDFdown' ,paper) quoted_num1 = re.findall( 'scrollbars=yes.* ,paper) download_num = re.findall( 'onclick="SubCountDownLoad.*' ,paper) o=[title,authors,pub_year,download_url,quoted_num1,download_num] raw_paper_infos.append(o) #初步储存了全部的搜索信息 初步搜索出来的结果如下:
raw_paper_infos[ 7 ] #结构:[[trs],[],……] [[ 'target="_blank">消费行为在个人信用风险识别中的信息含量研究' ], [ 'target="knet">王正位; 周从意 ; 廖理 ; 张伟强 ' ], [ '2020-01-16' ], [ 'briefDl_D" href="../download.aspx?filename=4kXaYNFW0VEa4UzTFZXdJVlSvB3cHdXWrU0cKZ0VXllatB3ZaZVeUdESlxEePJHV3clQuVneGNkQSRXSKdHMvklS6Vzbv9WVwQWaENTdXJ0aOpFd4FzUSRGd3okW0Z1dx90SGljM5JVRwczRTdnSVl3Z3ImMrlVM&tablename=CAPJLAST&dflag=PDFdown' ], [], [ 'onclick="SubCountDownLoad(0,this)">264' ]] 接下来继续完成匹配工作:精确匹配和删除多余字符:
papers = [] #干净的匹配结果存放处 ilegal_word = [ '/' , '\',''' , ':' , '|' , '?' , '*' ] #考虑到后续下载时,保存文件会有一些非法字符导致文件名生成失败(windows不允许这些字符出现在文件名中) for i in raw_paper_infos: if not i == [[], [], [], [], [], []]: #初步搜索时候,会有一些tr标签不是我们的论文标签,不符合初步搜索的要求,其结果就是空列表,过滤掉 raw_title = i[ 0 ][ 0 ].strip( 'target="_blank>~' ) chars = [] for x in raw_title: if not x in ilegal_word: chars.append(x) title2 = '' .join(c for c in
chars) authors2 = ',' .join(j for j in re.findall( '[\u2E80-\u9FFF]+' ,str(i[ 1 ]))) #在join里面加一个符号就可以用这个符号链接加入进来的各个str了,nice try! 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'>.* ,str(i[ 4 ][ 0 ]))[ 0 ].strip( '> )) #被引次数对于发表不久的论文,可能没有这一项,所以对于没有这一项的给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(root+ r'\JJYJ论文信息汇总.xlsx' ) 输出的 Excel 文档长这样:
注 :和代码部分有一点不一样,笔者自行输入了标题行,并且按照发表日期排序
在这里插入图片描述 注意: 下载链接不完整,下载时需要在前面加: http://new.gb.oversea.cnki.net/kns 。
4. 下载论文的代码 import pandas as pd import requests,os content = pd.read_excel(content_JJYJ) #读取excel content = content.drop(columns = [ 'Unnamed: 0' , '作者' , '被引次数' , '下载次数' ,
'截止日期:2020-2-6' , "要下载论文,链接前接:'http://new.gb.oversea.cnki.net/kns'" ]) #只保留title和下载链接,其余删掉 for i in range(len(content[ '题目' ])): #这是DataFrame中列的访问方式 title = content[ '题目' ][i] #第i篇论文的题目 text = requests.get(content[ '下载链接' ][i]) #下载第i个论文 with open(root + '\\' + title + '.PDF' , 'wb' ) as f: #给出保存地址以及open的模式是wb,写入字节 #因为下载的是字节,所以写入字节:wb f.write(text.content) f.close() size = float(os.path.getsize(save_path)) kb = size/ 1024 #判断是不是下载成功了,小于7字节应该就是没下载到论文而是别的东西 if kb< 7 : os.remove(save_path) #如果是,删除,以备后面重新下载 print( '封IP了,暂停10min' ) exceptions.append(paper) time.sleep( 300 ) #下载失败的原因是封ip了,这时候暂停5-10min比较好 下载论文的主体部分就是这些了,后面可以加入 try/except 结构、跳过已经下载的论文等功能,但是程序主体就是这些,文章已经很长,再长不大好,所以写到这里,更多功能请大家依据需求添加。
🍓 课程推荐:连享会:2025政策优化和机制分析专题 嘉宾:杨海生教授,中山大学 时间:2025 年 8 月 20-22 日 地点:东南大学榴园会议中心 (南京市玄武区进香河路38号) 咨询:王老师 18903405450(微信)
连享会微信小店上线啦!
Note:扫一扫进入“连享会微信小店”,你想学的课程在这里······
New! Stata 搜索神器: lianxh 和 songbl GIF 动图介绍 搜: 推文、数据分享、期刊论文、重现代码 …… 👉 安装: . ssc install lianxh . ssc install songbl 👉 使用: . lianxh DID 倍分法 . songbl all
🍏 关于我们
直通车: 👉【 百度一下: 连享会 】即可直达连享会主页。亦可进一步添加 「知乎」,「b 站」,「面板数据」,「公开课」 等关键词细化搜索。