1 写在前面
最近想要在百度网盘里面搜索一些pdf资源,打开以前保存的一个专门搜索百度网盘资源的页面so.baiduyun.me
,页面转了好久,终于出来,但是出现的却是Error 522,链接失效了。最后,在网上找到一个可以用的地址http://pan.java1234.com/
,这个地址确实可以搜索百度网盘资源,但是广告超级多,稍有不慎,就进入了一个广告页面,神烦。当时就想能不能寻找到这个网页中资源搜索的地址,然后自己根据这个地址来模拟请求,从而获得查询结果。打开浏览器的调试工具,随意输入一个关键字进行查询,点击查询,然后进行分析。分析发现了一个url请求返回的正是百度网盘搜索结果,数据是json格式。找到了这个获取搜索结果url之后就好办了。我们可以完全自己写一个Winform界面,然后通过这个url去模拟请求,获取结果,这样就没有广告了,想怎么弄就怎么弄,下面介绍一下,如何完成这一系列的过程。
2 分析
2.1 获取请求头信息
实现这个程序的关键就是如何获取http://pan.java1234.com/
百度网盘搜索结果的url,首先我们打开这个页面,启动浏览器调试,然后随意输入一个关键字,点击查询。
上图我们可以看到,有一个请求url,返回来的结果就是页面上显示的搜索结果。我们可以看看它的请求地址以及请求头信息。
通过查看headers面板可以知道请求信息如下:
- 请求地址:http://pan1234.com/server3?jsoncallback=jQuery19109864917922941505_1478436979648&q=win7&start=0&_=1478436979649
- User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36
- Reference:http://pan.java1234.com/result2.jsp?wp=0&op=0&ty=gn&q=win7
- Host:pan1234.com
知道请求地址,user-agent,host,referer请求头信息,我们就可以构造出一个搜索资源的请求,现在我们来分析一下这个请求地址的特点,这个请求地址有一个查询参数q=win7
,而我们知道先前在搜索框里面输入的关键字就是win7,由此可以判断,该查询参数代表的搜索关键字。我们可以把这个请求地址在浏览器中打开,然后去去更改这些查询参数,来分析这些查询参数各有什么作用。
经过分析,请求地址中的q参数代表的是搜索关键字;start参数代表的是搜索页面,一共有10页,0代表第一页,10代表第二页,···,90代表第十页,该网页最高显示100条资源结果;而最后的&_=1478436979649可以删掉,在请求中没有实质的作用。
2.2 分析返回的搜索结果格式
经过2.1节分析,我们知道搜索结果的url地址,现在我们随意的构造一个如下。
http://pan1234.com/server3?jsoncallback=jQuery19109864917922941505_1478436979648&q=win7&start=0
在浏览器中显示的效果如下:
我们可以知道搜索结果是以json字符串的格式返回的。返回的是一个对象数组,每个资源对象都包含了title
,content
,unescapedUrl
三个属性。
知道了返回的json格式结构,我们就可以在c#中建立相对应的类,然后将这些json数据经过预处理,之后便可以反序列化成为相对应的对象。
3.程序实现
下面将贴出实现该程序的关键代码,源代码可以到本文章的末尾自行下载。
3.1 数据实体类
1 2 3 4 5 6 7 8 9 10 11 |
public class SearchResult { public BDWPResource[] resources { get; set; } } public class BDWPResource { public string title { get; set; } public string content { get; set; } public string unescapedUrl { get; set; } } |
3.2 数据请求及预处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
class HttpHelper { static readonly string urlTemplate = "http://pan1234.com/server3?jsoncallback=jQuery191042552483269501273_1478315152726&q={0}&start={1}"; public static SearchResult Requset(string key, string start) { string url = string.Format(urlTemplate, key, start); HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(url); httpRequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"; httpRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36"; httpRequest.Host = "pan1234.com"; httpRequest.Referer = "http://pan.java1234.com/result.jsp?wp=0&op=0&ty=gn&q=" + Uri.EscapeUriString(key); try { HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse(); Stream s = httpResponse.GetResponseStream(); StreamReader sr = new StreamReader(s); string jsonString = sr.ReadToEnd(); string jsonProcessed = null; if ((jsonProcessed = JsonPreProcessing(jsonString)) != null) { SearchResult searchResult = UtilityClass.GetObject<SearchResult>(jsonProcessed); return searchResult; } return null; } catch { return null; } } public static string JsonPreProcessing(string jsonString) { int startIndex = jsonString.IndexOf("("); if (startIndex > 0) { string json = jsonString.Substring(startIndex + 1); return "{\"resources\":" + json.Remove(json.Length - 3) + "}"; } else { return null; } } } |
3.3 json数据反序列化对象
1 2 3 4 5 6 7 8 9 10 |
class UtilityClass { public static T GetObject<T>(string json) { DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T)); MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json)); T obj = (T)serializer.ReadObject(ms); return obj; } } |
3.4 界面
界面设计如下:
将网络请求的代码放到任务线程中进行执行。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
Thread thread = new Thread(() => { for (int i = 0; i < 100; i += 10) { if (isSearch) { SearchResult sr = HttpHelper.Requset(key, i.ToString()); if (sr != null) { foreach (BDWPResource resource in sr.resources) { BindResource(resource); } } } else break; } //搜索完成 SearchOver(); }); thread.IsBackground = true; thread.Start(); //绑定数据代码 private void BindResource(BDWPResource resource) { string title = resource.title.Replace("</b>", "").Replace("<b>",""); string content = resource.content.Replace("</b>", "").Replace("<b>", ""); this.Invoke(new Action<string, string, string>((tle, ctt, url) => { this.dataGridView1.Rows.Add(tle, ctt, url); this.lblResult.Text = (Int32.Parse(this.lblResult.Text) + 1).ToString(); this.pgsBar.Value++; }), title, content, resource.unescapedUrl); } //搜索完成 private void SearchOver() { this.Invoke(new Action(() => { this.btnSearch.Text = "开始搜索"; this.btnSearch.Enabled = true; this.btnStop.Enabled = false; this.isSearch = true; })); } |
3.5 程序运行结果
4 结论
该程序搜索速度有时候比较慢,有时间快,刚开始点击搜索一般都要等一会才有结果,可能有网络延迟的原因。但发现搜索一会还没结果的时候,可以先停止搜索,然后再点击开始搜索,就会有搜索结果出来了。
转自:https://www.cnblogs.com/mingjiatang/p/6036558.html