Это ошибка CookieContainer?
Что я делаю:
Я разрабатываю "многопоточный", вот и все, смеется.
Мне нужно отправить форму перед извлечением данных со страницы, поэтому макет такой:
- ПОЛУЧИТЕ запрос к example.com/path/doc.jsp (мои данные).
- Проверьте, присутствует ли форма подтверждения в источнике документа. Если да, перейдите к шагу 3 (мои данные отсутствуют, сначала нужно отправить форму), в противном случае верните (поскольку формы для отправки нет и мои данные здесь).
- Получите запрос к example.com/path/sub/other.jsp (необходимое значение ключа).
- POST-запрос к example.com/path/submit.jsp (отправить значения).
- Проверьте ответ от запроса POST, если все в порядке, перейдите к 6, иначе вернитесь к 1.
- ПОЛУЧИТЕ запрос к example.com/path/doc.jsp (мои данные, опять же. Поскольку я отправил форму, теперь мои данные будут присутствовать).
Все работает нормально, за исключением случаев, когда ответ на запрос POST (шаг 4) говорит мне вернуться к шагу 1.
Эта проблема:
Одно из значений в форме мне нужно, чтобы извлечь его из файлов cookie, поэтому я использую GetCookies()
функции, но, как я уже сказал, если ответ говорит мне вернуться к шагу 1, ВСЕ запросы (как GET, так и POST) после этого пропускают файлы cookie (и добавляются странные). Смотрите изображение ниже:
- Первый вызов - это запрос GET к doc.jsp, где находятся мои данные.
- Вторым вызовом является запрос other.jsp, так как форма подтверждения присутствует в исходном коде doc.jsp.
- Третий вызов - когда я отправляю все значения.
- Четвертый вызов - это снова запрос GET к doc.jsp, поскольку ответ формы отправки (третий вызов) велел мне повторить процесс. По сути, вызовы 4º ~ 6º совпадают с вызовами 1º ~ 3º, но с cookie-файлами.
Мой код:
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 Professional 2013.
- Целевой платформой является.NET Framework 4.5.
- Платформа x86 (отладка).
- WebClientEx - это расширенная версия WebClient для работы с файлами cookie. Получите это здесь PasteBin. Я пытался реализовать
BugFix_CookieDomain()
(из этого вопроса), но даже с этим исправлением эта проблема все еще возникает. Все мои URL включают префикс http: //.
Использовал Fiddler для просмотра информации о запросах.
- Английский не мой родной язык... '-'
1 ответ
Я использую System.Net.WebRequest для чего-то похожего на то, что вы делаете. Он обрабатывает куки-файлы при использовании Http (подкласс HttpWebRequest в WebRequest) через свойство CookieContainer. Я заметил, что файлы cookie добавляются и, очевидно, также удаляются из контейнера для файлов cookie. Я считаю, что это полностью контролируется серверной стороной (веб-приложением, к которому вы обращаетесь). Он способен добавлять дополнительные куки.
Кроме того, если у файлов cookie есть дата истечения срока действия, флаг сброса и домен, поэтому, если истекает срок действия файлов cookie, сервер устанавливает флаг сброса или домен меняет список, и список применимых файлов cookie может измениться.
Не уверен, что это полезно, но я стараюсь.