前言
之前寒假里为了发专利,写了一篇用python+selenium爬取中国知网专利的攻略,好家伙这隔了几个月老板又让用同一个主题发会议论文了。正好这里优化一下上次的代码,这次不去专利专区了,就看正常的知网检索,爬取一下同一主题相关的期刊、论文。
前文指路:Python-Selenium Webdriver+google chrome浏览器爬取中国知网的文献概述
整体思路及环境搭建
整体思路:就我找文献的思路来看,我会先用手动检索的方式看一下某关键词下检索结果的相关度,在确认关键词的有效性后再做自动化的文献爬取。根据知网前端网页结构,文献的作者、摘要、关键词、发表时间等概述性内容都可以实现自动化的爬取与储存。我会在翻阅摘要与关键词内容后再决定要不要回去知网下载文献(文献一多还是涉及到了批量下载的问题,也是我下一步准备做的代码优化。当然,有个人知网账户的大佬可以无视这一步直接点批量下载就好)
环境搭建:开发环境的话涉及webdriver、python,python相关包还有IDE的配置,这些我在上篇文章里都有说,可以看一下Python-Selenium Webdriver+google chrome浏览器爬取中国知网的文献概述的第一章——使用webdriver的注意事项以及第二章——开始码代码的“引入库”部分。
爬虫流程
这一部分我会讲解代码的各部分功能,并在最后贴上整体代码。此次代码针对的是常规期刊论文的爬取,运行程序后可直接按控制台的提示完成文献列表中 [‘文献名’, ‘发表时间’, ‘作者 机构’, ‘来源’, ‘摘要’, ‘关键词’, ‘url’] 的爬取,并将结果存储在pycharm项目文件夹下的excel文件中。
检索部分
需要引入的库在此系列的前文中已经说过了,文章最后也会贴上整体代码。
先来看检索部分,这里使用webdriver自动化操作网页实现专业检索模式下的文献检索:
driver = webdriver.Chrome()
driver.get('https://kns.cnki.net/kns8/AdvSearch?dbprefix=SCDB&&crossDbcodes=CJFQ%2CCDMD%2CCIPD%2CCCND%2CCISD%2CSNAD%2CBDZK%2CCCVD%2CCJFN%2CCCJD') # 这个直接就是高级检索的网页
# driver.get('https://cnki.net')
time.sleep(2)
# advanced_search = driver.find_element_by_class_name('btn-grade-search')
# advanced_search.click() # 跳转进入高级检索,后期可维护
# time.sleep(1)
major_search = driver.find_element_by_name('majorSearch')
major_search.click() # 跳转进入专业检索,后期可维护
time.sleep(1)
# 输入检索语句,后期可维护
input_key_words = driver.find_element_by_class_name('search-middle').find_element_by_tag_name('textarea')
key_words = input("输入检索语句:")
input_key_words.send_keys(key_words)
'''
勾一些checkbox
Xpath选中元素右键复制就行,这里勾一下同义词扩展
'''
check_something = driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div/div[1]/div[1]/div[2]/div[1]/div[1]/span[3]/label[2]/input')
check_something.click()
'''
时间范围的选择——通过修改js脚本:
移除控件的只读属性
然后直接把日期赋值给日历框
'''
js = "$('input:eq(1)').removeAttr('readonly')"
driver.execute_script(js)
js_value = 'document.getElementById("datebox0").value="2010-01-01"'
driver.execute_script(js_value)
time.sleep(1)
js2 = "$('input:eq(2)').removeAttr('readonly')"
driver.execute_script(js2)
date_today = time.strftime('%Y-%m-%d')
js_value2 = 'document.getElementById("datebox1").value=' + '"' + date_today + '"'
driver.execute_script(js_value2)
time.sleep(1)
search_button = driver.find_element_by_class_name('search-buttons').find_element_by_tag_name('input')
search_button.click()
time.sleep(2)
这里除了由前端排布不同导致的元素修改之外,我还做了几处优化
- 首先在元素的选择上,我找到一个偷懒的办法。。在使用F12打开谷歌浏览器的开发者模式后,可以直接右击元素对应的标签来复制它的Xpath, 黏贴到python中后直接使用find_element_by_xpath去找它就行,对应代码块里那句话是check_something = driver.find_element_by_xpath(’/html/body/div[2]/div/div[2]/div/div[1]/div[1]/div[2]/div[1]/div[1]/span[3]/label[2]/input’)
- 然后就是对日历控件的编辑:在网页上操作日历控件筛选时间范围的时候使用的是手动点击,而在webdriver中我采用的使用的是修改js脚本的方式,取消控件的只读属性,然后直接将想要的日期input进去,对应的代码找那个修改js脚本的注释就行了。我的代码里时间范围是2010-01-01到运行脚本当天的日期(用import time可以调用方法,用一定格式取到当日日期)。
URL批量爬取
检索完之后,需要整合每篇文献的url到列表里,这是文献详情爬取的前置步骤,具体的url编辑方式需要观察不同网站的url组合方式,中国知网的话用的是dbcode, dbname, filename三个关键词以“&”符号连接,比如:基于运动约束的移动机器人路径规划,正常后面还会有个v关键词带着一串乱码,我猜测是版本代号之类的,但这个不加入也能搜到目标文章。看下代码:
# 现在开始抓取每篇文献的url
results = driver.find_element_by_class_name('pagerTitleCell').find_element_by_tag_name('em').text
num_results =