百度登录 - 续3

进展:可以批量获取下载链接了。递归就是眨眼间的事。

yunData.sign2()commonService.base64Encode() 就基本上照抄了,除了结合 .NET 的做了一点点优化。话说本来看到第二步的函数名称是 base64Encode,就直接用了 System.Convert.ToBase64String()。结果出来的和百度的标准大相径庭,遂照抄了百度的代码。(还没深刻理解,同时还不明白为什么会出现这样的不同。即使是 System.Text.Encoding.UTF8.GetBytes() 也不应该影响,毕竟获得的源就是单字节的字符串。)输入两组数据测试通过。

在获取 DLink 列表的时候,两个错误值:

  • 2 表示 fsid 列表为空。
  • 113(似乎是这个数值,忘了保存结果了)表示签名错误。

在获取真实地址的时候要经过一次从 http://d.pcs.baidu.com/ 来的302跳转。之前按理说获得了指向 http://d.pcs.baidu.com/ 的链接,直接发起 GET 请求不就好了?但是我得到的一直是403。我以为是普通情况(手工下载也不时会遇到403),用了一个循环,结果每次都是403;又以为是访问过于频繁,延迟了一下还是403。于是仔细看浏览器发起的请求并在 Fiddler 中伪造之,是可以正常下载的。那么,问题一定就出在请求头上。是哪里伪装得不对呢?

最后尝试的结果是 cookie 中的一项 pcsett,有正确的参数才能避免403。现在好了,这个 cookie 是在哪里设置的呢?

由于在浏览器中无法查看所有的 cookie 及其有效域,所以只好继续借助 Fiddler。用 IE 设置 Fiddler 为代理,从零开始访问百度盘,实际开始一次下载流程;接着过滤掉 Fiddler 中明显无用的项(普通的几个域在调试的时候看过,没有有效项)。最后发现是第一次访问 pcs.baidu.com 的一个 RESTful API 的时候,服务器返回了一个 Set-Cookie 标头,设置的正是 pcsett

补上这一步,终于能避开403,拥抱302了。

接下来就准备做 Host 映射了,一个粗糙的原型就要出来了。我觉得。


我正在做的软件是要告诉他们:我本来就是做技术的,我最有力的武器不是被称作“静候圣音”的东西,而是技术。如果各位官老爷继续闭门不见的话,我会用优雅的方式开另一条路。


7月9日:

脑中灵光一闪,突然想到了一个解释 Base64 编码失败的问题。应该就是 System.Text.Encoding.UTF8.GetBytes() 上。查阅 UTF-8 编码规范得,有些字符起到了“分隔”所属区域的作用,例如分隔单字节字符、双字节字符和三字节字符。想想如果恰好碰到了某个这样的字符,那么我这个所有组成串的字符都是单字节字符的字符串就会被识别为一个夹杂着多种长度字符的字符串,假如在 UTF-8 编码表里真的有对应字符的话。

那么,就应该要让程序知道,我使用的是一个单字节字符组成的字符串。所以我想到了 HTTP 所使用的常用单字节编码:ISO-8859-1(又名 Latin-1)。调用代码如下。

var latin1Encoding = Encoding.GetEncoding("ISO-8859-1");
// sign0 是经过 yunData.sign2() 函数处理的字符串
var sign = Convert.ToBase64String(latin1Encoding.GetBytes(sign0));
// 对比:之前所使用的是
// var sign = Convert.ToBase64String(Encoding.UTF8.GetBytes(sign0));

然后查看 sign 的值,与所需的是一致的。这证实了我的猜测。

分享到 评论