0

我在做什么:
我正在开发一个“webscraper”(多线程),就是这样,哈哈。
我需要在从页面中提取数据之前提交一个表单,所以布局是这样的:

  1. 对 example.com/path/doc.jsp(我的数据)的 GET 请求。
  2. 检查确认表单是否存在于文档源中。如果是则继续步骤 3(我的数据不存在,需要先提交表单),否则返回(因为没有要提交的表单,我的数据在这里)。
  3. 对 example.com/path/sub/other.jsp 的 GET 请求(必要的键值)。
  4. 对 example.com/path/submit.jsp 的 POST 请求(发送值)。
  5. 检查 POST 请求的响应,如果正常则转到 6,否则返回 1。
  6. 对 example.com/path/doc.jsp 的 GET 请求(我的数据,再次。由于我提交了表单,现在我的数据将出现)。

一切正常,除非来自 POST 请求(第 4 步)的响应告诉我返回第 1 步。

问题:
表单中的值之一我需要从 cookie 中提取它,所以我使用该GetCookies()函数,但是,就像我说的,如果响应告诉我返回第 1 步,则所有请求(GET 和 POST ) 之后缺少 cookie(并添加了奇怪的 cookie)。见下图:

Cookie 错误
图片说明:

  • 第一个调用是对我的数据所在的 doc.jsp 的 GET 请求。
  • 第二个调用是 other.jsp 请求,因为确认表单存在于 doc.jsp 源代码中。
  • 第三次调用是当我提交所有值时。
  • 第四个调用是再次对 doc.jsp 的 GET 请求,因为提交表单(第三个调用)的响应告诉我重复该过程。基本上,4º ~ 6º 调用与 1º ~ 3º 相同,但带有 cookie fu**ed。


我的代码:

public class CWeb : IDisposable
{
    private WebClientEx _wc;
    private string _originalUrl;

    public CWeb()
    {
        _wc = new WebClientEx(new CookieContainer());
    }

    public string downloadPage(string url)
    {
        _originalUrl = url;
        string pgSrc = "error";
        int tries = 0;

        while (tries < 3 && pgSrc == "error)
        {
            try
            {
                pgSrc = _wc.DownloadString(url);
            }
            catch (Exception err)
            {
                tries += 1;
                pgSrc = "error";
                ...
            }
        }

        if (needSubmit(pgSrc)) // needSubmit just peform IndexOf on pgSrc
            do
            {
                pgSrc = sendForm(pgSrc);
            } while (needSubmit(pgSrc));

        return WebUtility.HtmlDecode(pgSrc);
    }

    public string sendForm(pageSource)
    {
        // 1- Get Cookie Value
        string cookie = _wc.CookieContainer.GetCookies(new Uri(_originalUrl))["JSESSIONID"].Value;

        // 2- Get hidden values in pageSource parameter
        // skip this, since there's no web request here, only some html parsing
        // with Html Agility Pack
        ...

        // 3- Get key value
        string tmpStr = _wc.DownloadString("http://example.com/path/sub/other.jsp");
        ... more html parsing ...

        // 4- Build form
        NameValueCollection nvc = new NameValueCollection();
        nvc["param1"] = cookie;
        nvc["param2"] = key;
        ...

        // 5- Send
        _wc.UploadValues("example.com/path/submit.jsp", nvc);

        // 6- Return
        return _wc.DownloadString(_originalUrl);
    }

    public void Dispose()
    {
        _wc.Dispose();
    }
}


主程序:

static void Main(string[] args)
{
    // Load tons of 'doc' url list from database...
    List<string> urls = new List<string>();
    ...

    Parallel.ForEach(urls, (url) =>
        {
            using (CWeb crawler = new CWeb())
            {
                string pageData = crawler.downloadPage(url);
                ... parse html data here ...
            }
        });
}


我的环境:

  • 使用 Visual Studio 专业版 2013。
  • 目标框架是 .NET Framework 4.5。
  • 平台 x86(调试)。
  • WebClientEx 是 WebClient 的扩展版本,用于处理 cookie。在这里获取它PasteBin。我试图实现BugFix_CookieDomain()(来自这个问题),但即使有这个修复,这个问题仍然存在。
  • 我所有的网址都包含 http:// 前缀。

  • 使用 Fiddler 查看请求信息。

  • 英语不是我的母语...'-'
4

1 回答 1

0

我将System.Net.WebRequest用于类似于您正在做的事情。它在使用 Http(WebRequest 的 HttpWebRequest 子类)时通过名为 CookieContainer 的属性处理 cookie。我注意到 cookie 被添加并且显然也从 cookie 容器中删除。我的信念是,这完全由服务器端(您正在向其发出请求的 Web 应用程序)控制。它能够添加额外的 cookie。

此外,如果 cookie 具有到期日期、丢弃标志和域,那么如果到期日期已过,服务器会设置丢弃标志,或者域更改,适用的 cookie 列表可能会更改。

不确定这是否有帮助,但我尝试。

于 2016-01-11T23:37:31.040 回答