The custom error module does not recognize this error в результате POST-запроса

206
22 января 2019, 06:10

Пытаюсь спарсить сайт https://emex.ru. Собираю запрос так же, как он представлен в браузере:

public async Task<string> GetEventListData(string detailNum, string requestVerificationToken, string sessionId)
{
    FormUrlEncodedContent content = new FormUrlEncodedContent(new[]
    {
        new KeyValuePair<string, string>("detailNum", detailNum),
        new KeyValuePair<string, string>("loadingGroupId", ""),
        new KeyValuePair<string, string>("packetId", "-1"),
        new KeyValuePair<string, string>("locationId", "17883"),
        new KeyValuePair<string, string>("deliveryType", ""),
        new KeyValuePair<string, string>("isFirstLoading", "true"),
        new KeyValuePair<string, string>("sessionId", sessionId),
        new KeyValuePair<string, string>("latitude", "57.9984"),
        new KeyValuePair<string, string>("longitude", "56.2591"),
        new KeyValuePair<string, string>("geoCoordsType", "Location"),
        new KeyValuePair<string, string>("__RequestVerificationToken", requestVerificationToken),
    });
    return await SendEventListRequest("/Find2/Find/FindByDetailNum", content);
}

И далее отправляю его:

public async Task<string> SendEventListRequest(string url, FormUrlEncodedContent content = null)
{
    Uri baseAddress = new Uri("https://emex.ru");
    CookieContainer cookieContainer = new CookieContainer();
    foreach (string c in
        "best-location=4481; __RequestVerificationToken=7OCgvyozf0gUnLj6ptYdjEQGf4mgcCLeQPno12tMQiDdK1Wnco07eeiK3YCtvBOPcWXdm3Nhg4LBx_bYoZS0uUXszoqMZNudJ4to1SnixjitRmyLEzmaXe3jpPqy16rk-b62di2CjGT6jHkWgU03GQ2; NSC_xxx.fnfy.sv=ffffffffc3a01c1f45525d5f4f58455e445a4a423652; _ga=GA1.2.1487574528.1538146273; _ym_uid=1538146273636665587; _ym_d=1538146273; current-location=17883; isBestLocationDetected=true; current-region-long-lat=%257B%2522Id%2522%253A1658%252C%2522Name%2522%253A%2522%25D0%259F%25D0%25B5%25D1%2580%25D0%25BC%25D1%258C%2522%252C%2522EmexName%2522%253A%2522%25D0%259F%25D0%25B5%25D1%2580%25D0%25BC%25D1%258C%2522%252C%2522Longitude%2522%253A56.234195%252C%2522Latitude%2522%253A58.010259%252C%2522AreaId%2522%253A1683%252C%2522AreaName%2522%253A%2522%25D0%259F%25D0%25B5%25D1%2580%25D0%25BC%25D1%2581%25D0%25BA%25D0%25B8%25D0%25B9%2520%25D0%25BA%25D1%2580%25D0%25B0%25D0%25B9%2522%252C%2522CountryId%2522%253A3%252C%2522CountryName%2522%253A%2522%25D0%25A0%25D0%25BE%25D1%2581%25D1%2581%25D0%25B8%25D1%258F%2522%257D; current-position=%257B%2522X%2522%253A%252256.2591%2522%252C%2522Y%2522%253A%252257.9984%2522%252C%2522type%2522%253A%2522Location%2522%252C%2522source%2522%253A%2522CurrentLocation%2522%252C%2522fixed%2522%253Afalse%257D; _gid=GA1.2.951665973.1538303681; _ym_isad=1"
            .Split(';'))
        cookieContainer.Add(baseAddress, new Cookie(c.Split('=')[0].Trim(), c.Split('=')[1].Trim()));
    using (HttpClientHandler handler = new HttpClientHandler() /*{CookieContainer = cookieContainer}*/)
        using (HttpClient client = new HttpClient(handler) {BaseAddress = baseAddress})
        {
            client.DefaultRequestHeaders.Add("User-Agent",
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36");
            HttpResponseMessage result = await client.PostAsync(url, content);
            return await result.Content.ReadAsStringAsync();
        }
}

В итоге, возвращается код 418 и сообщение "The custom error module does not recognize this error.". Пробовал добавить cookie, но эффекта нет. Как выйти решить проблему?

Answer 1

Вы зачем то закомментировали Cookie, вот тут:

using (HttpClientHandler handler = new HttpClientHandler() /*{CookieContainer = cookieContainer}*/)

Также очень не советую Вам делать что то вроде

foreach (string c in "best-location=4481...куча текста...".Split(';'))
    cookieContainer.Add(baseAddress, new Cookie(c.Split('=')[0].Trim(), c.Split('=')[1].Trim()));

Во первых не нужно отправлять так много!
Во вторых, Cookie зачастую неизменны, меняются их значения, но не кол-во или что то подобное, зачем тогда цикл? Да, вы можете получить новую куку при запросе, но лучше сохранять их в CookieContainer и дальше работать с ней, а не брать string значение и "парсить" его!

Теперь помогу вам с запросом и покажу, что 80% из запроса попросту можно выкинуть. Зачастую, достаточно 1-2 значений, что бы сайт выдал нам что то. У вас к примеру авторизация - это __RequestVerificationToken, отправив его, сайт уже не будет "шутить" над вами и говорить, что он чайник, а просто выдаст 500'ю ошибку (неожиданные условия). Давайте поэкспериментируем с запросом:

  1. Скачиваем Postman.
  2. Запускаем его и создаем в точности идентичный запрос, который отправляет наш браузер, указываем адрес, тип запроса.
  3. Получаем ответ 200 (OK).
  4. Теперь в этой красивой обертке (я про Postman), смотрим внимательней на те данные, которые мы отправляем и выясняем то, что является мусором, а что нет (для удобства можно убрать галку рядом с параметром и отправить повторный запрос). В итоге получаем следующее:
    • [заголовок] Content-Type - данные отправляются в application/x-www-form-urlencoded.
    • [тело] detailNum - Id детали
    • [тело] geoCoordsType - Location (тип координат)
    • [тело] latitude/longitude - широта/долгота, координаты выбранного магазина.
    • [тело] __RequestVerificationToken - токен от CSRF атак.
    • [cookie] __RequestVerificationToken - аналогично предыдущему.

Как видим, 80% мы попросту можем не слать, серверу не нужен UserAgent, sessionId или что то еще, достаточно отправить локацию, id и токен.

В общем удачи и научитесь общаться с такими системами на "ты", они это любят ;-)

READ ALSO
WPF: добавить элемент в ObservableCollection&lt;T&gt; через IEnumerable

WPF: добавить элемент в ObservableCollection<T> через IEnumerable

Такая дилемма: у меня есть эдакий "ItemsSource" в моем элементе управленияDependencyProperty типа IEnumerable

162
Поворот оружия в сторону Touch на Unity

Поворот оружия в сторону Touch на Unity

Каким образом сделать, так чтобы оружие моего персонажа дулом было повернуто в сторону моего пальца (тача) и следило за ним, когда вожу по экрану

160
WPF NotifyIcon. Как привязать метод к LeftClickCommand

WPF NotifyIcon. Как привязать метод к LeftClickCommand

Подскажите, как привязать в TaskbarIcon метод из MainWindow (а не из отдельного класса команд)Пример от разработчика показывает как привязать из отдельного...

174
Редактирование реестра пользователя в \HKEY_USERS\&lt;SID пользователя&gt;\. Загрузка куста пользователя

Редактирование реестра пользователя в \HKEY_USERS\<SID пользователя>\. Загрузка куста пользователя

Необходимо изменить/прочитать/добавить переменную Shell в реестре Windows по пути \HKEY_USERS\\Software\Microsoft\Windows NT\CurrentVersion\Winlogon для каждого пользователяОднако...

158