c#动态生成网站将接受的cookie
本文关键字:cookie 网站 动态 | 更新日期: 2023-09-27 18:11:47
我尝试了网上所有相关的解决方案,但由于某种原因,它们都不起作用。这也不起作用:c# - HttpWebRequest POST(登录到Facebook),因为我们使用不同的方法。
我没有使用POST方法,而是在请求中使用的GET方法。我使用的网站不需要任何登录凭据来获取图像。(该网站拥有的大多数其他根域不需要cookie。)
下面的代码是我想让程序像基于web的版本一样获得图像的一部分,但是有一些问题。
之前,我试图使用一个正常的WebClient下载图像,因为它拒绝以任何方式显示,PictureBox控件将接受。但后来我切换到HttpWebRequest。
我试图从中获取图像的网站的特定根域需要cookie,但是
下面是一个代码片段,它基本上试图从网站获取图像。唯一的问题是,几乎不可能从网站获得图像,除非您在HttpWebRequest中传递一些东西,以及cookie。
现在,我使用静态cookie作为临时解决方案。
HttpWebRequest _request = (HttpWebRequest)HttpWebRequest.Create(_URL);
_request.Method = WebRequestMethods.Http.Get;
_request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
_request.Headers.Set(HttpRequestHeader.AcceptEncoding, "gzip,deflate,sdch");
_request.Headers.Set(HttpRequestHeader.AcceptLanguage, "en-US,en;q=0.8");
_request.Headers.Set(HttpRequestHeader.CacheControl, "max-age=0");
_request.Host = "www.habbo" + _Country;
_request.UserAgent = "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36";
using (WebResponse _response = _request.GetResponse())
using (Stream _stream = _response.GetResponseStream())
{
Image _image = Image.FromStream(_stream);
_bitmap = new Bitmap(_image);
string contentType = _response.ContentType;
_PictureBox.Image = _bitmap;
}
我们设以下变量为:
_URL = "http://www.habbo.com/habbo-imaging/avatarimage?hb=img&user=aa&direction=2&head_direction=2&size=m&img_format=gif";
_Country = ".com";
我传递到HttpWebRequest的大部分内容都是通过查看Google Chrome的开发人员工具的网络选项卡获得的。
基于网络的Habbo Imager似乎只是将人们引导到他们可以找到图像的页面,而他们的浏览器似乎以某种方式添加了cookie。我所做的是不同的,因为他们所做的就是显示图像所在的网站,但我想找到图像的真实位置,然后从它读取到image类型。
显然,网站似乎需要用户"访问"他们,根据我从这篇文章中读到的:点击这里
我想知道的是,是否有更好的方法来获得一个有效的cookie,服务器将愉快地接受每次?
或者我是否需要以某种方式欺骗网站,使其认为用户已经访问并看到了该页面,从而使他们可能返回我们可能需要的cookie,即使用户从未看到过该页面?
不太确定这是否意味着我需要以某种方式动态生成cookie。
我也不明白如何使用c#真正创建或获取cookie(并设置存储的cookie),所以如果可能的话,请使用一些示例。
我宁愿不使用任何第三方库,或者改变我使用太多的代码。程序也不会发送两个GET请求,只是为了能够获得一个GET请求所能获得的东西。因此,这不会工作:传递cookie与HttpWebRequest在winforms?
我使用的是。net 4.0。
这比乍一看预期的要复杂一点。浏览器实际上会进行两次调用。第一个返回一个html脚本,其中包含一小段javascript,该脚本在执行时设置cookie并重新加载页面。在你的c#代码中,你必须模仿它。
在表单类中添加一个实例变量来保存多个httpwebrequest调用中的所有cookie:
readonly CookieContainer cookiecontainer = new CookieContainer();
我已经创建了一个Builder方法来创建HttpWebRequest并返回一个HttpWebResponse。它需要一个namevaluecollection来将任何cookie添加到cookie容器中。
private HttpWebResponse Builder(string url, string host, NameValueCollection cookies)
{
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
request.Method = WebRequestMethods.Http.Get;
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
// _request.Headers.Set(HttpRequestHeader.AcceptEncoding, "gzip,deflate,sdch");
request.Headers.Set(HttpRequestHeader.AcceptLanguage, "en-US,en;q=0.8");
request.Headers.Set(HttpRequestHeader.CacheControl, "max-age=0");
request.Host = host;
request.UserAgent = "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36";
request.CookieContainer = cookiecontainer;
if (cookies != null)
{
foreach (var cookiekey in cookies.AllKeys)
{
request.CookieContainer.Add(
new Cookie(
cookiekey,
cookies[cookiekey],
@"/",
host));
}
}
return (HttpWebResponse) request.GetResponse();
}
如果传入流是text/html内容类型,我们需要解析其内容并返回cookie名称和值。Parse方法就是这样做的:
// find in the html and return the three parameters in a string array
// setCookie('YPF8827340282Jdskjhfiw_928937459182JAX666', '127.0.0.1', 10);
private static string[] Parse(Stream _stream, string encoding)
{
const string setCookieCall = "setCookie('";
// copy html as string
var ms = new MemoryStream();
_stream.CopyTo(ms);
var html = Encoding.GetEncoding(encoding).GetString(ms.ToArray());
// find setCookie call
var findFirst = html.IndexOf(
setCookieCall,
StringComparison.InvariantCultureIgnoreCase) + setCookieCall.Length;
var last = html.IndexOf(");", findFirst, StringComparison.InvariantCulture);
var setCookieStatmentCall = html.Substring(findFirst, last - findFirst);
// take the parameters
var parameters = setCookieStatmentCall.Split(new[] {','});
for (int x = 0; x < parameters.Length; x++)
{
// cleanup
parameters[x] = parameters[x].Replace("'", "").Trim();
}
return parameters;
}
现在我们的构建模块已经完成,我们可以开始从Click方法调用我们的方法。我们使用循环两次调用Builder以从给定的url获取结果。根据接收到的内容类型,我们从流中解析或创建图像。
private void button1_Click(object sender, EventArgs e)
{
var cookies = new NameValueCollection();
for (int tries = 0; tries < 2; tries++)
{
using (var response = Builder(_URL, "www.habbo" + _Country, cookies))
{
using (var stream = response.GetResponseStream())
{
string contentType = response.ContentType.ToLowerInvariant();
if (contentType.StartsWith("text/html"))
{
var parameters = Parse(stream, response.CharacterSet);
cookies.Add(parameters[0], parameters[1]);
}
if (contentType.StartsWith("image"))
{
pictureBox1.Image = Image.FromStream(stream);
break; // we're done, get out
}
}
}
}
}
注意事项
此代码适用于您的问题中的url。我没有采取任何措施来处理其他模式和/或异常。这是由你来决定的。此外,在进行这种抓取时,请确保网站所有者允许这样做。