知网页面信息转JSON

把页面上的部分信息抽取成JSON并放入剪切板

Fra og med 27.02.2023. Se den nyeste version.

  1. // ==UserScript==
  2. // @name 知网页面信息转JSON
  3. // @namespace script
  4. // @match https://*.cnki.net/*/*/*?*=**
  5. // @license MIT
  6. // @version 2.2.0
  7. // @author Ade
  8. // @grant GM_notification
  9. // @grant GM_setClipboard
  10. // @require https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.6.0/jquery.min.js
  11. // @description 把页面上的部分信息抽取成JSON并放入剪切板
  12. // ==/UserScript==
  13. initButton();
  14. /** 创建按钮 */
  15. function initButton() {
  16. $(".wrapper").append("<button class='cjwk_btn cjwk_btn_arr'>复制全部</button>");
  17. const _all_btn = `
  18. <button class='cjwk_btn cjwk_btn_all_title'>复制标题、副标题</button>
  19. <button class='cjwk_btn cjwk_btn_all_abstract'>复制摘要</button>
  20. <button class='cjwk_btn cjwk_btn_all_keyword'>复制关键词</button>
  21. <button class='cjwk_btn cjwk_btn_all_fund'>复制基金</button>
  22. <button class='cjwk_btn cjwk_btn_all_classNumber'>复制分类号</button>
  23. `
  24. // $("#ChDivSummary").next().append("<button class='cjwk_btn cjwk_btn_jc' title='插件更新时间:2022-05-31'>复制基础数据(标题、副标题、摘要、关键词、基金、专辑、专题、分类号)</button>");
  25. $("#ChDivSummary").next().append(`<div class="cjwk_all_btn_warp">${_all_btn}</div>`);
  26. $(".brief #authorpart").append("<button class='cjwk_btn cjwk_btn_zzdw'>复制作者单位</button>");
  27. $("#left_part").after("<button class='cjwk_btn cjwk_btn_ml'>复制目录</button>");
  28. //$("#zqfilelist").prev().children().append("<button class='cjwk_btn cjwk_btn_flh'>复制分类号</button>");
  29. $('.cjwk_btn').css({
  30. "background-color": "#f98c51",
  31. "display": "inline-block",
  32. "height": "32px",
  33. "width": "auto",
  34. "padding": "0 10px",
  35. "font-size": "14px",
  36. "text-indent": "0",
  37. "text-align": "center",
  38. "color": "#fff",
  39. "line-height": "32px",
  40. "font-family": "Microsoft Yahei,serif",
  41. "border-radius": "4px",
  42. "overflow": "visible",
  43. });
  44. $(".cjwk_btn_arr").css({
  45. "position": "fixed",
  46. "top": "100px",
  47. "right": "2%",
  48. "z-index": "99",
  49. });
  50. $(".cjwk_all_btn_warp").css({
  51. "display": "fixe",
  52. });
  53. $(".cjwk_all_btn_warp button").css({
  54. "margin-right": "5px",
  55. });
  56. }
  57. let items = [];
  58. let data = {};
  59. //全部数据
  60. $('.cjwk_btn_arr').on("click", function () {
  61. setAllData()
  62. });
  63. //基础数据
  64. $('.cjwk_btn_jc').on("click", function () {
  65. setJichuData()
  66. });
  67. //作者单位
  68. $('.cjwk_btn_zzdw').on("click", function () {
  69. setAuthorsUnitData()
  70. });
  71. //文章目录
  72. $('.cjwk_btn_ml').on("click", function () {
  73. setCatalogueData()
  74. });
  75.  
  76. // begin-------------------新拆分(原基础数据)-------------------
  77. //复制标题、副标题
  78. $('.cjwk_btn_all_title').on("click", function () {
  79. setJichuData(1)
  80. });
  81.  
  82. //复制摘要
  83. $('.cjwk_btn_all_abstract').on("click", function () {
  84. setJichuData(2)
  85. });
  86. //复制关键词
  87. $('.cjwk_btn_all_keyword').on("click", function () {
  88. setJichuData(3)
  89. });
  90. //复制基金
  91. $('.cjwk_btn_all_fund').on("click", function () {
  92. setJichuData(4)
  93. });
  94. //复制分类号
  95. $('.cjwk_btn_all_classNumber').on("click", function () {
  96. setJichuData()
  97. });
  98. // //复制副标题
  99. // $('.cjwk_btn_all_subTitle').on("click", function () {
  100. // setJichuData()
  101. // });
  102. // //复制专辑
  103. // $('.cjwk_btn_all_collection').on("click", function () {
  104. // setJichuData()
  105. // });
  106. // //复制专题
  107. // $('.cjwk_btn_all_special').on("click", function () {
  108. // setJichuData()
  109. // });
  110.  
  111. // end-------------------新拆分-------------------
  112.  
  113.  
  114. //----获取全部数据----
  115. function setAllData() {
  116. data.data = {};
  117. // 获取标题
  118. data.data.articles = {};
  119. let _title = $(".wx-tit>h1").text().trim();
  120. let _index = _title.indexOf("——");
  121. if (_index > 0) {
  122. let _subtitle = _title.substr(_index + 2, _title.length)
  123. data.data.articles.subTitle = _subtitle;
  124. }
  125. data.data.articles.title = _title;
  126. // 获取作者及单位
  127. data.data.articlesAuthors = getAuthors();
  128.  
  129. // 获取摘要
  130. data.data.articles.summary = $("#ChDivSummary").text();
  131.  
  132. // 获取关键词
  133. data.data.articles.keywords = getKeywords();
  134.  
  135. // 获取基金项目
  136. data.data.articles.fund = handleStr($(".funds").text()).replace(/[;。]\s*$/g, "");;
  137.  
  138. // 获取分类号
  139. //data.data.clcs = getClc(); //因为复制数据没解析出来准确,要求注释
  140.  
  141. // 获取目录
  142. data.data.menus = getMenus();
  143. GM_setClipboard(JSON.stringify(data), 'text');
  144. alert('全部信息获取成功,已复制')
  145. }
  146. //----获取基础数据----
  147. function setJichuData(type) {
  148. data.data = {};
  149. data.data.articles = {};
  150. let _alert = '分类号';
  151. let _title,_index,_subtitle
  152. switch (type) {
  153. case 1:
  154. // 获取标题、副标题
  155. _title = $(".wx-tit>h1").text().trim();
  156. _index = _title.indexOf("——");
  157. if (_index > 0) {
  158. _subtitle = _title.substr(_index + 2, _title.length)
  159. data.data.articles.subTitle = _subtitle;
  160. }
  161. data.data.articles.title = _title;
  162. _alert = '标题、副标题';
  163. break;
  164. case 2:
  165. // 获取摘要
  166. data.data.articles.summary = $("#ChDivSummary").text();
  167. _alert = '摘要';
  168. break;
  169. case 3:
  170. // 获取关键词
  171. data.data.articles.keywords = getKeywords();
  172. _alert = '关键词';
  173. break;
  174. case 4:
  175. // 获取基金项目
  176. data.data.articles.fund = handleStr($(".funds").text()).replace(/[;。]\s*$/g, "");;
  177. _alert = '基金项目';
  178. break;
  179. default:
  180. // 获取分类号
  181. data.data.clcs = getClc();
  182. }
  183. GM_setClipboard(JSON.stringify(data), 'text');
  184.  
  185. alert(_alert+'数据获取成功,已复制')
  186.  
  187. }
  188. //----获取目录数据----
  189. function setCatalogueData() {
  190. data.data = {};
  191. data.data.menus = {}
  192. // 获取目录
  193. data.data.menus = getMenus();
  194. GM_setClipboard(JSON.stringify(data), 'text');
  195. alert('目录获取成功,已复制')
  196.  
  197. }
  198. //----获取作者单位数据----
  199. function setAuthorsUnitData() {
  200. data.data = {};
  201. data.data.articlesAuthors = {}
  202. // 获取作者及单位
  203. data.data.articlesAuthors = getAuthors();
  204. GM_setClipboard(JSON.stringify(data), 'text');
  205. alert('作者单位获取成功,已复制')
  206.  
  207. }
  208.  
  209.  
  210. /** 删除空格,并替换分号 */
  211. function handleStr(str) {
  212. return str.replace(/\s+/mg, "").replace(/;/mg, ";");
  213. };
  214.  
  215. /** 获取关键词 */
  216. function getKeywords() {
  217. let keywords = handleStr($(".keywords").text());
  218. if (keywords.endsWith(";")) {
  219. return keywords.slice(0, keywords.length - 1);
  220. }
  221. }
  222.  
  223. /** 来自wf的目录解析 */
  224. function parseMenu(str) {
  225. console.log(str)
  226. let arr = str.split(/[\r\n]+/);
  227. let result = [];
  228. let result_ = [];
  229. let isNew = false;
  230. let name = "";
  231. let children = [];
  232. let $level1_key = 0;
  233.  
  234. for (let i = 0, len_i = arr.length; i < len_i; i++) {
  235. let line = arr[i];
  236. //非空白行才进
  237. if (/\S/.test(line)) {
  238. //一级菜单
  239. if (/^\S/.test(line)) {
  240. $level1_key = i;
  241. result[$level1_key] = {
  242. text: line,
  243. children: [],
  244. };
  245. }
  246.  
  247. //二级菜单
  248. if (/^\s/.test(line) && result[$level1_key]) {
  249. result[$level1_key]["children"].push({
  250. text: line.trim(),
  251. children: [],
  252. });
  253. }
  254. }
  255. }
  256.  
  257. for (let i = 0, len_i = result.length; i < len_i; i++) {
  258. if (result[i] !== undefined) {
  259. result_.push(result[i]);
  260. }
  261. }
  262. return result_;
  263. }
  264.  
  265. /** 获取目录 */
  266. function getMenus() {
  267. let mns = $(".catalog-list>li");
  268. let res = "";
  269. for (let index = 0; index < mns.length; index++) {
  270. const element = mns[index];
  271. let eleText = $(element).text(),_eleText='';//去掉自带空格的目录,程序统一加空格
  272. // if(!/^\s*(\d+\s*\.\s*){2,}\d+\s*/im.test($(element).text())){//剔除三级目录
  273. eleText = eleText?.replace(/^(\s*\d+(?:\.\d+)?)\s*([^\r\n]+)/img, "$1 $2");//数字和标题之间加空格
  274. // }
  275. res += eleText + "\r\n";
  276. }
  277. return parseMenu(res);
  278. }
  279.  
  280. /** 获取分类号 */
  281. function getClc() {
  282. let rows = $(".top-space>.rowtit");
  283. var clcreg = /^分类号[::]/m;
  284. let clcCode = "";
  285. for (let index = 0; index < rows.length; index++) {
  286. const element = rows[index];
  287. let eleText = $(element).text();
  288. if (clcreg.test(eleText)) {
  289. clcCode = $(element).parent().find("p").text();
  290. break;
  291. }
  292. }
  293. let res = [];
  294. res.push({
  295. "clcCode": clcCode
  296. });
  297. return res;
  298. }
  299. /** 来自xjd的获取作者单位 */
  300. class Getunits {
  301. constructor() {
  302. this.string = $('.wx-tit h3:last-child')
  303. this.qukg = /\s+/mg, ''
  304. this.tihuan = /\d+\.(\S+?)(?=\d+\.|$)/mg
  305. this._arr = []
  306. this._praent = this.string.text().trim().length
  307. this._chiild = this.string.children().text().trim().length
  308. }
  309. getUnits_1() {//只有单个字符且没有编号的单位
  310. let _string = this.string.text().trim();
  311. //return [_string] ;
  312. let authorpart = $("#authorpart>span").length,_authorpart = [];
  313. if(authorpart>1){ //多个作者
  314. for(let i = 0;i<authorpart;i++){
  315. _authorpart.push(_string)
  316. }
  317. }else{ //一个作者
  318. _authorpart.push(_string);
  319. }
  320. return _authorpart
  321. }
  322. getUnits_2() { //单位有编号但首行编号(没有标签包裹)的单位
  323. this._arr = []
  324. let _string = this.string.text().replace(this.qukg);
  325. if (_string.indexOf('1')) {
  326. this._arr.push(_string)
  327. }
  328. // let _reg = /\d+\.(\S+?)(?=\d+\.|$)/mg;
  329. let match = this.tihuan.exec(_string);
  330. while (match != null) {
  331. this._arr.push(match[0].trim().replace(/undefined/g, ''))
  332. match = this.tihuan.exec(_string)
  333. }
  334. return this._arr;
  335. }
  336. getUnits_3() { //单位没有编号都是标签包裹纯文本
  337. this._arr = []
  338. let _string_1 = this.string.children()
  339. for (let i = 0; i < _string_1.length; i++) {
  340. let _text = _string_1[i].innerText
  341. this._arr.push(_text.trim())
  342. }
  343. return this._arr;
  344. }
  345. strType() {//枚举字符串可能出现的问题
  346. // let _praent = this.string.text().length
  347. // let _chiild = this.string.children().text().length
  348. if (this.string.children().length == 1) {//没有编号且只有一个单位
  349. return this.getUnits_1()
  350. }
  351. if (this._praent > this._chiild) {//单位有编号但首行编号(没有标签包裹)的单位
  352. return this.getUnits_2()
  353. }
  354. if (this._praent === this._chiild) {//单位没有编号都是标签包裹纯文本
  355. return this.getUnits_3()
  356. }
  357. }
  358. }
  359. let _data = new Getunits();
  360.  
  361. /** 获取作者及单位信息 */
  362. function getAuthors() {
  363. // 获取单位信息放入map
  364. let compsText;
  365. let comps = new Map();
  366. let comp = _data.strType();
  367. for (let index = 0; index < comp.length; index++) {
  368. const eleText = comp[index];
  369. let compMatch = eleText.match(/^(\d+)\s*\.\s*(.+)/m);
  370. if (compMatch != null) {
  371. comps.set(compMatch[1], compMatch[2]);
  372. } else {
  373. compsText = eleText;
  374. }
  375. }
  376. // 获取作者信息,遍历放入结果集,
  377. let authors = [];
  378. let a = $("#authorpart>span");
  379. for (let index = 0; index < a.length; index++) {
  380. const element = a[index].firstChild;//去掉Email数据带来的影响
  381. let eleText = $(element).text();
  382. let authorMatch = eleText.match(/^(\D+)([\d,]+)/m);
  383. if (authorMatch != null) {
  384. let a1 = authorMatch[1];
  385. let a2 = authorMatch[2];
  386. if (a2.indexOf(",") > -1) {
  387. // 有分组
  388. let a2s = a2.split(",");
  389. for (let a2sindex = 0; a2sindex < a2s.length; a2sindex++) {
  390. const a2sele = a2s[a2sindex];
  391. authors.push({
  392. authorName: a1,
  393. unitsName: comps.get(a2sele)
  394. })
  395. }
  396. } else {
  397. authors.push({
  398. authorName: a1,
  399. unitsName: comps.get(a2)
  400. })
  401. }
  402. } else {
  403. authors.push({
  404. authorName: eleText,
  405. unitsName: compsText
  406. })
  407. }
  408. }
  409. return authors;
  410. }
  411.  
  412. //-------------------------------------------------------------------------------------更新日志-------------------------------------------------------------------------------------
  413.  
  414. // date |-| author |-| versions |-| describe
  415.  
  416. //2022-05-31 xjd 2.0 代码基础优化,有待深入优化(添加单个数据源获取)
  417. //2022-05-31 xjd 2.0.1 修改点击复制弹窗两次bug
  418. //2022-05-31 xjd 2.0.2 修改更多摘要覆盖基础按钮bug
  419. //2022-06-1 xjd 2.0.5 添加副标题
  420. //2022-06-02 xjd 2.0.6 修改副标题bug
  421. //2022-06-06 xjd 2.0.7 隐藏插件
  422. //2022-07-18 xjd 2.1.0 将基础数据拆分为多个按钮5个
  423. //2022-11-09 xjd 2.1.1 修复插件地址匹配问题
  424. //2023-02-09 xjd 2.1.3 复制数据没解析出来准确,要求注释获取分类号
  425. //2023-02-16 xjd 2.1.4 复制的知网基金项目内容,去掉最后一个分号;和句号。
  426. //2023-02-20 xjd 2.1.7 1、修复作者后台邮箱数据带来的影响(多个作者一个单位,最后一个作者没绑定单位),2、目录的数字和标题之间加空格