2015-09-06 17 views
5

Tôi sử dụng htmlagility để nhận dữ liệu trang web nhưng tôi đã thử mọi thứ với trang bằng cách sử dụng bảo vệ www.cloudflare.com cho ddos. Trang chuyển hướng là không thể xử lý trong htmlagility bởi vì họ không chuyển hướng với meta cũng không js tôi đoán, họ kiểm tra xem bạn đã được kiểm tra với một cookie mà tôi đã không mô phỏng với C#. Khi tôi nhận được trang, mã html là từ trang cloadflare đích.Tôi làm cách nào để nhận html từ trang có cổng ddos ​​cloudflare?

+0

Truyền cookie http: // stackoverflow.com/a/20478716/736079 – jessehouwing

+0

Bạn cũng có thể sử dụng lớp BrowserSession như được giải thích tại đây: http://refactoringaspnet.blogspot.nl/2010/04/using-htmlagilitypack-to-get-and-post.html – jessehouwing

Trả lời

-1

Sử dụng WebClient để có được html của trang,
tôi đã viết sau lớp mà xử lý các tập tin cookie quá,
Chỉ cần vượt qua CookieContainer dụ trong constructor.

using System; 
using System.Collections.Generic; 
using System.Configuration; 
using System.Linq; 
using System.Net; 
using System.Text; 

namespace NitinJS 
{ 
    public class SmsWebClient : WebClient 
    { 
     public SmsWebClient(CookieContainer container, Dictionary<string, string> Headers) 
      : this(container) 
     { 
      foreach (var keyVal in Headers) 
      { 
       this.Headers[keyVal.Key] = keyVal.Value; 
      } 
     } 
     public SmsWebClient(bool flgAddContentType = true) 
      : this(new CookieContainer(), flgAddContentType) 
     { 

     } 
     public SmsWebClient(CookieContainer container, bool flgAddContentType = true) 
     { 
      this.Encoding = Encoding.UTF8; 
      System.Net.ServicePointManager.Expect100Continue = false; 
      ServicePointManager.MaxServicePointIdleTime = 2000; 
      this.container = container; 

      if (flgAddContentType) 
       this.Headers["Content-Type"] = "application/json";//"application/x-www-form-urlencoded"; 
      this.Headers["Accept"] = "application/json, text/javascript, */*; q=0.01";// "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"; 
      //this.Headers["Accept-Encoding"] = "gzip, deflate"; 
      this.Headers["Accept-Language"] = "en-US,en;q=0.5"; 
      this.Headers["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1; rv:23.0) Gecko/20100101 Firefox/23.0"; 
      this.Headers["X-Requested-With"] = "XMLHttpRequest"; 
      //this.Headers["Connection"] = "keep-alive"; 
     } 

     private readonly CookieContainer container = new CookieContainer(); 

     protected override WebRequest GetWebRequest(Uri address) 
     { 
      WebRequest r = base.GetWebRequest(address); 
      var request = r as HttpWebRequest; 
      if (request != null) 
      { 
       request.CookieContainer = container; 
       request.Timeout = 3600000; //20 * 60 * 1000 
      } 
      return r; 
     } 

     protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult result) 
     { 
      WebResponse response = base.GetWebResponse(request, result); 
      ReadCookies(response); 
      return response; 
     } 

     protected override WebResponse GetWebResponse(WebRequest request) 
     { 
      WebResponse response = base.GetWebResponse(request); 
      ReadCookies(response); 
      return response; 
     } 

     private void ReadCookies(WebResponse r) 
     { 
      var response = r as HttpWebResponse; 
      if (response != null) 
      { 
       CookieCollection cookies = response.Cookies; 
       container.Add(cookies); 
      } 
     } 
    } 
} 

SỬ DỤNG:

CookieContainer cookies = new CookieContainer(); 
SmsWebClient client = new SmsWebClient(cookies); 
string html = client.DownloadString("http://www.google.com"); 
+0

Nhưng isn ' vấn đề ở đây là một vấn đề hoàn toàn khác? Anh ta không thể truy cập trang vì bảo vệ chống dDoS của Cloudflare chuyển hướng anh ta đến một trang khác. Sử dụng một lớp WebClient tự động lưu trữ các tập tin cookie không giúp anh ta. Hay là 'this.Headers [" X-Requested-With "] =" XMLHttpRequest ";' phá vỡ toàn bộ các bảo vệ chống dDoS của Cloudflare? –

+0

'Tiêu đề' cần được sửa đổi, tôi đề nghị OP đăng nhập yêu cầu từ trình duyệt của mình bằng cách sử dụng trình duyệt và sửa đổi tiêu đề cho phù hợp. Tôi hy vọng bằng cách sử dụng vấn đề lớp này sẽ được giải quyết. –

+0

Vấn đề này không chỉ là về cookie. Như @MaximilianGerhardt giải thích trong câu trả lời của mình, bạn phải giải quyết một thử thách JavaScript để vượt qua biện pháp chống DDoS của CloudFlare. –

5

Tôi cũng gặp phải vấn đề này một thời gian trước. Giải pháp thực sự sẽ giải quyết những thách thức mà các trang web cloudflare cung cấp cho bạn (bạn cần tính toán câu trả lời đúng bằng javascript, gửi lại và sau đó bạn nhận được cookie/mã thông báo mà bạn có thể tiếp tục xem trang web). Vì vậy, tất cả các bạn sẽ nhận được thường là một trang như

cloudflare

Cuối cùng, tôi chỉ gọi là một con trăn-kịch bản với một vỏ thực thi. Tôi đã sử dụng các mô-đun được cung cấp trong phạm vi this github fork. Điều này có thể phục vụ như là một điểm khởi đầu để thực hiện việc phá vỡ trang chống dDoS của cloudflare trong C#.

FYI, tập lệnh python tôi đã viết cho mục đích sử dụng cá nhân của mình vừa viết cookie trong một tệp. Tôi đọc lại sau đó bằng cách sử dụng C# và lưu trữ nó trong một CookieJar để tiếp tục duyệt trang trong C#.

#!/usr/bin/env python 
import cfscrape 
import sys 

scraper = cfscrape.create_scraper() # returns a requests.Session object 
fd = open("cookie.txt", "w") 
c = cfscrape.get_cookie_string(sys.argv[1]) 
fd.write(str(c)) 
fd.close() 
print(c) 

EDIT: Để lặp lại điều này, điều này chỉ có LITTLE để làm với cookie! Cloudflare buộc bạn phải giải quyết một thử thách REAL bằng cách sử dụng các lệnh javascript. Nó không dễ dàng như việc chấp nhận một cookie và sử dụng nó sau này. Hãy xem https://github.com/Anorov/cloudflare-scrape/blob/master/cfscrape/init.py và ~ 40 dòng mô phỏng javascript để giải quyết thử thách.

Chỉnh sửa2: Thay vì viết gì đó để tránh sự bảo vệ, tôi cũng thấy mọi người sử dụng đối tượng trình duyệt chính thức (đây là không phải là trình duyệt không có đầu) để truy cập trang web và đăng ký các sự kiện nhất định trang được tải. Sử dụng lớp WebBrowser để tạo cửa sổ trình duyệt nhỏ thông thường và đăng ký các sự kiện thích hợp.

Chỉnh sửa3: Được rồi, tôi thực sự đã triển khai cách C# để thực hiện việc này. Này sử dụng JavaScript Engine Jint cho .NET, có sẵn thông qua https://www.nuget.org/packages/Jint

Mã cookie xử lý là xấu xí vì đôi khi các lớp HttpResponse sẽ không nhận cookie, mặc dù tiêu đề chứa một phần Set-Cookie.

using System; 
using System.Net; 
using System.IO; 
using System.Text.RegularExpressions; 
using System.Web; 
using System.Collections; 
using System.Threading; 

namespace Cloudflare_Evader 
{ 
    public class CloudflareEvader 
    { 
     /// <summary> 
     /// Tries to return a webclient with the neccessary cookies installed to do requests for a cloudflare protected website. 
     /// </summary> 
     /// <param name="url">The page which is behind cloudflare's anti-dDoS protection</param> 
     /// <returns>A WebClient object or null on failure</returns> 
     public static WebClient CreateBypassedWebClient(string url) 
     { 
      var JSEngine = new Jint.Engine(); //Use this JavaScript engine to compute the result. 

      //Download the original page 
      var uri = new Uri(url); 
      HttpWebRequest req =(HttpWebRequest) WebRequest.Create(url); 
      req.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0"; 
      //Try to make the usual request first. If this fails with a 503, the page is behind cloudflare. 
      try 
      { 
       var res = req.GetResponse(); 
       string html = ""; 
       using (var reader = new StreamReader(res.GetResponseStream())) 
        html = reader.ReadToEnd(); 
       return new WebClient(); 
      } 
      catch (WebException ex) //We usually get this because of a 503 service not available. 
      { 
       string html = ""; 
       using (var reader = new StreamReader(ex.Response.GetResponseStream())) 
        html = reader.ReadToEnd(); 
       //If we get on the landing page, Cloudflare gives us a User-ID token with the cookie. We need to save that and use it in the next request. 
       var cookie_container = new CookieContainer(); 
       //using a custom function because ex.Response.Cookies returns an empty set ALTHOUGH cookies were sent back. 
       var initial_cookies = GetAllCookiesFromHeader(ex.Response.Headers["Set-Cookie"], uri.Host); 
       foreach (Cookie init_cookie in initial_cookies) 
        cookie_container.Add(init_cookie); 

       /* solve the actual challenge with a bunch of RegEx's. Copy-Pasted from the python scrapper version.*/ 
       var challenge = Regex.Match(html, "name=\"jschl_vc\" value=\"(\\w+)\"").Groups[1].Value; 
       var challenge_pass = Regex.Match(html, "name=\"pass\" value=\"(.+?)\"").Groups[1].Value; 

       var builder = Regex.Match(html, @"setTimeout\(function\(\){\s+(var t,r,a,f.+?\r?\n[\s\S]+?a\.value =.+?)\r?\n").Groups[1].Value; 
       builder = Regex.Replace(builder, @"a\.value =(.+?) \+ .+?;", "$1"); 
       builder = Regex.Replace(builder, @"\s{3,}[a-z](?: = |\.).+", ""); 

       //Format the javascript.. 
       builder = Regex.Replace(builder, @"[\n\\']", ""); 

       //Execute it. 
       long solved = long.Parse(JSEngine.Execute(builder).GetCompletionValue().ToObject().ToString()); 
       solved += uri.Host.Length; //add the length of the domain to it. 

       Console.WriteLine("***** SOLVED CHALLENGE ******: " + solved); 
       Thread.Sleep(3000); //This sleeping IS requiered or cloudflare will not give you the token!! 

       //Retreive the cookies. Prepare the URL for cookie exfiltration. 
       string cookie_url = string.Format("{0}://{1}/cdn-cgi/l/chk_jschl", uri.Scheme, uri.Host); 
       var uri_builder = new UriBuilder(cookie_url); 
       var query = HttpUtility.ParseQueryString(uri_builder.Query); 
       //Add our answers to the GET query 
       query["jschl_vc"] = challenge; 
       query["jschl_answer"] = solved.ToString(); 
       query["pass"] = challenge_pass; 
       uri_builder.Query = query.ToString(); 

       //Create the actual request to get the security clearance cookie 
       HttpWebRequest cookie_req = (HttpWebRequest) WebRequest.Create(uri_builder.Uri); 
       cookie_req.AllowAutoRedirect = false; 
       cookie_req.CookieContainer = cookie_container; 
       cookie_req.Referer = url; 
       cookie_req.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0"; 
       //We assume that this request goes through well, so no try-catch 
       var cookie_resp = (HttpWebResponse)cookie_req.GetResponse(); 
       //The response *should* contain the security clearance cookie! 
       if (cookie_resp.Cookies.Count != 0) //first check if the HttpWebResponse has picked up the cookie. 
        foreach (Cookie cookie in cookie_resp.Cookies) 
         cookie_container.Add(cookie); 
       else //otherwise, use the custom function again 
       { 
        //the cookie we *hopefully* received here is the cloudflare security clearance token. 
        if (cookie_resp.Headers["Set-Cookie"] != null) 
        { 
         var cookies_parsed = GetAllCookiesFromHeader(cookie_resp.Headers["Set-Cookie"], uri.Host); 
         foreach (Cookie cookie in cookies_parsed) 
          cookie_container.Add(cookie); 
        } 
        else 
        { 
         //No security clearence? something went wrong.. return null. 
         //Console.WriteLine("MASSIVE ERROR: COULDN'T GET CLOUDFLARE CLEARANCE!"); 
         return null; 
        } 
       } 
       //Create a custom webclient with the two cookies we already acquired. 
       WebClient modedWebClient = new WebClientEx(cookie_container); 
       modedWebClient.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0"); 
       modedWebClient.Headers.Add("Referer", url); 
       return modedWebClient; 
      } 
     } 

     /* Credit goes to https://stackoverflow.com/questions/15103513/httpwebresponse-cookies-empty-despite-set-cookie-header-no-redirect 
      (user https://stackoverflow.com/users/541404/cameron-tinker) for these functions 
     */ 
     public static CookieCollection GetAllCookiesFromHeader(string strHeader, string strHost) 
     { 
      ArrayList al = new ArrayList(); 
      CookieCollection cc = new CookieCollection(); 
      if (strHeader != string.Empty) 
      { 
       al = ConvertCookieHeaderToArrayList(strHeader); 
       cc = ConvertCookieArraysToCookieCollection(al, strHost); 
      } 
      return cc; 
     } 

     private static ArrayList ConvertCookieHeaderToArrayList(string strCookHeader) 
     { 
      strCookHeader = strCookHeader.Replace("\r", ""); 
      strCookHeader = strCookHeader.Replace("\n", ""); 
      string[] strCookTemp = strCookHeader.Split(','); 
      ArrayList al = new ArrayList(); 
      int i = 0; 
      int n = strCookTemp.Length; 
      while (i < n) 
      { 
       if (strCookTemp[i].IndexOf("expires=", StringComparison.OrdinalIgnoreCase) > 0) 
       { 
        al.Add(strCookTemp[i] + "," + strCookTemp[i + 1]); 
        i = i + 1; 
       } 
       else 
        al.Add(strCookTemp[i]); 
       i = i + 1; 
      } 
      return al; 
     } 

     private static CookieCollection ConvertCookieArraysToCookieCollection(ArrayList al, string strHost) 
     { 
      CookieCollection cc = new CookieCollection(); 

      int alcount = al.Count; 
      string strEachCook; 
      string[] strEachCookParts; 
      for (int i = 0; i < alcount; i++) 
      { 
       strEachCook = al[i].ToString(); 
       strEachCookParts = strEachCook.Split(';'); 
       int intEachCookPartsCount = strEachCookParts.Length; 
       string strCNameAndCValue = string.Empty; 
       string strPNameAndPValue = string.Empty; 
       string strDNameAndDValue = string.Empty; 
       string[] NameValuePairTemp; 
       Cookie cookTemp = new Cookie(); 

       for (int j = 0; j < intEachCookPartsCount; j++) 
       { 
        if (j == 0) 
        { 
         strCNameAndCValue = strEachCookParts[j]; 
         if (strCNameAndCValue != string.Empty) 
         { 
          int firstEqual = strCNameAndCValue.IndexOf("="); 
          string firstName = strCNameAndCValue.Substring(0, firstEqual); 
          string allValue = strCNameAndCValue.Substring(firstEqual + 1, strCNameAndCValue.Length - (firstEqual + 1)); 
          cookTemp.Name = firstName; 
          cookTemp.Value = allValue; 
         } 
         continue; 
        } 
        if (strEachCookParts[j].IndexOf("path", StringComparison.OrdinalIgnoreCase) >= 0) 
        { 
         strPNameAndPValue = strEachCookParts[j]; 
         if (strPNameAndPValue != string.Empty) 
         { 
          NameValuePairTemp = strPNameAndPValue.Split('='); 
          if (NameValuePairTemp[1] != string.Empty) 
           cookTemp.Path = NameValuePairTemp[1]; 
          else 
           cookTemp.Path = "/"; 
         } 
         continue; 
        } 

        if (strEachCookParts[j].IndexOf("domain", StringComparison.OrdinalIgnoreCase) >= 0) 
        { 
         strPNameAndPValue = strEachCookParts[j]; 
         if (strPNameAndPValue != string.Empty) 
         { 
          NameValuePairTemp = strPNameAndPValue.Split('='); 

          if (NameValuePairTemp[1] != string.Empty) 
           cookTemp.Domain = NameValuePairTemp[1]; 
          else 
           cookTemp.Domain = strHost; 
         } 
         continue; 
        } 
       } 

       if (cookTemp.Path == string.Empty) 
        cookTemp.Path = "/"; 
       if (cookTemp.Domain == string.Empty) 
        cookTemp.Domain = strHost; 
       cc.Add(cookTemp); 
      } 
      return cc; 
     } 
    } 

    /*Credit goes to https://stackoverflow.com/questions/1777221/using-cookiecontainer-with-webclient-class 
(user https://stackoverflow.com/users/129124/pavel-savara) */ 
    public class WebClientEx : WebClient 
    { 
     public WebClientEx(CookieContainer container) 
     { 
      this.container = container; 
     } 

     public CookieContainer CookieContainer 
     { 
      get { return container; } 
      set { container = value; } 
     } 

     private CookieContainer container = new CookieContainer(); 

     protected override WebRequest GetWebRequest(Uri address) 
     { 
      WebRequest r = base.GetWebRequest(address); 
      var request = r as HttpWebRequest; 
      if (request != null) 
      { 
       request.CookieContainer = container; 
      } 
      return r; 
     } 

     protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult result) 
     { 
      WebResponse response = base.GetWebResponse(request, result); 
      ReadCookies(response); 
      return response; 
     } 

     protected override WebResponse GetWebResponse(WebRequest request) 
     { 
      WebResponse response = base.GetWebResponse(request); 
      ReadCookies(response); 
      return response; 
     } 

     private void ReadCookies(WebResponse r) 
     { 
      var response = r as HttpWebResponse; 
      if (response != null) 
      { 
       CookieCollection cookies = response.Cookies; 
       container.Add(cookies); 
      } 
     } 
    } 
} 

Hàm sẽ trả về webclient với các thách thức và cookie được giải quyết bên trong. Bạn có thể sử dụng nó như sau:

static void Main(string[] args) 
{ 
    WebClient client = null; 
    while (client == null) 
    { 
     Console.WriteLine("Trying.."); 
     client = CloudflareEvader.CreateBypassedWebClient("http://anilinkz.tv"); 
    } 
    Console.WriteLine("Solved! We're clear to go"); 
     Console.WriteLine(client.DownloadString("http://anilinkz.tv/anime-list")); 

    Console.ReadLine(); 
} 
+2

Gần đây tôi đã phải giải quyết cùng một vấn đề. Là một [giải pháp] (https://github.com/elcattivo/CloudFlareUtilities), tôi đã viết một thư viện lớp di động nhỏ cho .NET, cung cấp DelegatingHandler quản lý thử thách JS tự động để bạn có thể truy cập một trang được bảo vệ bằng lớp HttpClient mà không lo lắng về sự bảo vệ của CloudFlare. Nó không phụ thuộc vào bất kỳ công cụ JS nào. –

Các vấn đề liên quan