私はあなたがファイルをダウンロードする前にログインが必要なサイトを持っています。現在、私はログインにBrowserSessionクラスを使用しており、必要なすべてのスクラップを実行しています(少なくともほとんどの場合)。
投稿の下にあるBrowserSessionクラスのソース:
ダウンロードリンクは、ドキュメントノードに表示されます。しかし、私はそのクラスにダウンロード機能を追加する方法がわかりません.WebClientでそれらをダウンロードしようとすると失敗します。私はすでにBrowserSessionクラスを大幅に変更しなければなりませんでした(私は、 t)だから、私は実際にBrowserSessionクラスの使用を変更したくありません。
私はhtmlAgilityPack.HtmlWebを使ってウェブページをダウンロードして読み込むと信じています。
BrowserSessionを簡単に変更する方法がない場合は、CookieCollectionをWebclientで使用する方法がありますか?
PS:ファイルをダウンロードするにはログインする必要があります。そうしないと、リンクがログイン画面にリダイレクトされます。 WebClientを単に使用することができず、ダウンロードできるようにBrowserSessionクラスを変更するか、ページを取得する前にCookieを使用するようWebClientを変更する必要があります。
私はCookieをよく理解していないことを認めます(GETが使用されるたびに、またはPOST時に使用されるかどうかはわかりませんが)。
PPS:私が投稿した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);
}
}
私は、BrowserSessionと変更されたWebClientを使用して、それを動作させることができました:
最初にドキュメントノードにアクセスするには、_htmlDocをPublicに変更します。
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このクラスをどこかに追加すると、BrowserSessionからWebClientにCookieを渡すことができます。
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であるかのようにCookieのみを設定しますそのようです:
Using(wc = new CookieAwareWebClient())
{
wc.Cookies = BrowserSession.Cookies
//Download with WebClient As normal
wc.DownloadFile();
}
ログインしてWebページをダウンロードするのは簡単ではありません。私は最近、同じ問題を抱えています。あなたが解決策を見つけたら、それを提供してください。
今私がしたことは、PhantomJSでSeleniumを使ったことでした。セレンを使って、自分が選んだウェブブラウザとやりとりすることができます。
また、ブラウザクラスでは、Nugetを通じて利用可能なサードパーティのライブラリであるHtml Agility Packは使用されません。
私はこれにあなたを参照したい質問私はHTMLDocumentのをダウンロードして、XPathを使用して、必要な情報をフィルタリングするセレン及び方法を使用する方法の全体の例を作成しました、。