一键批量下载淘宝图片

一键批量下载淘宝主图,sku以及详情页(重构和经过了一些逻辑上的改良,按钮更协调;内存占用更小;操作更流畅)

  1. // ==UserScript==
  2. // @name 一键批量下载淘宝图片
  3. // @namespace https://item.taobao.com
  4. // @version 1.0.4
  5. // @description 一键批量下载淘宝主图,sku以及详情页(重构和经过了一些逻辑上的改良,按钮更协调;内存占用更小;操作更流畅)
  6. // @author Leo
  7. // @homepage
  8. // @match https://item.taobao.com/*
  9. // @match https://item.taobao.hk/*
  10. // @grant GM_log
  11. // @grant GM_setClipboard
  12. // @grant GM_notification
  13. // @grant GM_download
  14. // @grant GM_setValue
  15. // @grant GM_getValue
  16. // @grant GM_deleteValue
  17. // @grant GM_addStyle
  18. // ==/UserScript==
  19. /*jshint multistr:true */
  20.  
  21. /*
  22. * 下载天猫图片工具
  23. * 下载商品主图
  24. * 下载sku
  25. * 下载详情页
  26. * */
  27.  
  28. window.onload = () => {
  29. const props = getData()
  30. setStyle()
  31. getProductImage(props)
  32. getProductSKU(props)
  33. getProductInfoPage(props)
  34. }
  35.  
  36. // 获取数据方法
  37. function getData() {
  38. // 全部变量
  39. const props = {}
  40. const params = location.search.substr(1).split('&')
  41. for (let i in params) {
  42. props[params[i].split('=')[0]] = unescape(params[i].split('=')[1])
  43. }
  44. return props
  45. }
  46.  
  47. // 注入下载商品主图方法
  48. function getProductImage(props) {
  49. // 获取主图缩略图列表DOM
  50. let imgList = document.getElementById('J_UlThumb')
  51. // 创建并注入下载专区
  52. const downBox = document.createElement('div')
  53. document.getElementsByClassName('tb-gallery')[0].appendChild(downBox)
  54. // 创建并注入标题
  55. const title = document.createElement('h2')
  56. title.innerHTML = '下载主图'
  57. title.style = 'text-align: center; margin-bottom: 20px; margin-top: 20px'
  58. downBox.appendChild(title)
  59. // 创建并插入下载按钮列表
  60. const downList = document.createElement('ul')
  61. downList.className = 'tb-thumb tb-clearfix thumb-ul'
  62. downBox.appendChild(downList)
  63.  
  64. // 创建主图的下载链接列表
  65. const imgArr = []
  66.  
  67. // 遍历主图缩略图,并插入下载按钮
  68. for (let k = 0; k < imgList.getElementsByTagName('li').length; k++) {
  69. // 获取主图下载链接
  70. let src
  71.  
  72. const xpath = document.evaluate(
  73. `//li[${k + 1}]/div/a/img`,
  74. imgList,
  75. null,
  76. XPathResult.ANY_TYPE,
  77. null
  78. )
  79. let img = xpath.iterateNext()
  80.  
  81. if (k === 0) {
  82. // 检查首图视频
  83. const arr = imgList
  84. .getElementsByTagName('li')[0]
  85. ?.getElementsByTagName('span')
  86. if (!(arr?.length >= 1)) {
  87. src = img?.src
  88. }
  89. } else {
  90. src = img?.src
  91. }
  92.  
  93. if (src) {
  94. src = src.substr(0, src.length - 16)
  95. // 注入给下载列表
  96. imgArr.push(src)
  97. // 创建并注入按钮
  98. const downButton = document.createElement('li')
  99. downButton.style =
  100. 'display:flex; flexflow: row; align-items: center; justify-content: center'
  101. const downImg = document.createElement('img')
  102. downImg.src = src
  103. downImg.style.cursor = 'pointer'
  104. downImg.title = (k + 1).toString()
  105. downImg.onmouseover = () => {
  106. imgList.getElementsByTagName('li')[k].className = 'tb-selected'
  107. }
  108. downImg.onmouseout = () => {
  109. imgList.getElementsByTagName('li')[k].className = 'tb-thumb tm-clear'
  110. }
  111. downImg.onclick = () => {
  112. GM_download(src, `${props.id}_主图_${k >= 9 ? k + 1 : '0' + (k + 1)}`)
  113. }
  114. downList.appendChild(downButton)
  115. downButton.appendChild(downImg)
  116. }
  117. }
  118.  
  119. // 注入下载全部按钮
  120. const downAll = document.createElement('li')
  121. downAll.style =
  122. 'display:flex; flexflow: row; align-items: center; justify-content: center'
  123. const downAllSpan = document.createElement('a')
  124. downAllSpan.style.cursor = 'pointer'
  125. downAllSpan.onclick = () => {
  126. GM_notification('共下载 ' + imgArr.length + ' 张图片', '下载主图')
  127. imgArr.forEach((i, k) => {
  128. GM_download(
  129. i,
  130. `${props.id}_主图_${k >= 9 ? k + 1 : '0' + (k + 1)}${i.substr(-4, 4)}`
  131. )
  132. })
  133. }
  134. downAllSpan.innerHTML = '全部'
  135. downList.appendChild(downAll)
  136. downAll.appendChild(downAllSpan)
  137.  
  138. return imgArr
  139. }
  140.  
  141. // 注入下载sku方法
  142. function getProductSKU(props) {
  143. // 获取SKU列表DOM
  144. let skuList = document.getElementsByClassName('J_Prop_Color')[0]
  145. console.log(skuList)
  146. // 创建并注入下载专区
  147. const downBox = document.createElement('dl')
  148. downBox.className = 'tb-prop'
  149. document
  150. .getElementsByClassName('tb-skin')[0]
  151. .getElementsByTagName('dl')[0]
  152. .insertAdjacentElement('afterend', downBox)
  153. // 创建并注入标题
  154. const title = document.createElement('dt')
  155. title.innerHTML = '下载 SKU'
  156. title.className = 'tb-metatit'
  157. downBox.appendChild(title)
  158. // 创建注入下载图按钮的列表
  159. const downListBox = document.createElement('dd')
  160. downBox.appendChild(downListBox)
  161. const downList = document.createElement('ul')
  162. downList.className = 'tm-clear J_TSaleProp tb-img'
  163. downListBox.appendChild(downList)
  164.  
  165. // 创建主图的下载链接列表
  166. const imgArr = []
  167.  
  168. //遍历SKU,生成并注入下载按钮
  169. for (let k = 0; k < skuList.getElementsByTagName('li').length; k++) {
  170. // 获取sku下载链接
  171. let img = skuList
  172. .getElementsByTagName('li')
  173. ?.[k]?.getElementsByTagName('a')?.[0]?.style.backgroundImage
  174. if (img) {
  175. const src = 'https:' + img.substr(5, img.length - 17)
  176. // 注入给下载列表
  177. imgArr.push(src)
  178. // 创建并注入按钮
  179. const downButton = document.createElement('li')
  180. const downImg = document.createElement('a')
  181. downImg.style = `background: ${img} center no-repeat;`
  182. downImg.onmouseover = function () {
  183. skuList.getElementsByTagName('li')[k].className = 'tb-selected'
  184. }
  185. downImg.onmouseout = function () {
  186. skuList.getElementsByTagName('li')[k].className = ''
  187. }
  188. downImg.onclick = () => {
  189. GM_download(src, `${props.id}_SKU_${k >= 9 ? k + 1 : '0' + (k + 1)}`)
  190. }
  191. downList.appendChild(downButton)
  192. downButton.appendChild(downImg)
  193. }
  194. }
  195.  
  196. // 创建并注入下载全部按钮
  197. const downButton = document.createElement('li')
  198. const downImg = document.createElement('a')
  199. downImg.innerHTML = '全部'
  200. downImg.style = 'color: red; font-weight: bold;'
  201. downImg.onclick = () => {
  202. GM_notification('共下载 ' + imgArr.length + ' 张图片', '下载 SKU')
  203. imgArr.forEach((i, k) => {
  204. GM_download(i, `${props.id}_SKU_${k >= 9 ? k + 1 : '0' + (k + 1)}`)
  205. })
  206. }
  207. downList.appendChild(downButton)
  208. downButton.appendChild(downImg)
  209. }
  210.  
  211. // 注入下载详情页方法
  212. function getProductInfoPage(props) {
  213. // 创建详情页图片列表
  214. const imgArr = []
  215.  
  216. // 获取表单
  217. const editForm = document.getElementById('J_TabBar')
  218. // 创建下载按钮
  219. const downButton = document.createElement('li')
  220. downButton.style =
  221. 'display:flex; flexflow: row; align-items: center; justify-content: center'
  222. const downA = document.createElement('a')
  223. // 调整属性
  224. downA.innerHTML = '下载详情页'
  225. downA.style = 'color: red; font-weight: bold;'
  226. downA.title =
  227. '请注意,下载详情图之前请先将所有详情图片显示完毕再点击此按钮下载,否则会出现下载不完整等问题'
  228. downA.onclick = () => {
  229. downButton.className = 'tm-selected'
  230. const imgList = document.getElementsByClassName('ke-post')[0].childNodes
  231. // todo 改成多层遍历,穿透获取
  232. // 分层穿透,
  233. // 检查节点是否含有src
  234. // 检查节点是否有子元素 ———闭包遍历
  235. const imgArr = []
  236. const mapChild = list => {
  237. list.forEach(i => {
  238. if (i?.src) {
  239. imgArr.push(i.src)
  240. }
  241. if (i.childNodes.length !== 0) {
  242. mapChild(i.childNodes)
  243. }
  244. })
  245. }
  246. mapChild(imgList)
  247. GM_notification('共下载 ' + imgArr.length + ' 张图片', '下载详情页')
  248. // 下载图片
  249. for (let k = 0; k < imgArr.length; k++) {
  250. GM_download(
  251. imgArr[k],
  252. `${props.id}_详情页_${k >= 9 ? k + 1 : '0' + (k + 1)}`
  253. )
  254. }
  255. }
  256. // 将下载按钮注入表单
  257. editForm.insertBefore(
  258. downButton,
  259. document.getElementsByClassName('tm-qrcode-icon')[0]
  260. )
  261. downButton.appendChild(downA)
  262. }
  263.  
  264. // 注入样式
  265. function setStyle() {
  266. GM_addStyle(`
  267. .thumb-ul{
  268. font-family:Arial;
  269. font-weight:bold;
  270. }
  271. .thumb-ul li{
  272. border-style:solid;
  273. border-color:#FE4403!important;
  274. font-family:Arial;
  275. font-weight:bold;
  276. font-size:16px;
  277. cursor:pointer;
  278. }
  279. .cat-ul li{
  280. cursor:pointer;
  281. font-size:14px;
  282. font-family:Arial;
  283. }
  284. .detail-li,.border-li{
  285. width:40px!important;
  286. padding:0px!important;
  287. }
  288. .tb-tabbar>li{
  289. min-width:80px!important;
  290. }
  291. `)
  292. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址