Python-SeleniumWebdriver+googlechrome浏览器爬取中国知。。。
⽬录
前⾔
之前寒假⾥为了发专利,写了⼀篇⽤python+selenium爬取中国知⽹专利的攻略,好家伙这隔了⼏个⽉⽼板⼜让⽤同⼀个主题发会议论⽂了。正好这⾥优化⼀下上次的代码,这次不去专利专区了,就看正常的知⽹检索,爬取⼀下同⼀主题相关的期刊、论⽂。
前⽂指路:
整体思路及环境搭建
整体思路:就我⽂献的思路来看,我会先⽤⼿动检索的⽅式看⼀下某关键词下检索结果的相关度,在确认关键词的有效性后再做⾃动化的⽂献爬取。根据知⽹前端⽹页结构,⽂献的作者、摘要、关键词、发表时间等概述性内容都可以实现⾃动化的爬取与储存。我会在翻阅摘要与关键词内容后再决定要不要回去知⽹下载⽂献(⽂献⼀多还是涉及到了批量下载的问题,也是我下⼀步准备做的代码优化。当然,有个⼈知⽹账户的⼤佬可以⽆视这⼀步直接点批量下载就好)
环境搭建:开发环境的话涉及webdriver、python,python相关包还有IDE的配置,这些我在上篇⽂章⾥都有说,可以看⼀下的第⼀章——使⽤webdriver的注意事项以及第⼆章——开始码代码的“引⼊库”部分。
爬⾍流程
这⼀部分我会讲解代码的各部分功能,并在最后贴上整体代码。此次代码针对的是常规期刊论⽂的爬取,运⾏程序后可直接按控制台的提⽰完成⽂献列表中 [‘⽂献名’, ‘发表时间’, ‘作者 机构’, ‘来源’, ‘摘要’, ‘关键词’, ‘url’] 的爬取,并将结果存储在pycharm 项⽬⽂件夹下的excel⽂件中。
检索部分
需要引⼊的库在此系列的前⽂中已经说过了,⽂章最后也会贴上整体代码。
先来看检索部分,这⾥使⽤webdriver⾃动化操作⽹页实现专业检索模式下的⽂献检索:
driver = webdriver.Chrome()
<('knski/kns8/AdvSearch?dbprefix=SCDB&&crossDbcodes=CJFQ%2CCDMD%2CCIPD%2CCCND%2CCISD%2CSNAD%2CBDZK%2 CCCVD%2CCJFN%2CCCJD')# 这个直接就是⾼级检索的⽹页
# ('cnki')
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')"
js_value ='ElementById("datebox0").value="2010-01-01"'
time.sleep(1)
js2 ="$('input:eq(2)').removeAttr('readonly')"
date_today = time.strftime('%Y-%m-%d')
js_value2 ='ElementById("datebox1").value='+'"'+ date_today +'"'
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)
这⾥除了由前端排布不同导致的元素修改之外,我还做了⼏处优化
1. ⾸先在元素的选择上,我到⼀个偷懒的办法。。在使⽤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]/in put’)
2. 然后就是对⽇历控件的编辑:在⽹页上操作⽇历控件筛选时间范围的时候使⽤的是⼿动点击,⽽在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 =int(results)
num_pages =int(num_results/20)+1
# print(num_pages)
# print(num_results)
# print(type(num_results))
url_list =[]
# 以下为测试代码,抓取⽬标元素存⼊字符串变量
# file = driver.find_element_by_class_name('seq').find_element_by_tag_name('input')
# file_attr = _attribute('value')
# print(file_attr)
# print(type(file_attr))
# print(file)
for j in range(num_pages):
files = driver.find_elements_by_class_name('seq')
k =0
for i in files:
target_str = files[k].find_element_by_tag_name('input').get_attribute('value')
# print(target_str)
# 这⾥的value以“!”分割dbname和filename
dbcode = target_str[0:4]
split_string = target_str.split("!")
dbname = split_string[0]
filename = split_string[1]
url ='knski/kcms/detail/detail.aspx?dbcode='+ dbcode +'&dbname='+ dbname +'&filename='+ filename # print(url)
url_list.append(url)
k +=1
turn_page = driver.find_element_by_class_name('pages').find_elements_by_tag_name('a')[-1]
turn_page.click()
time.sleep(2)
'''
以下循环可以核对抓取到url的准确性
format输出,还挺好使的
'''
# y = 1
# for x in url_list:
# print("{} {}".format(y, x))
# y += 1
这块的代码和上⼀篇⽂章相⽐没有很⼤变动,具体代码解释可以参考我的上⼀篇⽂章,前⾯有指路嗯。
⽂献详情爬取及excel保存
最后⼀部分,使⽤beautifulsoup解析url列表⾥的每⼀篇⽂章,并把所需关键内容存⼊excel中。
# 抓取页⾯详情的信息,存⼊excel
headers ={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36 Edg/ 85.0.564.51'}
wb = openpyxl.Workbook()
sheet = wb.active
sheet.title ='VR——机器⼈控制相关⽂献'
ColumnName =['⽂献名','发表时间','作者机构','来源','摘要','关键词','url']
sheet.append(ColumnName)
for address in url_list:
res = (address, headers=headers)
get_page = ,'html.parser')
append_list =[]
title = get_page.find('h1').text
append_list.append(title)
rows = get_page.find_all('a')
# 瞅⼀眼每个a标签的text都是啥,确认发表时间和来源该⽤哪个a标签
# for z in rows:
# try:
# )
# except:
# print('no text')
# exit()
publish_time = rows[6].text
append_list.append(publish_time)
h3 = get_page.find_all('h3')
# h3标签和上⽂a标签同理
# for z in h3:
# try:
# )
# except:
# print('no text')
author_institute = h3[0].text +' '+ h3[1].text
append_list.append(author_institute)
source = rows[5].text
append_list.append(source)
abstract = get_page.find('span', class_='abstract-text').text
append_list.append(abstract)
# keywords = get_page.find_all('a', {"target": "_blank"})
# keywords = get_page.find('p', class_='keywords')
keywords = get_page.select('p[class="keywords"] > a')
# keywords = get_page.body.div[2].div[1].div[3].div.div.div[5].p.text
# /html/body/div[2]/div[1]/div[3]/div/div/div[5]/p
# print(test)
kw_list =''
for word in keywords:
kw_list += strip()
append_list.append(kw_list)
add = address
append_list.append(add)
sheet.append(append_list)
wb.save('VR控制相关⽂献爬取.xlsx')
wb.close()
⽂献的前端界⾯中,有⼀些元素⽐较难,此次优化的⼀个⽐较关键的点是由beautifulsoup所解析的页⾯中,层级搜索元素的⽅式,⽐如这句话:
keywords = get_page.select(‘p[class=“keywords”] > a’),表⽰的是寻class为keywords的p标签下,a标签的内容。
总结
此次代码的改进可以完成常规类型的⽂献检索和关键内容的爬取储存,这⾥总结⼏个爬⽹页内容的技巧:
1. 在⾃动化⽹页操作过程中,元素最快的⽅法是直接右击复制Xpath
2. 操作控件的过程可通过修改JavaScript实现,⽐如这⾥的⽇历控件
3. 由BeautifulSoup解析的⽹页也能实现嵌套select,可以极⼤提⾼定位精度,降低重复测试的次数
4. 实在不到的标签可以把同名的全print出来看看在第⼏个就完事了
嗯差不多就是这些了,下⼀步(如果还有机会的话),可以⽤通过知⽹校外登录的界⾯实现⽤学校账号登录之后的⾃动化批量下载操作。
完整代码
# -*- coding:utf-8 -*-
import requests
import time
from selenium import webdriver
from bs4 import BeautifulSoup
import openpyxl
# 前序搜索条件的录⼊使⽤webdriver,其实也可以⼿动
'''
优化:校外的账号密码登录没看到⼈机验证
且校内cnki主页进去直接处于登录状态
这⾥需要优化⼀下,后⾯可以⾃动下载了
'''
driver = webdriver.Chrome()
<('knski/kns8/AdvSearch?dbprefix=SCDB&&crossDbcodes=CJFQ%2CCDMD%2CCIPD%2CCCND%2CCISD%2CSNAD%2CBDZK%2 CCCVD%2CCJFN%2CCCJD')# 这个直接就是⾼级检索的⽹页
# ('cnki')js脚本开发
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')"
js_value ='ElementById("datebox0").value="2010-01-01"'
time.sleep(1)
js2 ="$('input:eq(2)').removeAttr('readonly')"
date_today = time.strftime('%Y-%m-%d')
js_value2 ='ElementById("datebox1").value='+'"'+ date_today +'"'
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论