1. 程式人生 > 實用技巧 >C# CefSharp Winform抓取拼多多訂單

C# CefSharp Winform抓取拼多多訂單

C# CefSharp Winform抓取拼多多訂單

前言

  • 只支援查詢自己的買家訂單
  • 支援Excel匯出,只支援部分欄位
  • 純技術實戰分享

如何使用

  • 直接執行專案
  • 登入拼多多
  • 點選全部訂單
  • 等待頁面載入不跳轉了,點選 匯出訂單按鈕

登入驗證

基於CefSharp Winform載入Web瀏覽器(chrome核心),瀏覽器地址導航到http://mobile.yangkeduo.com/personal.html,然後用手機驗證碼方式登入

獲取訂單資料

 if (request.Method.Equals("POST")&&request.Url.Contains("order_list"))
{
    var filter = FilterManager.GetFileter(request.Identifier.ToString()) as TestJsonFilter;
    if (filter==null)
    {
        return;
    }
    ASCIIEncoding encoding = new ASCIIEncoding();
    //這裡截獲返回的資料
    var data = encoding.GetString(filter.DataAll.ToArray());
}

但是由於採用了分頁獲取的仍然不是全部,這樣我們必須通過手動模擬Post請求來載入全部

嘗試抓取Post資料

將byte轉為string之後得到json

{"timeout":1300,"type":"all","page":1,"pay_channel_list":["9","30","31","35","38","52","97","122","135","322","-1"],"origin_host_name":"mobile.yangkeduo.com","size":10,"offset":"200725-031832966363189"}

看得出size為10條資料 所以嘗試更改post入參試試,offset應該是分頁的最後條記錄作為偏移量,理論我們可以傳空試試,從第一條記錄消費

結論是拼多多那邊做了驗證 返回了errorCode 300000

重新梳理!

獲取Post Json

Encoding.Default.GetString(request.PostData.Elements[0].Bytes);將Byte轉為String
  • 第一頁json
{"timeout":1300,"type":"all","page":1,"pay_channel_list":["9","30","31","35","38","52","97","122","135","322","-1"],"origin_host_name":"mobile.yangkeduo.com","size":10,"offset":"200803-173139887143189"}
  • 第二頁
{"timeout":1300,"type":"all","page":1,"pay_channel_list":["9","30","31","35","38","52","97","122","135","322","-1"],"origin_host_name":"mobile.yangkeduo.com","size":10,"offset":"200727-071906181943189"}
  • 第三頁
{"timeout":1300,"type":"all","page":1,"pay_channel_list":["9","30","31","35","38","52","97","122","135","322","-1"],"origin_host_name":"mobile.yangkeduo.com","size":10,"offset":"200725-031832966363189"}

區別的只有offset,那麼offset是啥

由於offset是前端請求必然是在後端返回的訂單資料裡有,所以拿到offset值去搜索,可以找到為訂單order_sn欄位!

那麼下一步的思路清晰了,解析返回的json

解析返回json

  • 根據json建立model
public class Order
{
    public long server_time { get; set; }
    public List<OrderItem> orders { get; set; }
}
public class OrderItem { 
    /// <summary>
    /// 快遞單號
    /// </summary>
    public string tracking_number { get; set; }
    /// <summary>
    /// 訂單編碼
    /// </summary>
    public string order_sn { get; set; }
    /// <summary>
    /// 快遞公司ID
    /// </summary>
    public string shipping_id { get; set; }
    /// <summary>
    /// 訂單狀態 4為已收貨
    /// </summary>
    public int status { get; set; }
    /// <summary>
    /// 訂單金額
    /// </summary>
    public int display_amount { get; set; }
}
  • 獲取返回json,拿到最後一個的訂單編碼然後重新請求,直到訂單查完
if (request.Method.Equals("POST")&&request.Url.Contains("order_list"))
{
    var filter = FilterManager.GetFileter(request.Identifier.ToString()) as TestJsonFilter;
    if (filter==null)
    {
        return;
    }
    ASCIIEncoding encoding = new ASCIIEncoding();
    //這裡截獲返回的資料
    var data = encoding.GetString(filter.DataAll.ToArray());
    var orderList= JsonConvert.DeserializeObject<Order>(data);
    if (orderList.orders!=null&& orderList.orders.Count!=0)
    {
        Thread.Sleep(1000);
        FilterManager.AddOrder(orderList);
        //反向排序
        orderList.orders.Reverse();
        //獲取第一個
        var order=orderList.orders.FirstOrDefault();
        string json = "{\"timeout\":1300,\"type\":\"all\",\"page\":1,\"pay_channel_list\":[\"9\",\"30\",\"31\",\"35\",\"38\",\"52\",\"97\",\"122\",\"135\",\"322\",\"-1\"],\"origin_host_name\":\"mobile.yangkeduo.com\",\"size\":10,\"offset\":\"#offset#\"}";
        json=json.Replace("#offset#", order.order_sn);
        chromiumWebBrowser.Navigate(Encoding.Default.GetBytes(json), request);
    }
}

匯出Excel

引用NOPI進行匯出,將List轉為DataTable

開源地址

點我前往github