• 艾伟_转载:尝试通过HttpWebRequest向TAOBAO批量发布商品及上传图片 狼人:


      朋友开了个淘宝店,所以经常要将新商品及图片发布到网店里,而且有时还需要上传很多商品。如果手工一条一个商品的上传未免太花时间,所以我就琢磨着能否用WinForm写个程序通过WebRequest发送POST/GET请求来达到这个目的。由于上传上品时即有普通的Form字段信息需要提交,还需要上传图片,所以在写HttpWebRequest时参考了这个帖子http://bytes.com/topic/c-sharp/answers/268661-how-upload-file-via-c-codeHow upload file via c# code?

      在淘宝网上发布一个商品大体分为两个步骤(即两个页面,实际都是提交到同各URL进行处理的:http://sell.taobao.com//auction/publish/publish.htm),第一个步骤为选择商品的分类,第二个步骤为填写商品的信息及相关照片。

    image

     image

      通过IEInspector软件观察第二个步骤提交后的http请求的RAW Stream大致为:

    POST /auction/publish/publish.htm HTTP/1.1
    Accept: image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-fla
    sh, application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocume
    nt, application/xaml+xml, application/x-silverlight, application/vnd.ms-excel, application
    /msword, application/vnd.ms-powerpoint, */*
    Referer: http://sell.taobao.com/auction/publish/publish.htm
    Accept-Language: zh-cn
    User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 
    2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
    Content-Type: multipart/form-data; boundary=---------------------------7d9da39c0084
    Accept-Encoding: gzip, deflate
    Host: sell.taobao.com
    Content-Length: 217424
    Connection: Keep-Alive
    Cache-Control: no-cache
    Cookie: po=50008882_100.0_14_0.0_%E5%8C%.; sellTbToken=%2Ceee15ee6bb
    aee%237856351072575161%2Ce87e3fe110be1%237856331541398694

    -----------------------------7d9da39c0084
    Content-Disposition: form-data; name="action"

    publish/publishAction
    -----------------------------7d9da39c0084
    Content-Disposition: form-data; name="isMImageUser"

    -----------------------------7d9da39c0084
    Content-Disposition: form-data; name="_fma.pu._0.ca"

    50008882
    -----------------------------7d9da39c0084
    Content-Disposition: form-data; name="_fma.pu._0.i"

    NDczYzE0MjI3Yzc4ZTczOGI2ZGQ3ZjJiYThjMGZkYWEgYjc2MGM1MDBjYWVjYmFlN2I0MzRlZ
    jQwZTIzOGI0NWIgMTI1NTc1MDA0NjQwNA==
    -----------------------------7d9da39c0084

    -----------------------------7d9da39c0084
    Content-Disposition: form-data; name="_fma.pu._0.ima"; filename="DSC_6873.JPG"
    Content-Type: image/pjpeg

    …..

      所以在做这个http请求前,我们需要先准备好几个东西,即Cookie值、_fma.pu._0.i值和sellTbToken的值。

      获取Cookie值最理想的办法就是用WebHttpRequest模拟登录过程向服务器发出包含用户名和密码的Http请求,等服务器登录成功后HttpResponse里包含的Set-Cookie部分就有我们要找的Cookie值。由于现在TaoBao的登录页面输入密码部分采用了插件方式,好像在发出请求前插件会生成一个Token之类的,所以简单的WebHttpRequest发送登录请求达不到我们的目的,至于他的登录安全加密过程具体是怎么回事,我也没有足够时间去探个究竟,只好放弃了这个获取Cookie的方式。最后索性用最原始的方法,即在web页面上登录TaoBao,然后用IEInspector来跟踪返回的数据包,将其中的Cookie部分copy出来直接用就可以了。

        image

      接下来就是获取_frma.pu._0.i的值了,其实这个值是干什么用的我也不知道。通过观察,发现这个值最初出现的地方是用GET请求URLhttp://sell.taobao.com//auction/publish/publish.htm?auction_type=b&auth_alert=true后返回的HTML文本里,是以hidden的input形式出现的。所以我就在代码里模拟这个过程并解析出这个值:

        private string GetFmaPu_0i()
    {
    string actionUrl = "http://sell.taobao.com//auction/publish/publish.htm?auction_ty
    pe=b&auth_alert=true";
    HttpWebRequest httpWebRequest
    = WebRequest.Create(actionUrl) as HttpWebR
    equest;
    httpWebRequest.Method
    = "GET";
    httpWebRequest.Headers[
    "Cookie"] = txtCookie.Text;

    WebResponse webResponse
    = httpWebRequest.GetResponse();
    Stream stream
    = webResponse.GetResponseStream();
    StreamReader rd
    = new StreamReader(stream, Encoding.GetEncoding("gb231
    2"));
    string ouptText = rd.ReadToEnd();

    rd.Close();
    webResponse.Close();

    string startStr = "<input type=\"hidden\" name=\"_fma.pu._0.i\" value=\"";
    int startPos = ouptText.IndexOf(startStr) + startStr.Length;
    int endPos = ouptText.IndexOf("\" />", startPos);
    return ouptText.Substring(startPos, endPos - startPos);
    }

      对于sellTbToken值的意义我也不明白,只是看名字好像是一个Token。虽然在Cookie里我也发现了一个sellTbToken,但他们的值是不一样的,我没有发现他们之间的联系,例如,在Cookie里的sellTbToken值是%2C33d58361b5b7%2312446852732896952%2Ce337766ee471f%2312317842106832544%2Cebd13373eed76%2312317854579307544%2Cfe3e333de58e6%2313206186303479904%efd65353b8377%239822969650842632%2Cb5b5e7bb31ae%2312957211756764136%2Ce7e883bdd77e3%237273521182867360%2Ce8b1374b13bee%2313038885937950800%2C5780d773e5075%2312322949035362088%2C715735e53ed3b%237439832831399704,而第二步请求中Post Data里sellTbToken的值是5be7931b93e57#9260334924738040。我们要找的这个sellTbToken的值是在填写商品相信信息页面的hidden input里的,所以还是通过httpWebRequest发出POST请求并解析HTML来得到这个值:

    private string GetSellTbToken(string fmaPu_0i)
    {
    string actionUrl = "http://sell.taobao.com/auction/publish/publish.htm";

    NameValueCollection paras
    = new NameValueCollection();
    paras.Add(
    "_fma.pu._0.ca", "50008882");
    paras.Add(
    "_fma.pu._0.cat", "20000%3A29973");
    paras.Add(
    "action", "publish%2FpublishAction");
    paras.Add(
    "event_submit_do_input_auction_info", "1");
    paras.Add(
    "_fma.pu._0.i", fmaPu_0i);
    paras.Add(
    "_fma.pu._0.x", "");
    paras.Add(
    "_fma.pu._0.a", "b");
    paras.Add(
    "_fma.pu._0.t", "");
    paras.Add(
    "_fma.pu._0.pi", "");
    paras.Add(
    "isEdit", "");
    paras.Add(
    "isHaveImageExtra", "");
    paras.Add(
    "_fma.pu._0.cat", "20000%3A29973");
    paras.Add(
    "_fma.pu._0.d", "");
    paras.Add(
    "_fma.pu._0.q", "10");
    paras.Add(
    "_fma.pu._0.du", "14");
    paras.Add(
    "_fma.pu._0.stu", "5");
    paras.Add(
    "_fma.pu._0.m", "");
    paras.Add(
    "_fma.pu._0.bu", "0");
    paras.Add(
    "_fma.pu._0.in", "0.0");
    paras.Add(
    "_fma.pu._0.pro", "%B1%B1%BE%A9");
    paras.Add(
    "_fma.pu._0.c", "%B1%B1%BE%A9");
    paras.Add(
    "_fma.pu._0.sh", "1");
    paras.Add(
    "_fma.pu._0.se", "0.0");
    paras.Add(
    "_fma.pu._0.sec", "0.0");
    paras.Add(
    "_fma.pu._0.secu", "0.0");
    paras.Add(
    "_fma.pu._0.pa", "%BF%EE%B5%BD%B7%A2%BB%F5");
    paras.Add(
    "_fma.pu._0.h", "0");
    paras.Add(
    "_fma.pu._0.ha", "0");
    paras.Add(
    "_fma.pu._0.secur", "1");
    paras.Add(
    "_fma.pu._0.r", "A");
    paras.Add(
    "_fma.pu._0.auc", "0");
    paras.Add(
    "_fma.pu._0.st", "");
    paras.Add(
    "_fma.pu._0.sto", "");
    paras.Add(
    "_fma.pu._0.e", "false");
    paras.Add(
    "_fma.pu._0.fr", "");
    paras.Add(
    "_fma.pu._0.sho", "%2C143119754%2C");
    paras.Add(
    "_fma.pu._0.aut", "false");
    paras.Add(
    "_fma.pu._0.b", "100.0");
    paras.Add(
    "oldDesc", "");
    paras.Add(
    "oldStory", "");
    paras.Add(
    "productRootCat", "");
    paras.Add(
    "productId", "");
    paras.Add(
    "oldCat", "");
    paras.Add(
    "oldSpuId", "");
    paras.Add(
    "oldCategoryProperty", "");
    paras.Add(
    "_fma.pu._0.isa", "false");
    paras.Add(
    "_fma.pu._0.po", "2047393");
    paras.Add(
    "_fma.pu._0.an", "false");
    paras.Add(
    "_fma.pu._0.o", "");
    paras.Add(
    "_fma.pu._0.auct", "0.0");
    paras.Add(
    "_fma.pu._0.n", "");
    paras.Add(
    "_fma.pu._0.isn", "false");
    paras.Add(
    "_fma.pu._0.iso", "false");
    paras.Add(
    "_fma.pu._0.s", "");
    paras.Add(
    "_fma.pu._0.sk", "");
    paras.Add(
    "_fma.pu._0.gtr", "");
    paras.Add(
    "_fma.pu._0.g", "");

    StringBuilder sbData
    = new StringBuilder();
    foreach (string key in paras.Keys)
    {
    if (sbData.Length > 0)
    sbData.Append(
    "&");
    sbData.Append(String.Format(
    "{0}={1}",key,paras[key]));
    }
    sbData.Insert(
    0, "\r\n");

    HttpWebRequest httpWebRequest2
    = (HttpWebRequest)WebRequest.Create
    (actionUrl);
    httpWebRequest2.ContentType
    = "application/x-www-form-urlencoded";
    httpWebRequest2.Method
    = "POST";
    httpWebRequest2.KeepAlive
    = true;
    httpWebRequest2.Credentials
    = System.Net.CredentialCache.DefaultCredentials;
    httpWebRequest2.Headers[
    "Cookie"] = txtCookie.Text;

    Stream memStream
    = new System.IO.MemoryStream();

    byte[] btData = Encoding.UTF8.GetBytes(sbData.ToString());
    memStream.Write(btData,
    0,btData.Length);

    httpWebRequest2.ContentLength
    = memStream.Length;

    Stream requestStream
    = httpWebRequest2.GetRequestStream();

    memStream.Position
    = 0;
    byte[] tempBuffer = new byte[memStream.Length];
    memStream.Read(tempBuffer,
    0, tempBuffer.Length);
    memStream.Close();
    requestStream.Write(tempBuffer,
    0, tempBuffer.Length);
    requestStream.Close();

    WebResponse webResponse2
    = httpWebRequest2.GetResponse();

    Stream stream2
    = webResponse2.GetResponseStream();
    StreamReader reader2
    = new StreamReader(stream2, Encoding.GetEncoding
    ("gb2312"));

    // Get response
    string ouptText = reader2.ReadToEnd();

    webResponse2.Close();
    httpWebRequest2
    = null;
    webResponse2
    = null;

    string startStr = "", startPos);
    return ouptText.Substring(startPos, endPos - startPos);
    }

      前面三个值准备好了后(实际上在取后两个值的时候就需要Cookie的支持),我们就可以模拟发起第二步POST请求了,大致代码如下:

    Code


      不过没有达到预期的结果,虽然我想了很多办法折腾了一个晚上和一个上午,还是失败了。也许是publish.html在服务器端有一个特殊的机制我还没有在客户端发现。不过结果并不很重要,重要的是通过这个例子更深入理解一下http请求的格式,例如cookie、header、post data等等。

      失败之余,也发现了另外一个小小的安慰,在网上找到了‘淘宝助理’这款桌面软件,也可以很好的批量处理一些事务。

  • 相关阅读:
    Minimum Inversion Number
    作业四
    牛客小白月赛18 G Forsaken的三维数点
    The Accomodation of Students HDU
    03-Bootstrap学习
    jquery 单击和双击事件冲突解决方案
    13-JS中的面向对象
    12-关于DOM操作的相关案例
    IO多路复用
    python读取excel文件
  • 原文地址:https://www.cnblogs.com/waw/p/2157124.html
Copyright © 2020-2023  润新知