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。

c#动态生成网站将接受的cookie

这比乍一看预期的要复杂一点。浏览器实际上会进行两次调用。第一个返回一个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。我没有采取任何措施来处理其他模式和/或异常。这是由你来决定的。此外,在进行这种抓取时,请确保网站所有者允许这样做。