当前位置:   article > 正文

傻瓜式提取网页数据的油猴脚本(JavaScript 代码)_js 油猴脚本 属性

js 油猴脚本 属性

目录

目录

一、脚本适用范围

二、将脚本配置到浏览器

三、脚本用法

四、脚本原理

五、脚本代码


一、脚本适用范围

脚本适用范围:一次性提取任意网站的布局类似的数据,例如 淘宝的商品价格、微博的热搜标题、必应搜索的图片链接

脚本不适用范围:页面布局不相似的数据。如下图圈出了两种样式的数据,不能一次性提取,需要手动分两次提取。

二、将脚本配置到浏览器

步骤:

(1)浏览器安装Tampermonkey(中文名 油猴、篡改猴)(可参考:油猴(Tampermonkey)安装教程-CSDN博客

(2)将脚本源码(见本文最后一章节)保存到 Tampermonkey (中文名 油猴、篡改猴)中(可参考:)

(3)之后每次打开任意一个网页,浏览器页面右下角会出现三个输入框和一个按键,如下图

三、脚本用法

步骤:

(1)从类似的数据中选择两条,拷贝它们的 xpath 粘贴到脚本生成的前两个输入框中

(2)填入数据对应的标签的属性名称到第三个框中,如果不填,则提取标签体的文本(innerText)

(3)点击提取数据,会出现弹窗,说明运行结果。成功提取出的数据会被拷贝到粘贴板,直接Ctrl+V即可粘贴

四、脚本原理

如果元素样式类似,则它们在HTML源码的标签树路径应该是类似的(xpath路径就是寻找元素的一种方式)。

给定两个xpath:

/html/body/div[1]/div[1]/div[2]/div[3]/div/div/div[14]/div/div/div/div/span[2]/span[1]

/html/body/div[1]/div[1]/div[2]/div[3]/div/div/div[17]/div/div/div/div/span[2]/span[1]

找出它们的数字差异,删除,得到的xpath即可匹配页面中所有类似的元素

/html/body/div[1]/div[1]/div[2]/div[3]/div/div/div/div/div/div/div/span[2]/span[1]

再给出需要提取的数据在标签中对应的属性名称,就可以提取出需要的数据

五、脚本源码

 脚本源码(JavaScript):

  1. // ==UserScript==
  2. // @name 傻瓜式提取网页数据
  3. // @namespace gzp
  4. // @version 0.1
  5. // @description 用XPath与属性名提取数据
  6. // @author gzp
  7. // @match *://*/*
  8. // @grant GM_setClipboard
  9. // @grant GM_setValue
  10. // @grant GM_getValue
  11. // ==/UserScript==
  12. (function () {
  13. 'use strict';
  14. // 给页面添加输入框与按键,并绑定回调函数。clickFunction 为点击按键时的回调函数
  15. function insertElement(clickFunction) {
  16. // 创建 XPath 输入框 1
  17. let xpathInput1 = document.createElement("input");
  18. xpathInput1.setAttribute('type', 'text')
  19. xpathInput1.setAttribute('placeholder', '填写第一个标签的XPath路径')
  20. xpathInput1.setAttribute('id', xpathInputId1)
  21. xpathInput1.style.cssText = 'font-weight: normal; border: 2px solid #5813fe;box-shadow: 0px 0px 12px 0px rgba(98, 19, 254, 0.6); border-radius: 5px; height: 32px;width: 350px;margin: 5px; padding-left: 10px;'
  22. // 创建 XPath 输入框 1
  23. let xpathInput2 = document.createElement("input");
  24. xpathInput2.setAttribute('type', 'text')
  25. xpathInput2.setAttribute('placeholder', '填写第二个标签的XPath路径')
  26. xpathInput2.setAttribute('id', xpathInputId2)
  27. xpathInput2.style.cssText = 'font-weight: normal; border: 2px solid #5813fe;box-shadow: 0px 0px 12px 0px rgba(98, 19, 254, 0.6); border-radius: 5px; height: 32px;width: 350px;margin: 5px; padding-left: 10px;'
  28. // 创建 需要提取的属性名称
  29. let attributeInput = document.createElement("input");
  30. attributeInput.setAttribute('type', 'text')
  31. attributeInput.setAttribute('placeholder', '输入需要的属性名称(不输入时提取标签内文本)')
  32. attributeInput.setAttribute('id', attributeInputId)
  33. attributeInput.style.cssText = 'font-weight: normal; border: 2px solid #5813fe;box-shadow: 0px 0px 12px 0px rgba(98, 19, 254, 0.6); border-radius: 5px; height: 32px;width: 350px;margin: 5px; padding-left: 10px;'
  34. // 创建 按键
  35. let extractButton = document.createElement('button')
  36. extractButton.setAttribute('id', 'extractButton')
  37. extractButton.textContent = '提取数据'
  38. extractButton.style.cssText = 'background-color: #4CAF50; border: none; color: white; margin: 5px; text-align: center; text-decoration: none; display: inline-block; font-size: 16px;border-radius: 5px; height: 32px;padding-left: 5px;'
  39. extractButton.onclick = clickFunction // 绑定回调函数
  40. // 添加上述几个元素到到一个位置固定的 div 中
  41. let div = document.createElement('div')
  42. div.appendChild(xpathInput1)
  43. div.appendChild(document.createElement('br'))
  44. div.appendChild(xpathInput2)
  45. div.appendChild(document.createElement('br'))
  46. div.appendChild(attributeInput)
  47. div.appendChild(document.createElement('br'))
  48. div.appendChild(extractButton)
  49. div.style.cssText = 'position: fixed; bottom: 20px; right: 20px;z-index: 10000;'
  50. // 显示之前缓存的输入数据
  51. xpathInput1.value = GM_getValue(xpathInputId1 + url, '')
  52. xpathInput2.value = GM_getValue(xpathInputId2 + url, '')
  53. attributeInput.value = GM_getValue(attributeInputId + url, '')
  54. // 添加 div 到网页中
  55. document.body.appendChild(div)
  56. }
  57. // 一个工具函数,给定 xpath 路径,返回对应的多个元素的数组
  58. function $x(STR_XPATH) {
  59. var xresult = document.evaluate(STR_XPATH, document, null, XPathResult.ANY_TYPE, null);
  60. var xnodes = [];
  61. var xres;
  62. while (xres = xresult.iterateNext()) {
  63. xnodes.push(xres);
  64. }
  65. return xnodes;
  66. }
  67. // 给定两个模式类似的 xpath,返回能同时匹配它们的xpath,用于之后找出所有类似的元素
  68. // 原理:将 xpath1、xpath2 分割为 “/” 分隔的一个个子串,再找出相同的子串,对于不同的子串将“[xxx]”删除
  69. // 示例:
  70. // 1. 以“/”为间隔符划分两个 XPath,得到子串数组
  71. // “//div[1]/li” 被划分为 ["","","div[1]","li"]
  72. // “//div[3]/li” 被划分为 ["","","div[3]","li"]
  73. // 2. 对比两个 XPath 的数组,相同的子串保留,不同的删除 “[xxx]” 模式串,得到新的子串数组
  74. // ["","","div","li"]
  75. // 3. 以“/”为间隔符拼接上一步得到的子串数组,作为同时能匹配多个类似标签的 XPath
  76. // “//div/li”
  77. function toXPath(xpath1, xpath2) {
  78. console.log('XPath路径 1', xpath1)
  79. console.log('XPath路径 2', xpath2)
  80. let list1 = xpath1.split('/')
  81. let list2 = xpath2.split('/')
  82. let result = ""
  83. if (list1.length === list2.length) {
  84. for (let i = 0; i < list1.length; i++) {
  85. console.log(`子串:${list1[i]}${list2[i]}`)
  86. if (list1[i] === list2[i]) {
  87. result += list1[i]
  88. console.log('完全相同', result, list1[i])
  89. } else {
  90. // let pattern1 = list1[i].replace(/\[\d+\]/, '[*]')
  91. // let pattern2 = list2[i].replace(/\[\d+\]/, '[*]')
  92. let pattern1 = list1[i].replace(/\[\d+\]/, '')
  93. let pattern2 = list2[i].replace(/\[\d+\]/, '')
  94. if (pattern1 === pattern2) {
  95. result += pattern1
  96. console.log('正则相同', result, pattern1)
  97. }
  98. else {
  99. console.log('正则不同', result, pattern1, pattern2)
  100. result = ''
  101. break
  102. }
  103. }
  104. if (i !== list1.length - 1) {
  105. result += '/'
  106. }
  107. }
  108. } else {
  109. console.log(`两个表达式长度不同:第一个长度为 ${list1.length},第二个长度为 ${list2.length}`)
  110. }
  111. return result
  112. }
  113. // 根据 XPath 与属性名称(dataName)提取数据。如果 dataName 为空串,则提取标签体文本
  114. function extractDataByXPathAndAttribute(xpath, dataName) {
  115. console.log('dataName', dataName)
  116. let items = $x(xpath)
  117. if (items.length === 0) {
  118. alert('XPath路径出错,找不到数据,请检查')
  119. console.log(`XPath路径出错,找不到数据,请检查 ${xpath}`)
  120. } else if (dataName !== '' && !items[0].hasAttribute(dataName)) {
  121. alert(`找出的元素没有指定的属性 ${dataName},请重新输入`)
  122. console.log(`找出的元素样例为 ${items[0]}`)
  123. }
  124. else {
  125. let result = ''
  126. if (dataName === '') {
  127. items.forEach(item => {
  128. result += '\n' + item.innerText;
  129. })
  130. }
  131. else {
  132. items.forEach(item => { result += '\n' + item.getAttribute(dataName) })
  133. }
  134. result = result.trim()
  135. console.log(`-------- 提取出的数据(共${items.length}条数据) -------- \n${result}`)
  136. GM_setClipboard(result)
  137. alert(`已经提取出 ${items.length} 条数据与粘贴板,按Ctrl+V粘贴,数据如下\n${result}`)
  138. saveInput()
  139. }
  140. }
  141. // 缓存输入框数据
  142. function saveInput(){
  143. let xpathInput1 = document.getElementById(xpathInputId1)
  144. let xpathInput2 = document.getElementById(xpathInputId2)
  145. let attributeInput = document.getElementById(attributeInputId)
  146. GM_setValue(xpathInputId1 + url, xpathInput1.value)
  147. GM_setValue(xpathInputId2 + url, xpathInput2.value)
  148. GM_setValue(attributeInputId + url, attributeInput.value)
  149. }
  150. // 按键回调函数
  151. function extractData() {
  152. console.log('数据提取结果')
  153. let xpathInput1 = document.getElementById(xpathInputId1)
  154. let xpathInput2 = document.getElementById(xpathInputId2)
  155. let attributeInput = document.getElementById(attributeInputId)
  156. if (xpathInput1.value === '' || xpathInput2.value === '') {
  157. console.log(`有的XPath输入框还未输入任何内容`)
  158. alert(`有的XPath输入框还未输入任何内容`)
  159. return
  160. } else {
  161. let xpath = toXPath(xpathInput1.value, xpathInput2.value)
  162. if (xpath.length === 0) {
  163. alert('输入的两个XPath模式不相同,请重新检查')
  164. }
  165. extractDataByXPathAndAttribute(xpath, attributeInput.value)
  166. }
  167. }
  168. const xpathInputId1 = 'xpathInput1'
  169. const xpathInputId2 = 'xpathInput2'
  170. const attributeInputId = 'attributeInput'
  171. const url = document.location.href.replace(/[0-9]/g, '')
  172. insertElement(extractData)
  173. })();

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/79286
推荐阅读