使用不同的本機IP地址訪問目標網站
來源:程序員人生 發布時間:2014-05-08 14:32:25 閱讀次數:3680次
公司的爬蟲在爬取個別網站內容時候發現目標服務器對訪問頻率做了限制,這樣只能限制爬蟲訪問的頻率,造成了信息的滯后和數量始終上不去。于是就研究能不能讓訪問請求依次通過不同的IP地址訪問目標服務器來增大訪問的頻率。讓爬蟲在不同的服務器上運行,這是另外一種解決思路,涉及到分布式爬蟲的很多問題,不在本文討論范圍內。
Google搜索了半天,找到了一些蛛絲馬跡,發現Socket.Bind方法理論上可行。接下來就想如何干涉HttpWebRequest的這個過程。一路查看HttpWebRequest的源代碼,果然在ServicePoint中找到了BindIPEndPointDelegate屬性,這個屬性是一個名為BindIPEndPoint的代理,簽名如下:
public delegate IPEndPoint BindIPEndPoint(ServicePoint servicePoint, IPEndPoint remoteEndPoint, int retryCount);
通過設置這個屬性,可以在發出連接的時候綁定客戶端發出連接所使用的IP地址。
一個簡單的示例程序:
class MyWebClient : WebClient
{
IPEndPoint m_OutIPEndPoint;
MyWebClient(IPEndPoint outIp)
{
if (outIp == null)
throw new ArgumentNullException("outIp");
m_OutIPEndPoint = outIp;
CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);
}
protected override WebRequest GetWebRequest(Uri address)
{
var request = (HttpWebRequest)base.GetWebRequest(address);
request.ServicePoint.BindIPEndPointDelegate = (servicePoint, remoteEndPoint, retryCount) =>
{
return m_OutIPEndPoint;
};
return request;
}
public static void Run()
{
MyWebClient client2 = new MyWebClient(new IPEndPoint(IPAddress.Parse("192.168.1.105"), 0));
Console.WriteLine(client2.DownloadString("http://192.168.1.15:8000/Default.asp"));
client2.Dispose();
Thread.Sleep(ServicePointManager.MaxServicePointIdleTime);
MyWebClient client = new MyWebClient(new IPEndPoint(IPAddress.Parse("192.168.1.204"), 0));
Console.WriteLine(client.DownloadString("http://192.168.1.15:8000/"));
client.Dispose();
}
}
我在本機的網卡綁定了2個IP地址,192.168.1.105和192.168.1.204.而http://192.168.1.15:8000/Default.asp是我寫的一個測試頁面,只輸出客戶端請求的IP地址。請注意,其中有一行Thread.Sleep(ServicePointManager.MaxServicePointIdleTime);如果沒有加入這行,你會得到兩行192.168.1.105的結果,在代理那行(return m_OutIPEndPoint;)加入斷點會發現只命中了一次。加入這行以后會得到192.168.1.105和192.168.1.204這個期望的結果.
原因就得從ServicePointManager說起,這個類緩存了ServicePoint,代表了到目標的連接。只要這個連接已經存在,出去的IP地址就已經確定了,所以不會再調用BindIPEndPointDelegate來獲取出去的IP地址。加入了Thread.Sleep這行代碼,只是等待這個連接釋放,這樣再次訪問頁面時候就會重新建立連接,從新綁定出去的IP地址了。這樣做只是為了驗證本文的目的。
當然這個示例程序沒有辦法真正工作,因為爬蟲不可能休眠這么長時間,也不可能把ServicePointManager.MaxServicePointIdleTime設置為很短的時間,雖然實現了目的,但是降低了效率。這個示例程序只是揭示了使用不同IP地址訪問目標服務器的可能性和實現途徑。
出處:http://www.cnblogs.com/cesium/
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈