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 資料實體類
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 資料請求及預處理
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資料反序列化對象
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 界面
界面設計如下:
将網絡請求的代碼放到任務線程中進行執行。代碼如下:
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 結論
該程式搜尋速度有時候比較慢,有時間快,剛開始點選搜尋一般都要等一會才有結果,可能有網絡延遲的原因。但發現搜尋一會還沒結果的時候,可以先停止搜尋,然後再點選開始搜尋,就會有搜尋結果出來了。
5 資源
源代碼下載下傳連結:http://download.csdn.net/download/mingge38/9674694