本文作者:左从江(投稿)
文字编辑:钱梦璇
总思路
首先,获取源码,涉及库:selenium,time。通过webdriver搜索按钮和输入栏,通常用requests无法获得包含论文信息的源码,其原因是知网的查询页面嵌套了一个子页面(iframe),requests请求得到的只是父页面。
其次,从源码中解析出作者、时间、Title以及下载链接,并储存到Excel中留存,其中涉及库re和pandas.
获取网页源码
from selenium import webdriverimport timeimport pandas as pdfrom bs4 import BeautifulSoupimport randomurl = 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 = 1while 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'))#被引次数对于发表不久的论文,可能没有这一项的数据,因此对于匹配不到的赋值0download_num2 = int(re.findall(r'>.*<',i[5][0])[0].strip('><')) #论文得下载次数papers.append([title2,authors2,pub_year2,download_url2,quoted_num2,download_num2])
到此为止,我们有了全部所需要的论文信息。
#储存到excelpd.DataFrame(papers).to_excel(r'.\JJYJ论文信息汇总.xlsx')
上述结果的Excel截图:
(注:和代码部分略有不同,笔者自行输入了标题行,并且按照发表日期排序)

注意:如上图所示,Excel表中的下载链接是不完整的,下载时需要在前面加上:http://new.gb.oversea.cnki.net/kns.
到此为止,就得到了每篇文章的信息,可利用request库请求链接,下载论文,利用open函数储存到pdf格式。在实践中发现,如果直接用解析的链接获取,下载得到的往往是caj格式文件,但是把链接中的“;”换为“&”就可以正常下载pdf格式的文件了。
NBA球员薪资分析——基于随机森林算法(二)
1)必须原创,禁止抄袭;
2)必须准确,详细,有例子,有截图;
注意事项:
1)所有投稿都会经过本公众号运营团队成员的审核,审核通过才可录用,一经录用,会在该推文里为作者署名,并有赏金分成。
2)邮件请注明投稿,邮件名称为“投稿+推文名称”。
3)应广大读者要求,现开通有偿问答服务,如果大家遇到有关数据处理、分析等问题,可以在公众号中提出,只需支付少量赏金,我们会在后期的推文里给予解答。

