2015-11-12 2 views
0

У меня есть сайт, который требует входа в систему, прежде чем он позволит вам скачивать файлы. В настоящее время я использую класс BrowserSession для входа и выполнения всех необходимых скрепов (по крайней мере, по большей части).Можно ли использовать «BrowserSession» для загрузки файлов? C#

источник класса BrowserSession в нижней части поста:

ссылки для скачивания показать на узлах документа. Но я не знаю, как добавить функциональность загрузки к этому классу, и если я попытаюсь загрузить их с помощью веб-клиента, это не сработает, мне уже пришлось сильно модифицировать класс BrowserSession (я должен был изменить его как часть, но didn ' t) Таким образом, я действительно не хочу переходить от использования класса BrowserSession.

Я считаю, что он использует htmlAgilityPack.HtmlWeb для загрузки и загрузки веб-страниц.

Если нет простого способа изменить BrowserSession, можно ли каким-то образом использовать CookieCollection с Webclient?

PS: Мне нужно войти в систему, чтобы загрузить файл. В противном случае ссылка перенаправляется на экран входа в систему. Вот почему я не могу просто использовать WebClient и должен либо модифицировать класс BrowserSession для загрузки, либо изменить WebClient для использования файлов cookie перед тем, как получить страницу.

Я признаю, что я не очень хорошо разбираюсь в куках (я не уверен, что они используются каждый раз, когда используется GET, или если его просто на POST), но до сих пор BrowserSession позаботился обо всем этом.

PPS: The BrowserSession, который я написал, не является тем, что я добавил, но все же основные функции одинаковы.

public class BrowserSession 
{ 
private bool _isPost; 
private HtmlDocument _htmlDoc; 

/// <summary> 
/// System.Net.CookieCollection. Provides a collection container for instances of Cookie class 
/// </summary> 
public CookieCollection Cookies { get; set; } 

/// <summary> 
/// Provide a key-value-pair collection of form elements 
/// </summary> 
public FormElementCollection FormElements { get; set; } 

/// <summary> 
/// Makes a HTTP GET request to the given URL 
/// </summary> 
public string Get(string url) 
{ 
    _isPost = false; 
    CreateWebRequestObject().Load(url); 
    return _htmlDoc.DocumentNode.InnerHtml; 
} 

/// <summary> 
/// Makes a HTTP POST request to the given URL 
/// </summary> 
public string Post(string url) 
{ 
    _isPost = true; 
    CreateWebRequestObject().Load(url, "POST"); 
    return _htmlDoc.DocumentNode.InnerHtml; 
} 

/// <summary> 
/// Creates the HtmlWeb object and initializes all event handlers. 
/// </summary> 
private HtmlWeb CreateWebRequestObject() 
{ 
    HtmlWeb web = new HtmlWeb(); 
    web.UseCookies = true; 
    web.PreRequest = new HtmlWeb.PreRequestHandler(OnPreRequest); 
    web.PostResponse = new HtmlWeb.PostResponseHandler(OnAfterResponse); 
    web.PreHandleDocument = new HtmlWeb.PreHandleDocumentHandler(OnPreHandleDocument); 
    return web; 
} 

/// <summary> 
/// Event handler for HtmlWeb.PreRequestHandler. Occurs before an HTTP request is executed. 
/// </summary> 
protected bool OnPreRequest(HttpWebRequest request) 
{ 
    AddCookiesTo(request);    // Add cookies that were saved from previous requests 
    if (_isPost) AddPostDataTo(request); // We only need to add post data on a POST request 
    return true; 
} 

/// <summary> 
/// Event handler for HtmlWeb.PostResponseHandler. Occurs after a HTTP response is received 
/// </summary> 
protected void OnAfterResponse(HttpWebRequest request, HttpWebResponse response) 
{ 
    SaveCookiesFrom(response); // Save cookies for subsequent requests 
} 

/// <summary> 
/// Event handler for HtmlWeb.PreHandleDocumentHandler. Occurs before a HTML document is handled 
/// </summary> 
protected void OnPreHandleDocument(HtmlDocument document) 
{ 
    SaveHtmlDocument(document); 
} 

/// <summary> 
/// Assembles the Post data and attaches to the request object 
/// </summary> 
private void AddPostDataTo(HttpWebRequest request) 
{ 
    string payload = FormElements.AssemblePostPayload(); 
    byte[] buff = Encoding.UTF8.GetBytes(payload.ToCharArray()); 
    request.ContentLength = buff.Length; 
    request.ContentType = "application/x-www-form-urlencoded"; 
    System.IO.Stream reqStream = request.GetRequestStream(); 
    reqStream.Write(buff, 0, buff.Length); 
} 

/// <summary> 
/// Add cookies to the request object 
/// </summary> 
private void AddCookiesTo(HttpWebRequest request) 
{ 
    if (Cookies != null && Cookies.Count > 0) 
    { 
     request.CookieContainer.Add(Cookies); 
    } 
} 

/// <summary> 
/// Saves cookies from the response object to the local CookieCollection object 
/// </summary> 
private void SaveCookiesFrom(HttpWebResponse response) 
{ 
    if (response.Cookies.Count > 0) 
    { 
     if (Cookies == null) Cookies = new CookieCollection(); 
     Cookies.Add(response.Cookies); 
    } 
} 

/// <summary> 
/// Saves the form elements collection by parsing the HTML document 
/// </summary> 
private void SaveHtmlDocument(HtmlDocument document) 
{ 
    _htmlDoc = document; 
    FormElements = new FormElementCollection(_htmlDoc); 
} 
} 

FormElementCollection Класс:

/// <summary> 
/// Represents a combined list and collection of Form Elements. 
/// </summary> 
public class FormElementCollection : Dictionary<string, string> 
{ 
/// <summary> 
/// Constructor. Parses the HtmlDocument to get all form input elements. 
/// </summary> 
public FormElementCollection(HtmlDocument htmlDoc) 
{ 
    var inputs = htmlDoc.DocumentNode.Descendants("input"); 
    foreach (var element in inputs) 
    { 
     string name = element.GetAttributeValue("name", "undefined"); 
     string value = element.GetAttributeValue("value", ""); 
     if (!name.Equals("undefined")) Add(name, value); 
    } 
} 

/// <summary> 
/// Assembles all form elements and values to POST. Also html encodes the values. 
/// </summary> 
public string AssemblePostPayload() 
{ 
    StringBuilder sb = new StringBuilder(); 
    foreach (var element in this) 
    { 
     string value = System.Web.HttpUtility.UrlEncode(element.Value); 
     sb.Append("&" + element.Key + "=" + value); 
    } 
    return sb.ToString().Substring(1); 
} 
} 

ответ

0

мне удалось получить его работу, используя BrowserSession и модифицированный WebClient:

Во-первых Изменение _htmlDoc для доступа общественности к Узлов документа:

public class BrowserSession 
{ 
    private bool _isPost; 
    public string previous_Response { get; private set; } 
    public HtmlDocument _htmlDoc { get; private set; } 
} 

Во-вторых Добавить этот метод BrowserSession:

public void DownloadCookieProtectedFile(string url, string Filename) 
    { 
     using (CookieAwareWebClient wc = new CookieAwareWebClient()) 
     { 
      wc.Cookies = Cookies; 
      wc.DownloadFile(url, Filename); 
     } 
    } 
//rest of BrowserSession 

Third Добавить этот класс Где-то, что позволяет передавать файлы cookie из BrowserSession в WebClient.

public class CookieAwareWebClient : WebClient 
{ 
    public CookieCollection Cookies = new CookieCollection(); 
    private void AddCookiesTo(HttpWebRequest request) 
    { 
     if (Cookies != null && Cookies.Count > 0) 
     { 
      request.CookieContainer.Add(Cookies); 
     } 
    } 

    protected override WebRequest GetWebRequest(Uri address) 
    { 
     WebRequest request = base.GetWebRequest(address); 
     HttpWebRequest webRequest = request as HttpWebRequest; 
     if (webRequest != null) 
     { 
      if (webRequest.CookieContainer == null) webRequest.CookieContainer = new CookieContainer(); 
      AddCookiesTo(webRequest); 
     } 
     return request; 
    } 
} 

Это должно дать вам возможность использовать BrowserSession Как обычно, и когда вам нужно получить файл, который вы можете только доступ Если ваш авторизованы, просто позвоните BrowserSession.DownloadCookieProtectedFile() Как будто это было WebClient, только Установите Куки так:

Using(wc = new CookieAwareWebClient()) 
{ 
    wc.Cookies = BrowserSession.Cookies 
    //Download with WebClient As normal 
    wc.DownloadFile(); 
} 
0

Это не просто войти в систему и загрузки веб-страниц. У меня недавно была такая же проблема. Если вы найдете решение aisde из этого, предоставьте его.

Теперь, что я сделал, я использовал Selenium с PhantomJS. С Selenium я могу взаимодействовать с веб-браузером по своему выбору.

Также класс Browser не использует Html Agility Pack, который является сторонней библиотекой, доступной через nuget.

Я хочу направить вас к этому question, где я создал целый пример использования Selenium и как загрузить HtmlDocument и отфильтровать необходимую информацию с помощью xpath.

+0

Браузер классов не использует Html Agility Pack, но 'BrowserSession' делает (класс я отправил выше). Кроме того, я действительно справился с этой работой. Но я не смог дать полезный ответ, поскольку он был немного запутанным. Я подниму решение, в котором я закончил, немного позже. –

+0

Я добавил решение, с которым я пришел. Это не очень хорошо, но он работает нормально. (До сих пор у меня не было никаких проблем) Хотя у меня есть только один браузер, активированный. –

Смежные вопросы