Python爬虫,批量获取知网文献信息

一、前言

最近临近毕业,写毕业论文需要从知网查找大量的文献。但去知网一条一条进去看摘要又略显麻烦和浪费时间。于是,反手写一个爬虫,批量获取基本信息,岂不美哉?

在开始这个项目之前,我抱着不重复造轮子的心态,寻思着去Github先找找。结果发现基本上都是几年前的项目,现在早已不能使用。最后证实了,靠别人不如靠自己,撸起袖子就开干!

1. 爬虫基础

网络爬虫就是模拟浏览器发送网络请求,接收请求响应,一种按照一定的规则,自动地抓取互联网信息的程序。
目前爬虫主要分为以 requests 库为代表的模拟请求类爬虫和以 selenium 为代表的模拟浏览器用户行为的爬虫两类。:

  • Requests 是用Python语言编写,基于 urllib,采用 Apache2 Licensed 开源协议的 HTTP 库。它比 urllib 更加方便,可以节约我们大量的工作,完全满足 HTTP 测试需求。Requests 的哲学是以 PEP 20 的习语为中心开发的,所以它比 urllib 更加 Pythoner。

  • Selenium 是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE,Mozilla Firefox,Safari,Google Chrome,Opera等。

中国知网作为国内最知名的文献数据库之一,有着复杂的反爬虫机制,包括:动态JS、iframe、验证码等等。直接模拟请求难度较大,且容易被封IP地址,所以本文主要介绍如何使用Selenium来爬取知网。

2. Selenium基本用法

  • *声明浏览器对象

Selenium支持非常多的浏览器,如Chrome、Firefox、Edge等,我们只要首先下载好相应浏览器的webdriver到python主目录中,或者加入环境变量即可。

不同浏览器的初始化:

from selenium import webdriver

browser = webdriver.Chrome()
browser = webdriver.Firefox()
browser = webdriver.Edge()
browser = webdriver.Safari()
  • *访问页面

我们可以用get()方法来请求一个网页,传入参数链接URL

browser.get('https://www.bing.com')
  • *查找元素
find_element_by_id()
find_element_by_name()
find_element_by_class_name()
find_element_by_tag_name()
find_element_by_link_text()
find_element_by_partial_link_text()
find_element_by_xpath()
find_element_by_css_selector()

在element变成elements就是找所有满足的条件,返回数组。
另外,我经常使用的查找元素方法为selenium中selenium.webdriver.common.by的By, 联合隐士等待EC
用法如下:

# 单个元素
WebDriverWait( driver, 10 ).until( EC.presence_of_element_located((By.XPATH ,"") ) )
# 多个元素
WebDriverWait( driver, 10 ).until( EC.presence_of_all_elements_located( (By.CLASS_NAME  ,"fz14") ) )

# 元素类型有:
CLASS_NAME = 'class name'
CSS_SELECTOR = 'css selector'
ID = 'id'
LINK_TEXT = 'link text'
NAME = 'name'
PARTIAL_LINK_TEXT = 'partial link text'
TAG_NAME = 'tag name'
XPATH = 'xpath'
  • *常用方法

在找到相应元素位置后,我们常用的交互动作包括:点击、输入、清楚、获取属性、获取文本等

element = find_element_by_id(''id)

element.send_keys('Hello')  # 传入Hello
element.clear()  # 清除输入框
element.click()  # 点击元素
element.text  # 获取元素文本信息
element.get_attribute('href')  # 获取元素属性

还有大量的方法这里没有提及,不过有了以上基本知识,我们就可以开始项目了!

二、知网爬虫实战

1. 知网页面元素分析

知网首页中,我们仅需要先在输入框中键入主题词,然后点击搜索图标,即可跳转到结果页面。

Python爬虫,批量获取知网文献信息

我们通过浏览器的检查页面,得到输入框和搜索图标的XPATH分别为:

input_xpath = '/html[1]/body[1]/div[1]/div[2]/div[1]/div[1]/input[1]'
button_xpath =  '/html[1]/body[1]/div[1]/div[2]/div[1]/div[1]/input[2]'

只需要在输入框键入我们要搜索的主题,然后操作搜索按钮即可转到结果页。以搜索Python为例,结果页如下所示,共找到15,925条,300页。每页中包含20个条目,每个条目包含题目、作者、来源等信息。

Python爬虫,批量获取知网文献信息

通过对当前页面分析,发现每个条目对应的的xpath的规律。

/html[1]/body[1]/div[5]/div[2]/div[2]/div[2]/form[1]/div[1]/table[1]/tbody[1]/tr[1]/td[2]

即倒数第二个标签数字代表本页的第几个条目,最后一个标签 2 – 6 分别代表题目、作者、来源、发表时间和数据库。

在当前页面无法或者文献的摘要信息,下载链接等等,需要进一步点击进入相关文献条目。

进入详情页面后,我们根据class name:abstract-text 能够很容易定位到摘要的文本,class name: btn-dlcaj 定位到下载链接,其他元素同理。

Python爬虫,批量获取知网文献信息
完成以上知网页面的分析后,我们就可以根据需求开始写代码了!

2. 代码示例

  • *引用所需要的库
import time
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from urllib.parse import urljoin
  • *创建浏览器对象

这里我们创建一个Chrome浏览器的窗口,并设置相关参数:

#get直接返回,不再等待界面加载完成
desired_capabilities = DesiredCapabilities.CHROME
desired_capabilities["pageLoadStrategy"] = "none"

# 设置谷歌驱动器的环境
options = webdriver.ChromeOptions()
# 设置chrome不加载图片,提高速度
options.add_experimental_option("prefs", {"profile.managed_default_content_settings.images": 2})
# 设置不显示窗口
#options.add_argument('--headless')
# 创建一个谷歌驱动器
driver = webdriver.Chrome(options=options)
# 设置搜索主题
theme = "Python"
# 设置所需篇数
papers_need = 100

  • *打开页面并搜索关键词
# 打开页面
driver.get("https://www.cnki.net")
# 传入关键字
WebDriverWait( driver, 100 ).until( EC.presence_of_element_located( (By.XPATH ,'''//*[@id="txt_SearchText"]''') ) ).send_keys(theme)
# 点击搜索
WebDriverWait( driver, 100 ).until( EC.presence_of_element_located( (By.XPATH ,"/html/body/div[1]/div[2]/div/div[1]/input[2]") ) ).click()
time.sleep(3)

# 点击切换中文文献
WebDriverWait( driver, 100 ).until( EC.presence_of_element_located( (By.XPATH ,"/html/body/div[5]/div[1]/div/div/div/a[1]") ) ).click()
time.sleep(1)
# 获取总文献数和页数
res_unm = WebDriverWait( driver, 100 ).until( EC.presence_of_element_located( (By.XPATH ,"/html/body/div[5]/div[2]/div[2]/div[2]/form/div/div[1]/div[1]/span[1]/em") ) ).text
# 去除千分位里的逗号
res_unm = int(res_unm.replace(",",''))
page_unm = int(res_unm/20) + 1
print(f"共找到 {res_unm} 条结果, {page_unm} 页。")
  • *解析结果页
# 赋值序号, 控制爬取的文章数量
count = 1
# 当,爬取数量小于需求时,循环网页页码
while count <= 10 papers_need: # 等待加载完全,休眠3s time.sleep(3) title_list="WebDriverWait(" driver, ).until( ec.presence_of_all_elements_located( (by.class_name ,"fz14") ) 循环网页一页中的条目 for i in range(len(title_list)): try: term="count%20" 本页的第几个条目 title_xpath="f"/html[1]/body[1]/div[5]/div[2]/div[2]/div[2]/form[1]/div[1]/table[1]/tbody[1]/tr[{term}]/td[2]"" author_xpath="f"/html[1]/body[1]/div[5]/div[2]/div[2]/div[2]/form[1]/div[1]/table[1]/tbody[1]/tr[{term}]/td[3]"" source_xpath="f"/html[1]/body[1]/div[5]/div[2]/div[2]/div[2]/form[1]/div[1]/table[1]/tbody[1]/tr[{term}]/td[4]"" date_xpath="f"/html[1]/body[1]/div[5]/div[2]/div[2]/div[2]/form[1]/div[1]/table[1]/tbody[1]/tr[{term}]/td[5]"" database_xpath="f"/html[1]/body[1]/div[5]/div[2]/div[2]/div[2]/form[1]/div[1]/table[1]/tbody[1]/tr[{term}]/td[6]"" title="WebDriverWait(" ec.presence_of_element_located((by.xpath ,title_xpath) ).text authors="WebDriverWait(" ,author_xpath) source="WebDriverWait(" ,source_xpath) date="WebDriverWait(" ,date_xpath) database="WebDriverWait(" ,database_xpath) 点击条目 title_list[i].click() 获取driver的句柄 n="driver.window_handles" driver切换至最新生产的页面 driver.switch_to_window(n[-1]) 开始获取页面信息 ," html body div[2] div[1] div[3] div h1") h3[1]") institute="WebDriverWait(" html[1] body[1] h3[2]") abstract="WebDriverWait(" ec.presence_of_element_located((by.class_name ,"abstract-text") keywords="WebDriverWait(" ,"keywords") ).text[:-1] except: url="driver.current_url" 获取下载链接 link="WebDriverWait(" ec.presence_of_all_elements_located((by.class_name ,"btn-dlcaj") )[0].get_attribute('href') link) 写入文件 res="f"{count}\t{title}\t{authors}\t{institute}\t{date}\t{source}\t{database}\t{keywords}\t{abstract}\t{url}".replace("\n","")+"\n"" print(res) with open('cnki_res.tsv', 'a', encoding="gbk" as f: f.write(res) print(f" 第{count} 条爬取失败\n") 跳过本条,接着下一个 continue finally: 如果有多个窗口,关闭第二个窗口, 切换回主页 n2="driver.window_handles" if len(n2)> 1:
                driver.close()
                driver.switch_to_window(n2[0])
            # &#x8BA1;&#x6570;,&#x5224;&#x65AD;&#x9700;&#x6C42;&#x662F;&#x5426;&#x8DB3;&#x591F;
            count += 1
            if count == papers_need:break

    # &#x5207;&#x6362;&#x5230;&#x4E0B;&#x4E00;&#x9875;
    WebDriverWait( driver, 10 ).until( EC.presence_of_element_located( (By.XPATH ,"//a[@id='PageNext']") ) ).click()

# &#x5173;&#x95ED;&#x6D4F;&#x89C8;&#x5668;
driver.close()
</=>

至此,所有功能都已实现,代码中写了详细的注释。需要获得完整代码的可以直达我的Github下载,CNKI_Spider.py(https://github.com/byemaxx/BioTools)。

结果展示

结果是一个以制表符分隔的表格文件,其中包含了论文的基本信息,包括:题目、作者、来源、摘要、链接等

Python爬虫,批量获取知网文献信息

三、遇到的一些坑

1. 网页加载太慢导致元素查找出错

有时候我们并不需要网页完全,我们想要的信息已经加载出来,于是加上以下设置:

#get&#x76F4;&#x63A5;&#x8FD4;&#x56DE;&#xFF0C;&#x4E0D;&#x518D;&#x7B49;&#x5F85;&#x754C;&#x9762;&#x52A0;&#x8F7D;&#x5B8C;&#x6210;
desired_capabilities = DesiredCapabilities.CHROME
desired_capabilities["pageLoadStrategy"] = "none"

另一方面,在适当的地方加上 time.sleep(3) 延时几秒,既可以等待页面加载,也可以防止爬取太快被封IP。

2. 编码不同导致的文件写入失败

在写入文件时,由于存在不同的编码,常常导致文件写入失败,在最开始我转换编码为 utf-8 ,后来发现这个编码在excel里面居然是乱码,于是改为 gbk 编码。

with open('CNKI_res.tsv', 'a', encoding='gbk') as f:
  f.write(res)

3. xpath 地址经常发生改变

由于知网中包含着不同类型的文献,如期刊、硕博、会议、专利 等,xpath的位置不是一成不变的,虽然xpath唯一定位的特性便于我们找到相应的标签。但偶尔class name 或许是更好的选择。

四、后记

在数据分析中,往往花费时间的事数据的获取和数据清洗,怎样从互联网海量的数据中高效获取我们想要的部分?无疑网络爬虫是最佳的选择之一。学习好爬虫的相关库的运用,不论是从或联网上获取相关的数据,还是设置某些东东提交任务,甚至是写一些抢票软件都不是什么困难的事情。

另一方面,爬虫与网站的反爬系统一直都是攻防的双方,Selenium 这类软件能够直接模拟浏览器操作,进而绕过一些反爬机制,但并不是不能够被网站识别。在真实的情况中,我们往往需要结合多种手段爬取网页。

在这场爬虫和反爬虫的军备竞赛中;在人与计算机的竞赛中,我们只有不断地学习新的东西,才能在这场进化中不被淘汰。

如果本文对你有帮助,别忘记给我个3连 ,点赞,转发,评论,
关注与私信博主(222)学习更多pytho知识与技巧,课件,源码,安装包,还有最新大厂面试资料等等等
咱们下期见。
收藏 等于白嫖,点赞才是真情。

Python爬虫,批量获取知网文献信息

Original: https://blog.csdn.net/k15778864599/article/details/126976826
Author: 快乐老男孩!
Title: Python爬虫,批量获取知网文献信息



相关阅读

Title: 使用vscode对threejs的本地调试

始终坚信阅读和调试结合的方式,才是学习开源的高效方法

一、老版本调试

遥想当年的threejs(使用版本为r75)还没有CommonJS,对于我这个小白可以拿起大刀大杀四方……(咳。咳。 就是拿来简单画个方块啥的。。。),使用vscode简单配置一下就可以老老实实的拜倒在我的淫威之下。这种小秘籍已经遍地都是,说出来也不怕大家偷学去。

1 准备

vscode + debugger for chrome

2 设置

打开html所在目录后,F5开始调试,选择chrome调试器

使用vscode对threejs的本地调试

生成launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch",
            "type": "chrome",
            "request": "launch",
            "webRoot": "${workspaceFolder}",
            "runtimeExecutable": "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe",
            "file": "${workspaceFolder}/examples/canvas_geometry_birds.html",
            "runtimeArgs":["--allow-file-access-from-files"]
        }
    ]
}

主要设置的内容为 runtimeExecutable,该参数为当前系统chrome浏览器的地址, file为要调试的网页地址;设置完成以后保存,找到要调试的网页,并在javascript段打上断点,然后F5启动调试,小功告成,欲要神功大成,先需。。,你懂的

使用vscode对threejs的本地调试

二、新版本调试

由于今年开始使用导入导出功能,所以就需要进行版本的升级(r113),一跑代码,我去,开不了了,原来新版本已经引入CommonJs的理念,需要在服务端运行。好吧,继续捣鼓吧。

1 准备

vscode + debugger for chrome + nodejs

2 设置

我选择的是使用nodejs作为服务器,nodejs+npm的安装我就不多介绍了,小伙伴们自己找秘籍吧。如果想使用其他方法,建议参考Testing with NPM一文。
在vscode的terminal窗口进行npm的安装操作,建议国内的还是使用cnpm,不然要等到天荒地老。

cnpm install

然后

npm run dev

然后在命令窗口中看到

[HTTP] Starting up http-server, serving ./
[HTTP] Available on:
[HTTP]   http://192.168.1.144:8080
[HTTP]   http://127.0.0.1:8080
[HTTP] Hit CTRL-C to stop the server

ok,现在你的本地服务已经运行起了,可以记载网页进行调试了。

跟老版本的调试差不多,生成launch.json,配置参数略微调试

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "chrome",
            "request": "launch",
            "name": "Launch Chrome",
            "url": "http://localhost:8080/examples/#webgl_animation_cloth",
            "webRoot": "${workspaceFolder}"
        }
    ]
}

将url改成你要访问的文件路径,这里面使用的是路由的方式,注意没有.html。到你要调试的页面断点开始调试吧,祝你好运。

使用vscode对threejs的本地调试

Original: https://www.cnblogs.com/chencarl/p/12367718.html
Author: chencarl
Title: 使用vscode对threejs的本地调试

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/280814/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

最近整理资源【免费获取】:   👉 程序员最新必读书单  | 👏 互联网各方向面试题下载 | ✌️计算机核心资源汇总