<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      AutoX 腳本導出微信賬單

      AutoX 腳本

      一個支持無障礙服務的 Android 平臺上的 JavaScript 運行環境 和 開發環境,其發展目標是類似 JsBoxWorkflow

      前提條件

      1. 你需要一個安卓手機
      2. 你需要安裝 AutoX apk
      3. 你需要一點動手能力
      4. 手機需要打開無障礙功能才能執行腳本

      如果以上條件不能滿足也沒關系,網上沖浪也是可以的。

      微信賬單

      微信是支持賬單導出的(錢包->賬單->下載賬單->用于個人對賬),有時間和格式限制。使用腳本沒有時間和格式限制,需要指定賬單截止日期即可。

      功能列表

      • 導出格式
        • csv (默認)
        • json
        • txt (微信默認格式)
        • md
      • 導出時間范圍
        • 示例:2024年10月,和賬單篩選時間范圍一致

      使用說明

      1. 執行腳本前先打開微信賬單頁面
      2. 再返回 autox 頁面執行腳本
      3. 執行結束會返回到 autox 頁面
      4. 默認保存文件在 /sdcard/Download/ 目錄

      實現思路

      使用 autox 獲取頁面布局信息一般常用 idclassName 獲取頁面布局信息,但是微信賬單頁面都沒有 idclassName,只能獲取最外面的容器 android.webkit.WebView,一層一層剝洋蔥了。下面是頁面布局的大概結構

      布局結構

      <view classNam="android.webkit.WebView">
          <view >
              <!-- 篩選條件 -->
              <view >
                  <view >
                      <button>全部賬單</button>
                      <button>統計</button>
                  <view />
              <view />
              <!-- 賬單列表 -->
              <view >
                  <view >
                      <!-- 兩行 view 是一個整體,第一個月份統計,第二月份收入明細 -->
                      <view >
                          <view >
                              <view >
                                  <button>2024-11</button>
                                  <view class="android.widget.TextView">支出<view />
                                  <view class="android.widget.TextView">¥200<view />
                                  <view class="android.widget.TextView">收入<view />
                                  <view class="android.widget.TextView">¥200<view />
                              <view />
                          <view />
                      <view />
                      <view >
                          <!-- 明細 -->
                          <view >
                              二維碼收款-來自計xxxx,11月00日00點00分,收入0.00元,按鈕。點按兩次并按住可長按
                          <view />
                          <view >
                              二維碼收款-來自計xxxx,11月00日00點00分,收入0.00元,按鈕。點按兩次并按住可長按
                          <view />
                          <view >
                              二維碼收款-來自計xxxx,11月00日00點00分,收入0.00元,按鈕。點按兩次并按住可長按
                          <view />
                          <!-- ......更多 -->
                      <view />
                  <view />
              <view />  
          <view />
          <view classNam="android.app.Dialog" ><view />
      <view />
      

      腳本代碼

      
      /**
       * @description wx 賬單導出腳本
       * 1、執行腳本前先打開微信賬單頁面
       * 2、返回 autox 頁面執行腳本
       * 3、執行結束會返回到 autox 頁面
       * 4、默認保存文件在 Download 目錄
       * @author Mr.Fang
       * @time 2024年11月4日12:01:39
       */
      
      // 等待打開無障礙繼續執行
      auto.waitFor();
      
      let endFlag = false; // 結束標識
      let format = "csv"; // 默認導出格式
      let endCondition = '2024年7月'; // 默認截止日期
      const savePath = '/sdcard/Download/';  // 本地路徑
      const options = ["json", "md", "txt", "csv"]; // 導出格式
      const listData = []; // 賬單數據
      const keyMap = new Map(); // 存放日期
      
      
      /**
       * 字符串日期轉標準日期
       * @param {*} inputDate 2024年10月22日7時8分
       * @returns 
       */
      function convertDateTime(inputDate) {
          // 解析輸入的日期字符串
          const match = inputDate.match(/(\d+)年(\d+)月(\d+)日(\d+)點(\d+)分/);
          if (!match) {
              return '輸入的日期格式不正確';
          }
          if (match) {
              const year = match[1];
              const month = String(match[2]).padStart(2, '0'); // 確保月份為兩位
              const day = String(match[3]).padStart(2, '0'); // 確保日期為兩位
              const hour = String(match[4]).padStart(2, '0'); // 轉換為24小時制
              const minute = String(match[5]).padStart(2, '0'); // 確保分鐘為兩位
      
              // 構建標準時間格式
              const standardTime = `${year}-${month}-${day} ${hour}:${minute}:00`;
              return standardTime;
          } else {
              console.log('輸入格式不正確');
          }
          return "";
      }
      
      /**
       * 驗證截止日期
       * @param {*} inputDate 2024年10月
       * @returns 
       */
      function verifyDateTime(inputDate) {
          // 解析輸入的日期字符串
          const dateParts = inputDate.match(/(\d+)年(\d+)月/);
          if (!dateParts) {
              return '輸入的截止日期不正確';
          }
          return '';
      }
      
      /**
       * 
       * @returns 返回最大長度
       */
      function calcMaxLength() {
          const mergedArray = listData.reduce((acc, item) => { return acc.concat(item.list) }, []);
          return mergedArray.reduce((max, item) => Math.max(max, (item.type ? item.type.length : 0) + item.user.length), 10);
      }
      
      
      // 轉 csv
      function textConvertCSV() {
          // 輸出 csv 格式
          let text = '時間,用戶名,類型,資金\n';
          const mergedArray = listData.reduce((acc, item) => { return acc.concat(item.list) }, []);
          for (let item of mergedArray) {
              let { time, user, type, amount } = item;
              text += `${time},${user},${type},${amount}\n`;
          }
          return text;
      }
      
      // 轉 md
      function textConvertMD() {
          let text = "| 時間               | 用戶名 | 類型 | 金額 |\n";
          text += "| ------------------ | ------ | ---- | ---- |\n";
          const mergedArray = listData.reduce((acc, item) => { return acc.concat(item.list) }, []);
          for (let item of mergedArray) {
              let { time, user, type, amount } = item;
              if (user.includes("*")) {
                  user = user.replace("*", "\\*");
              }
              text += `|${time}|${user}|${type}|${amount}|\n`;
          }
          return text;
      }
      
      // 轉 txt
      function textConvertTxt() {
          let text = "";
          const maxlength = calcMaxLength();
          for (let item of listData) {
              let { key, list } = item;
              let keys = key.split('|');
              text += `${keys[0]}\t\t支出¥${keys[1]} 收入¥${keys[2]}\n`;
              list.forEach(detail => {
                  // 構造空字符
                  let padding = ' '.repeat(maxlength - (detail.type ? detail.type.length : 0) - detail.user.length);
                  text += `${detail.type}-${detail.user}${padding}${detail.amount}\n`;
                  text += `${detail.time}\n`;
              })
              text += '\n\n';
          }
          return text;
      }
      
      /**
       * 保存到本地
       */
      function saveLocal() {
          // 輸出 csv 格式
          let content = '';
          switch (format) {
              case 'csv': content = textConvertCSV(); break;
              case 'md': content = textConvertMD(); break;
              case 'txt': content = textConvertTxt(); break;
              default: content = JSON.stringify(listData);
          }
          const fullPath = savePath + endCondition + '.' + format
          files.write(fullPath, content)
          console.log('文件寫入成功:', fullPath);
          return fullPath;
      }
      
      /**
       * 字符串金額轉金額
       * @param {*} transaction 
       * @returns 
       */
      function convertAmount(transaction) {
          // 使用正則表達式提取金額
          const amountMatch = transaction.match(/(\d+\.?\d*)元/);
          if (!amountMatch) return '無效的交易格式';
      
          // 提取金額并轉換為浮點數
          const amount = parseFloat(amountMatch[1]);
      
          // 根據交易類型添加正負號
          if (transaction.includes('收入')) {
              return `+${amount.toFixed(2)}`;
          } else if (transaction.includes('支出')) {
              return `-${amount.toFixed(2)}`;
          } else {
              return '無效的交易類型';
          }
      }
      
      // 定義一個函數來比較兩個對象是否相等
      function isSameEntry(entryA, entryB) {
          return entryA.user === entryB.user && entryA.time === entryB.time && entryA.amount === entryB.amount;
      }
      
      /**
       * 添加賬單數據
       * @param {*} key 日期
       * @param {*} data 明細
       */
      function addBill(key, data) {
          if (keyMap.has(key)) {
              let index = keyMap.get(key);
              let { list } = listData[index];
              // 過濾掉arrayA中存在于arrayB的項
              let filtered = list.filter(a => !data.some(b => isSameEntry(a, b)));
              // 合并 filtered 和 data
              listData[index].list = filtered.concat(data);
          } else {
              let index = listData.length;
              listData.push({ key: key, list: data });
              keyMap.set(key, index);
          }
      }
      
      function loadData() {
          // 獲取頁面根賬單節點
          let webView = className("android.webkit.WebView").findOne(1000);
          // 賬單列表節點
          let elements = webView.children()[0].children()[1].children()[0].children();
          // 節點數量
          let length = elements.length;
          console.log("賬單數量:", length);
          for (let i = 0; i < length; i += 2) {
              console.log(i);
              if (i + 1 >= length) {
                  console.log('提前結束')
                  break;
              }
              // 月份統計數據 示例:2024年11月 支出$00.00收入$00.00
              let firstChildrens = elements[i].children();
              // 賬單列表 示例:二維碼收款-來自*M,10月18日7點44分,+6.00,……
              let lastChildrens = elements[i + 1].children();
              if (firstChildrens.length === 0) {
                  console.log('跳過空節點')
                  continue;
              }
              console.log('firstChildrens:', firstChildrens.length);
              console.log('lastChildrens:', lastChildrens.length);
      
              let months = firstChildrens[0].children().length === 1 ? firstChildrens[0].children()[0].children() : firstChildrens[0].children();
              console.log('months', months.length)
              if (months.length === 0) {
                  continue;
              }
              let year = months[0].text();
              if (year === endCondition) {
                  endFlag = true;
                  console.log("提前結束")
                  return true;
              }
              let output = months[2].text();
              let input = months[4].text();
              console.log(`時間:${year} 支出:${output} 收入:${input}`)
      
              let listTemp = [];
              lastChildrens.forEach(item => {
                  // 二維碼收款-來自計*xxx,10月30日8點48分,收入1.00元,按鈕。點按兩次并按住可長按
                  let text = item.text();
                  if (text) {
                      let list = text.split(',');
                      list.pop();
                      // 收入類型-用戶 時間 收入 支出
                      let user = list[0], type = "";
                      let firstIndex = user.indexOf('-');
                      if (firstIndex != -1) {
                          type = user.substring(0, firstIndex);
                          user = user.substring(firstIndex + 1);
                      }
                      let time = convertDateTime(year.substring(0, 5) + list[1]);
                      let amount = convertAmount(list[2]);
                      console.log(time, '\t', type, '\t', user, '\t', amount);
                      listTemp.push({ time, type, user, amount })
                  }
              })
              addBill(year + "|" + output + "|" + input, listTemp);
          }
          // 結束標識
          if (length >= 2) { // 倒數第二個結束標識
              const end = elements[length - 2];
              const entText = end.children()[0].text();
              console.log('entText', entText);
              if (entText === "暫無更多記錄") {
                  return true;
              }
          }
          // 滾動頁面
          webView.scrollForward();
          return false;
      }
      
      
      /**
       * 定時器,每隔 5 秒執行一次
       */
      
      function startInterval() {
          launch("com.tencent.mm");
          sleep(2000);
          const button = text("全部賬單").findOne(1000);
          if (button) {
              const interval = setInterval(() => {
                  if (endFlag) {
                      clearInterval(interval);
                      const local = saveLocal();
                      launch("org.autojs.autoxjs.v7");
                      sleep(1000);
                      alert("保存路徑" + local)
                  } else {
                      endFlag = loadData();
                  }
              }, 1000)
          } else {
              launch("org.autojs.autoxjs.v7");
              sleep(1000);
              toast("請打開賬單頁面")
          }
      }
      
      /**
       * 開始方法
       */
      function start() {
          const input = dialogs.rawInput("請輸入截止年月", endCondition);
          console.log('input:', input);
          const result = verifyDateTime(input);
          if (result) {
              toastLog(result);
          } else {
              endCondition = input
              const selectIndex = dialogs.singleChoice("請選擇導出格式", options, 3);
              format = options[selectIndex];
              console.log(format);
              toastLog("開始執行");
              startInterval();
          }
      }
      
      start();
      
      

      導出示例

      txt

      2024年10月	支出¥200.00元 收入¥245.89元
      二維碼收款-來自計*g     +10.00
      2024-10-30 08:48:00
      二維碼收款-來自B*m     +1.00
      2024-10-24 10:53:00
      二維碼收款-來自L*S     +5.00
      2024-10-22 16:56:00
      二維碼收款-來自*鹿      +6.00
      2024-10-18 07:44:00
      轉賬-來來xxxx- yo      +100.00
      2024-10-17 16:00:00
      二維碼收款-來xxxx- yo  +18.88
      2024-10-17 14:46:00
      …………省略
      

      md

      | 時間                | 用戶名       | 類型       | 金額    |
      | ------------------- | ------------ | ---------- | ------- |
      | 2024-10-30 08:48:00 | 來自計\*g    | 二維碼收款 | +10.00  |
      | 2024-10-24 10:53:00 | 來自B\*m     | 二維碼收款 | +1.00   |
      | 2024-10-22 16:56:00 | 來自L\*S     | 二維碼收款 | +5.00   |
      | 2024-10-18 07:44:00 | 來自\*鹿     | 二維碼收款 | +6.00   |
      | 2024-10-17 16:00:00 | 來自xxxx- yo | 轉賬       | +100.00 |
      | 2024-10-17 14:46:00 | 來自xxxx- yo | 二維碼收款 | +18.88  |
      …………省略
      

      csv

      時間,用戶名,類型,資金
      2024-10-30 08:48:00,來自計*g,二維碼收款,+10.00
      2024-10-24 10:53:00,來自B*m,二維碼收款,+1.00
      2024-10-22 16:56:00,來自L*S,二維碼收款,+5.00
      2024-10-18 07:44:00,來自*鹿,二維碼收款,+6.00
      2024-10-17 16:00:00,來自xxxx- yo,轉賬,+100.00
      2024-10-17 14:46:00,來自xxxx- yo,二維碼收款,+18.88
      …………省略
      
      posted @ 2024-11-04 15:36  天葬  閱讀(182)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 成人污视频| 中文字幕国产精品一区二| 日本a在线播放| 国产成人综合网亚洲第一| 日本va欧美va欧美va精品| 四虎精品国产精品亚洲精| 松滋市| 91热在线精品国产一区| 黄色A级国产免费大片视频| 欧美孕妇乳喷奶水在线观看| 在线精品国精品国产不卡| 国产亚洲制服免视频| 国产精品无遮挡猛进猛出| 亚洲人成伊人成综合网小说| 日韩一区二区黄色一级片| 美女无遮挡免费视频网站| 日韩丝袜欧美人妻制服| 99热精品国产三级在线观看| 国产亚洲精久久久久久久91| 精品综合一区二区三区四区| 夜夜躁狠狠躁日日躁视频| 国产一区二区三区四区五区加勒比| 乃东县| 国产精品中文字幕在线| 爆乳日韩尤物无码一区| 日韩激情成人| 国产美女午夜福利视频| 西西午夜无码大胆啪啪国模| 亚洲国产成人精品女人久| 国产欧美综合在线观看第十页| 国产美女被遭强高潮免费一视频| 美女一区二区三区在线观看视频 | 久久av色欲av久久蜜桃网| 极品人妻少妇一区二区| 亚洲老熟女一区二区三区| 亚洲av久久精品狠狠爱av| 骚虎视频在线观看| 人人妻人人狠人人爽天天综合网 | 日韩av在线一区二区三区| 国产精品综合一区二区三区| 成人无码区在线观看|