您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Based on 淘宝买家订单导出 by CMA https://greasyfork.org/en/scripts/414444-%E6%B7%98%E5%AE%9D%E4%B9%B0%E5%AE%B6%E8%AE%A2%E5%8D%95%E5%AF%BC%E5%87%BA, added tracking number on top of it to the export data.
当前为
// ==UserScript== // @name Taobao orders export 淘宝订单快递导出 // @namespace http://tampermonkey.net/ // @version 0.01 // @description Based on 淘宝买家订单导出 by CMA https://greasyfork.org/en/scripts/414444-%E6%B7%98%E5%AE%9D%E4%B9%B0%E5%AE%B6%E8%AE%A2%E5%8D%95%E5%AF%BC%E5%87%BA, added tracking number on top of it to the export data. // @author Trizzy33 // @include https://buyertrade.taobao* // @require https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js // @grant window.close // @grant GM_xmlhttpRequest // @license MIT // ==/UserScript== //TODO: add retry for failed tracking number. //github https://github.com/Trizzy33/taobaoTrackingNumberExport/blob/main/script //TODO: add retry for failed tracking number. //**********************************global variables**************************************** let orderList = []; let isProcessing = false; let shouldStop = false; let currentWindow = null; const state = { orderList: [], isProcessing: false, shouldStop: false, currentWindow: null }; const orderListPage = /(http|https):\/\/buyertrade\.taobao.*?\/trade/g; //****************************************************************************************** function addButton(element, onclickFunc, value = "按钮", width = "60px", height = "60px") { const button = document.createElement("input"); button.type = "button"; button.value = value; button.style.height = height; button.style.width = width; button.style.align = "center"; button.style.marginBottom = "10px"; button.style.marginLeft = "250px"; button.style.color = "white"; button.style.background = "#409EFF"; button.style.border = "1px solid #409EFF"; button.onclick = function () { onclickFunc(); } element.appendChild(button); element.insertBefore(button, element.childNodes[0]); } if (orderListPage.exec(document.URL)) { const orderListMain = document.getElementById("J_bought_main"); addButton(orderListMain, addCurrentPageOrdersToList, "添加本页订单", "160px"); addButton(orderListMain, exportOrders, "导出订单", "160px"); addButton(orderListMain, stopScript, "停止脚本", "160px"); } function toCsv(header, data, filename) { let rows = '\uFEFF订单号,商品名称,店铺链接,价格,数量,实付款,状态,运单号\n' for(let order of data) { rows += order.join(',') + '\n'; } let blob = new Blob([rows], {type: 'text/csv;charset=utf-8;'}); let encodedUrl = URL.createObjectURL(blob); let url = document.createElement("a"); url.setAttribute("href", encodedUrl); url.setAttribute("download", filename + ".csv"); document.body.appendChild(url); url.click(); } //*************************************************Buttons functions**************************************************** function addCurrentPageOrdersToList() { if (state.isProcessing) { console.log('已有处理进行中,请等待...'); return; } state.isProcessing = true; state.shouldStop = false; const orders = document.querySelectorAll(".js-order-container"); processOrders(orders); } function exportOrders() { const header = ["订单号", "商品明细", "商品链接", "单价", "数量", "实付款", "状态", "快递单号"]; toCsv(header, orderList, "淘宝订单导出") } function stopScript() { state.shouldStop = true; console.log('正在停止处理...'); if (state.currentWindow && !state.currentWindow.closed) { state.currentWindow.close(); } if (state.orderList.length > 0) { exportOrders(); } state.isProcessing = false; let statusDiv = document.getElementById('processing-status'); if (statusDiv) { statusDiv.textContent = '处理已停止'; statusDiv.style.background = '#F56C6C'; // 2秒后移除状态显示 setTimeout(() => { statusDiv.remove(); }, 2000); } } //*************************************************Buttons functions**************************************************** function processOrders(orders, currentOrderIndex = 0, results = []) { if (currentOrderIndex >= orders.length || state.shouldStop) { console.log('所有订单处理完成!'); console.table(results); return results; } try{ const order = orders[currentOrderIndex]; const id = order.getAttribute('data-reactid').match(/order-(\d+)/)?.[1]; console.log(`处理订单 ${id},第 ${currentOrderIndex + 1}/${orders.length} 个订单`); // 处理单个订单中的商品 processOrderItems(order, id, 0, [], (orderResults) => { orderList.push(orderResults); setTimeout(() => { processOrders(orders, currentOrderIndex + 1, results); }, 500); }); }catch(error){ console.error(`当前订单结果处理失败:`, error); // 继续处理下一个订单 setTimeout(() => { processOrders(orders, currentOrderIndex + 1, results); }, 500); } } function processOrderItems(order, id, index, itemResults, callback) { try{ let productQuery = order.querySelector("span[data-reactid='.0.7:$order-" + id + ".$" + id + ".0.1:1:0.$" + index + ".$0.0.1.0.0.1']"); if (productQuery == null) { callback(itemResults); return; } const queries = { product: order.querySelector("span[data-reactid='.0.7:$order-" + id + ".$" + id + ".0.1:1:0.$" + index + ".$0.0.1.0.0.1']"), price: order.querySelector("span[data-reactid='.0.7:$order-" + id + ".$" + id + ".0.1:1:0.$" + index + ".$1.0.1.1']"), count: order.querySelector("p[data-reactid='.0.7:$order-" + id + ".$" + id + ".0.1:1:0.$" + index + ".$2.0.0']"), actualPay: order.querySelector("span[data-reactid='.0.7:$order-" + id + ".$" + id + ".0.1:1:0.$" + index + ".$4.0.0.2.0.1']"), itemUrl: order.querySelector("a[href]"), status: index === 0 ? order.querySelector("span[data-reactid='.0.7:$order-" + id + ".$" + id + ".0.1:1:0.$" + index + ".$5.0.0.0']") : null, tracking: index === 0 ? order.querySelector('#viewLogistic') : null }; if (!queries.product || !queries.price || !queries.count) { throw new Error(`订单 ${id} 缺少名称`); } const orderItem = [ id, queries.product.textContent.replace(/,/g, ","), queries.itemUrl.href, parseFloat(queries.price.textContent), queries.count.textContent, queries.actualPay?.textContent || '', queries.status?.textContent || '' ]; if (index === 0 && queries.tracking) { const logisticsUrl = queries.tracking.href; // 使用异步函数获取快递单号 getTrackingNumber(logisticsUrl).then(trackingNumber => { orderItem.push(trackingNumber); itemResults = orderItem; // 递归处理下一个商品 processOrderItems(order, id, index + 1, itemResults, callback); }); } else { // 没有物流信息或不是第一个商品,直接添加默认值并返回 orderItem.push('0'); itemResults = orderItem; callback(itemResults); } } catch (error) { // 直接处理下一个商品 console.error(`处理订单 ${id} 时出错:`, error); callback(itemResults?itemResults:[]); } } async function getTrackingNumber(logisticsUrl) { return new Promise((resolve) => { if (state.shouldStop) { resolve('0'); return; } const currentWindow = window.open(logisticsUrl); setTimeout(() => { try { if (currentWindow && !currentWindow.closed) { const trackingNumber = currentWindow.document .querySelector('.rax-view-v2.flexRow.pc-company-wrapper') ?.querySelector('.rax-view-v2.flexRow') ?.querySelectorAll('.rax-text-v2.desc')?.[1] ?.textContent || '0'; currentWindow.close(); resolve(trackingNumber); } else { resolve('0'); } } catch (error) { console.error('获取物流信息失败:', error); if (currentWindow) currentWindow.close(); resolve('0'); } finally { state.currentWindow = null; resolve('0'); } }, 2000); }); }