cart2excel

导出淘宝/天猫购物车到excel

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         cart2excel
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  导出淘宝/天猫购物车到excel
// @author       yxf
// @grant        none
// @license      MIT
// @include      *://cart.taobao.com/*
// @require      https://code.jquery.com/jquery-3.5.1.min.js
// @require      https://unpkg.com/[email protected]/FileSaver.js
// @require      https://unpkg.com/[email protected]/Blob.js
// @require      https://unpkg.com/xlsx/dist/shim.min.js
// @require      https://unpkg.com/xlsx/dist/xlsx.full.min.js
// @run-at document-body
// ==/UserScript==

(function ($) {
  'use strict'

  // Your code here...

  // const scripts = [
  //   '//unpkg.com/[email protected]/FileSaver.js',
  //   '//unpkg.com/[email protected]/Blob.js',
  //   '//unpkg.com/xlsx/dist/shim.min.js',
  //   '//unpkg.com/xlsx/dist/xlsx.full.min.js'
  // ]

  // const promises = scripts.map(item => loadScript(item))
  // Promise.all(promises).then(res => {
  //   createBtn()
  // })
  createBtn()
  function createBtn (src) {
    if (!document.querySelector('#downloadBtn')) {
      const btn = document.createElement('button')
      btn.id = 'downloadBtn'
      btn.onclick = handleDownload
      btn.style.cssText = `
      position:fixed;
      top:40px;
      right:0;
      z-index:999;     
      display: inline-block;
    padding: 10px 16px;
    color:white;
    cursor: pointer;
    border: none;
    text-decoration: none;
    background: #ea4c89;
    -webkit-transition: all 200ms ease;
    transition: all 200ms ease;
    border-radius: 8px;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    outline: none;
    font-family: 'Haas Grot Text R Web', 'Helvetica Neue', Helvetica, Arial, sans-serif;
    font-size: 14px;
    font-weight: 500;
    line-height: 20px;
    height: 40px;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
    text-align: center;
      `

      btn.innerText = 'export Excel'

      document.body.appendChild(btn)
    }
  }

  function handleDownload () {
    crawl().then(list => {
      const tHeader = ['图片', '标题', '规格', '原价', '现价', '数量', '总价', '失效状态']
      const filterVal = ['img', 'title', 'info', 'priceOriginal', 'priceNow', 'amount', 'sum', 'valid']
      const data = formatJson(filterVal, list)
      export_json_to_excel({
        header: tHeader, // 表头 必填
        data, // 具体数据 必填
        filename: 'cart', // 非必填
        autoWidth: true, // 非必填
        bookType: 'xlsx' // 非必填
      })
    })
  }

  function crawl () {
    return new Promise((resolve, reject) => {
      const $productList = $('.J_ItemBody')

      const list = []
      $productList.each((index, item) => {
        const obj = {}
        obj.img = $(item).find('.itempic.J_ItemImg').attr('src')
        obj.title = $(item).find('.item-basic-info').text() // 标题
        obj.info = $(item).find('.item-props').text() // 规格信息
        obj.priceOriginal = $(item).find('.price-original').text() // 原价
        obj.priceNow = $(item).find('.J_Price.price-now').text() // 现价
        obj.amount = $(item).find('input.J_ItemAmount').length ? $(item).find('input.J_ItemAmount').val() : $(item).find('.item-amount ').text() // 数量
        obj.sum = $(item).find('.J_ItemSum.number').text()
        obj.valid = $(item).find('.td-inner .label-invalid').length ? '失效' : ''
        list.push(obj)
      })
      resolve(list)
    })
  }
  function sheet_from_array_of_arrays (data, opts) {
    var ws = {}
    var range = {
      s: {
        c: 10000000,
        r: 10000000
      },
      e: {
        c: 0,
        r: 0
      }
    }
    for (var R = 0; R != data.length; ++R) {
      for (var C = 0; C != data[R].length; ++C) {
        if (range.s.r > R) range.s.r = R
        if (range.s.c > C) range.s.c = C
        if (range.e.r < R) range.e.r = R
        if (range.e.c < C) range.e.c = C
        var cell = {
          v: data[R][C]
        }
        if (cell.v == null) continue
        var cell_ref = XLSX.utils.encode_cell({
          c: C,
          r: R
        })

        if (typeof cell.v === 'number') cell.t = 'n'
        else if (typeof cell.v === 'boolean') cell.t = 'b'
        else if (cell.v instanceof Date) {
          cell.t = 'n'
          cell.z = XLSX.SSF._table[14]
          cell.v = datenum(cell.v)
        } else cell.t = 's'

        ws[cell_ref] = cell
      }
    }
    if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range)
    return ws
  }

  function Workbook () {
    if (!(this instanceof Workbook)) return new Workbook()
    this.SheetNames = []
    this.Sheets = {}
  }
  function s2ab (s) {
    var buf = new ArrayBuffer(s.length)
    var view = new Uint8Array(buf)
    for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF
    return buf
  }

  function datenum (v, date1904) {
    if (date1904) v += 1462
    var epoch = Date.parse(v)
    return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000)
  }

  function export_json_to_excel ({
    multiHeader = [],
    header,
    data,
    filename,
    merges = [],
    autoWidth = true,
    bookType = 'xlsx'
  } = {}) {
  /* original data */
    filename = filename || 'excel-list'
    data = [...data]
    data.unshift(header)

    for (let i = multiHeader.length - 1; i > -1; i--) {
      data.unshift(multiHeader[i])
    }

    var ws_name = 'SheetJS'
    var wb = new Workbook()
    var ws = sheet_from_array_of_arrays(data)

    if (merges.length > 0) {
      if (!ws['!merges']) ws['!merges'] = []
      merges.forEach(item => {
        ws['!merges'].push(XLSX.utils.decode_range(item))
      })
    }

    if (autoWidth) {
    /* 设置worksheet每列的最大宽度 */
      const colWidth = data.map(row => row.map(val => {
      /* 先判断是否为null/undefined */
        if (val == null) {
          return {
            wch: 10
          }
        }
        /* 再判断是否为中文 */
        else if (val.toString().charCodeAt(0) > 255) {
          return {
            wch: val.toString().length * 2
          }
        } else {
          return {
            wch: val.toString().length
          }
        }
      }))
      /* 以第一行为初始值 */
      const result = colWidth[0]
      for (let i = 1; i < colWidth.length; i++) {
        for (let j = 0; j < colWidth[i].length; j++) {
          if (result[j].wch < colWidth[i][j].wch) {
            result[j].wch = colWidth[i][j].wch
          }
        }
      }
      ws['!cols'] = result
    }

    /* add worksheet to workbook */
    wb.SheetNames.push(ws_name)
    wb.Sheets[ws_name] = ws

    var wbout = XLSX.write(wb, {
      bookType: bookType,
      bookSST: false,
      type: 'binary'
    })
    saveAs(new Blob([s2ab(wbout)], {
      type: 'application/octet-stream'
    }), `${filename}.${bookType}`)
  }

  function formatJson (filterVal, jsonData) {
    return jsonData.map(v => filterVal.map(j => {
      if (j === 'timestamp') {
        return parseTime(v[j])
      } else {
        return v[j]
      }
    }))
  }

  function loadScript (src) {
    return new Promise((resolve, reject) => {
      const existingScript = document.getElementById(src)
      if (!existingScript) {
        const script = document.createElement('script')
        script.id = src
        script.src = src

        document.body.appendChild(script)
        script.onload = function () {
          this.onerror = this.onload = null
          resolve()
        }
      }
    })
  }
})(window.$)