序言
场景是在知网高级检索界面中,选择报纸–>点击包含非学术文献–>改成全文模式–>点击检索页发表年度–>获取括号内的数字和对应的年份
需要三个库,都可以用pip install轻松下载,稍微麻烦点儿的是需要去下载个对应版本的chromedriver.exe驱动,放到python或者Anaconda的文件夹目录下,然后添加环境变量(这部分报错了自行百度即可,操作起来不麻烦的)
注意time.sleep()是必要的,一是为了避免频繁操作被浏览器提醒,二是在网络不好的情况下让网页加载完全,否则都会导致报错
一定不要图快,目前我是8s左右完成一次检索和数据录入,老师给我的要求是700次左右,也就运行个一个半个小时
这之中还会遇到诸多问题,在代码的注释里也都写到了
函数模块介绍
创建模拟浏览器对象
def openUrl(url):
driver = webdriver.Chrome()
driver.get(url)
time.sleep(3)
return driver
只需要执行一次的部分
xpath如何获取百度一下即可
def onceClick(driver):
driver.find_element_by_xpath('/html/body/div[3]/div[1]/div/ul[1]/li[4]/a').click()
time.sleep(2)
driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div/div[1]/div[1]/div[2]/div[1]/div[1]/label/input').click()
time.sleep(1)
driver.find_element_by_xpath('//*[@id="gradetxt"]/dd[1]/div[2]/div[1]').click()
time.sleep(2)
driver.find_element_by_xpath('//*[@id="gradetxt"]/dd[1]/div[2]/div[1]/div[2]/ul/li[5]').click()
time.sleep(2)
需要批量执行的重复操作部分
这部分主要是知网页面的交互产生的问题,反复改了好几次终于解决了
第一次检索的时候发表年度页面是关着的 第二次又变成了不关,但是如果要获取更多需要点击最下面的键,因此引入了flag(结合主函数看) try-except是为了防止年份数量不足而报错,因为有些关键词出现得很少,就不需要点击上图这个键,如果不try掉就会报错终止运行
def send_and_click(driver,kw,np,flag):
driver.find_element_by_xpath('//*[@id="gradetxt"]/dd[1]/div[2]/input').send_keys(kw)
time.sleep(0.5)
driver.find_element_by_xpath('//*[@id="gradetxt"]/dd[3]/div[2]/input').send_keys(np)
time.sleep(0.5)
driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div/div[1]/div[1]/div[2]/div[2]/input').click()
time.sleep(1.5)
if flag==True:
driver.find_element_by_xpath('//*[@id="divGroup"]/dl[3]/dt').click()
time.sleep(2)
if flag==False:
try:
driver.find_element_by_xpath('//*[@id="divGroup"]/dl[3]/dd/div/a').click()
time.sleep(1)
except:
pass
driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div/div[2]/a[2]').click()
time.sleep(0.5)
driver.find_element_by_xpath('//*[@id="gradetxt"]/dd[1]/div[2]/input').clear()
driver.find_element_by_xpath('//*[@id="gradetxt"]/dd[3]/div[2]/input').clear()
time.sleep(1)
获取网页数据
这个部分主要还是根据自己的需求来,这边我是返回列表
def getData_and_print(driver,tw,dp):
cntDict={}
for index in range(1,13):
try:
text1=driver.find_element_by_xpath('//*[@id="divGroup"]/dl[3]/dd/div/ul/li['+str(index)+']').text
cntDict[text1[:4]]=text1[5:-1]
except:
continue
for i in years:
if i not in cntDict.keys():
cntDict[i]='0'
cnttuplelist=[]
cntlist=[]
for i in sorted (cntDict,reverse=False):
if int(i)>=2011 and int(i)<=2018:
cnttuplelist.append((i, cntDict[i]))
cntlist.append(cntDict[i])
else:
continue
for ct1,ct2 in cnttuplelist:
print(dp+'\t\t\t'+ct1+'\t'+tw+'\t\t'+ct2)
return cntlist
录入excel
这个部分也是根据自己的需求来,主要是找准数据的录入规则
def load_into_excel(datalist,indexi,indexj):
wb=openpyxl.load_workbook('data.xlsx')
ws=wb['Sheet1']
for i in range(len(datalist)):
ws.cell(row=i+8*indexi+2,column=4+indexj).value=datalist[i]
wb.save("data.xlsx")
主函数
if __name__ =='__main__':
driver=openUrl('https://kns.cnki.net/kns8/AdvSearch?dbprefix=CFLS&&crossDbcodes=CJFQ%2CCDMD%2CCIPD%2CCCND%2CCISD%2CSNAD%2CBDZK%2CCCJD%2CCCVD%2CCJFN')
onceClick(driver)
flag=True
for indexi,dp in enumerate(dailyPapers):
for indexj,tw in enumerate(topicWords):
send_and_click(driver,tw,dp,flag)
flag=False
cntlist=getData_and_print(driver,tw,dp)
load_into_excel(cntlist,indexi,indexj)
driver.close()
本地文件结构
只需要将data.xlsx和代码文件放一起即可,或者用绝对路径也可
data.xlsx要求标题等事先按自己的要求准备好,代码只输入数据
全部代码
from selenium import webdriver
import time
import openpyxl
topicWords=['深化改革','中国梦','放管服']
dailyPapers=['北京日报','天津日报']
years='2022','2021','2020','2019','2018','2017','2016','2015','2014','2013','2012','2011']
def openUrl(url):
driver = webdriver.Chrome()
driver.get(url)
time.sleep(3)
return driver
def onceClick(driver):
driver.find_element_by_xpath('/html/body/div[3]/div[1]/div/ul[1]/li[4]/a').click()
time.sleep(2)
driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div/div[1]/div[1]/div[2]/div[1]/div[1]/label/input').click()
time.sleep(1)
driver.find_element_by_xpath('//*[@id="gradetxt"]/dd[1]/div[2]/div[1]').click()
time.sleep(2)
driver.find_element_by_xpath('//*[@id="gradetxt"]/dd[1]/div[2]/div[1]/div[2]/ul/li[5]').click()
time.sleep(2)
def send_and_click(driver,kw,np,flag):
driver.find_element_by_xpath('//*[@id="gradetxt"]/dd[1]/div[2]/input').send_keys(kw)
time.sleep(0.5)
driver.find_element_by_xpath('//*[@id="gradetxt"]/dd[3]/div[2]/input').send_keys(np)
time.sleep(0.5)
driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div/div[1]/div[1]/div[2]/div[2]/input').click()
time.sleep(1.5)
if flag==True:
driver.find_element_by_xpath('//*[@id="divGroup"]/dl[3]/dt').click()
time.sleep(2)
if flag==False:
try:
driver.find_element_by_xpath('//*[@id="divGroup"]/dl[3]/dd/div/a').click()
time.sleep(1)
except:
pass
driver.find_element_by_xpath('/html/body/div[2]/div/div[2]/div/div[2]/a[2]').click()
time.sleep(0.5)
driver.find_element_by_xpath('//*[@id="gradetxt"]/dd[1]/div[2]/input').clear()
driver.find_element_by_xpath('//*[@id="gradetxt"]/dd[3]/div[2]/input').clear()
time.sleep(1)
def getData_and_print(driver,tw,dp):
cntDict={}
for index in range(1,13):
try:
text1=driver.find_element_by_xpath('//*[@id="divGroup"]/dl[3]/dd/div/ul/li['+str(index)+']').text
cntDict[text1[:4]]=text1[5:-1]
except:
continue
for i in years:
if i not in cntDict.keys():
cntDict[i]='0'
cnttuplelist=[]
cntlist=[]
for i in sorted (cntDict,reverse=False):
if int(i)>=2011 and int(i)<=2018:
cnttuplelist.append((i, cntDict[i]))
cntlist.append(cntDict[i])
else:
continue
for ct1,ct2 in cnttuplelist:
print(dp+'\t\t\t'+ct1+'\t'+tw+'\t\t'+ct2)
return cntlist
def load_into_excel(datalist,indexi,indexj):
wb=openpyxl.load_workbook('data.xlsx')
ws=wb['Sheet1']
for i in range(len(datalist)):
ws.cell(row=i+8*indexi+2,column=4+indexj).value=datalist[i]
wb.save("data.xlsx")
if __name__ =='__main__':
driver=openUrl('https://kns.cnki.net/kns8/AdvSearch?dbprefix=CFLS&&crossDbcodes=CJFQ%2CCDMD%2CCIPD%2CCCND%2CCISD%2CSNAD%2CBDZK%2CCCJD%2CCCVD%2CCJFN')
onceClick(driver)
flag=True
for indexi,dp in enumerate(dailyPapers):
for indexj,tw in enumerate(topicWords):
send_and_click(driver,tw,dp,flag)
flag=False
cntlist=getData_and_print(driver,tw,dp)
load_into_excel(cntlist,indexi,indexj)
driver.close()
结果预览
控制台
文件
|