WinInet загружает только часть веб-страницы - PullRequest
0 голосов
/ 06 июля 2018

У меня есть функция, которая загружает веб-страницу в текстовый файл

#include <iostream>
#include <string>
#include <fstream>
#include <Windows.h>
#include <WinINet.h>

#pragma comment(lib, "WinINet.lib")
void Download(wstring url)
{
    std::ofstream fout(L"temp.txt");
    HINTERNET hopen = InternetOpen(L"MyAppName",
        INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    if (hopen)
    {
        DWORD flags = INTERNET_FLAG_DONT_CACHE;
        if (url.find(L"https://") == 0)
            flags |= INTERNET_FLAG_SECURE;
        HINTERNET hinternet = InternetOpenUrl(hopen, url.c_str(), NULL, 0, flags, 0);
        if (hinternet)
        {
            char buf[1024];
            DWORD received = 0;
            while (InternetReadFile(hinternet, buf, sizeof(buf), &received))
            {
                if (!received) break;
                fout.write(buf, received);
            }
            InternetCloseHandle(hinternet);
        }
        InternetCloseHandle(hopen);
    }
    return;
}

когда я даю "https://camelcamelcamel.com/Lodge-LMS3-Miniature-Skillet/product/B000LXA9YI" в качестве параметра выводятся только https://hastebin.com/gilomexomu.xml (слишком большой, чтобы положить сюда) и это отрезает большую часть веб-страницы. Я не уверен, есть ли какой-нибудь антивирусный скрипт на сайте или он просто слишком большой.

1 Ответ

0 голосов
/ 06 июля 2018

Это не твой код. Это веб-сайт. И я считаю, что он может доставлять только сжатые данные GZIP В противном случае он разорвется после нескольких килобайт данных. curl показывает, что веб-сайт прерывает передачу преждевременно:

$ curl https://camelcamelcamel.com/Lodge-LMS3-Miniature-Skillet/product/B000LXA9YI -o text.txt
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 15725    0 15725    0     0   4702      0 --:--:--  0:00:03 --:--:--  4702
curl: (18) transfer closed with outstanding read data remaining

Итак, я сделал две вещи, чтобы лучше эмулировать веб-браузер с вашим кодом

  1. Установите те же заголовки и пользовательский агент, что и в браузере.
  2. Поскольку кажется, что этот веб-сайт хочет только вернуть кодировку gzip, мне пришлось настроить код сохранения файла, сохранить его как двоичный файл вместо текста (что приводит к тому, что Windows CRT неправильно «исправляет» символы разрыва строки).

Затем, чтобы декодировать весь HTML, я просто запускаю это из командной строки Bash:

gunzip < temp.txt > temp_final.txt

В результате файл temp_final.txt имеет полный html-ответ.

Вот подправленный код:

#include <iostream>
#include <string>
#include <fstream>
#include <Windows.h>
#include <WinINet.h>

#pragma comment(lib, "WinINet.lib")
void Download(const std::wstring& url)
{
    FILE* file = fopen("temp.txt", "wb");
    HINTERNET hopen = InternetOpen(L"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36",
        INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    if (hopen)
    {
        DWORD flags = INTERNET_FLAG_DONT_CACHE;
        if (url.find(L"https://") == 0)
            flags |= INTERNET_FLAG_SECURE;

        LPCWSTR headers = L"User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36\r\n"
L"DNT: 1\r\n"
L"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n"
L"Accept-Encoding: gzip, deflate, br\r\n"
L"Accept-Language: en-US,en;q=0.9\r\n";


        HINTERNET hinternet = InternetOpenUrl(hopen, url.c_str(), headers, 0, flags, 0);
        if (hinternet)
        {
            char buf[1024+1]={};
            DWORD received = 0;
            while (InternetReadFile(hinternet, buf, 1024, &received))
            {
                if (!received) break;

                printf("%d\n", received);

                fwrite(buf, 1, received, file);
            }
            InternetCloseHandle(hinternet);
        }
        InternetCloseHandle(hopen);
    }
    return;
}

void main()
{
    Download(L"https://camelcamelcamel.com/Lodge-LMS3-Miniature-Skillet/product/B000LXA9YI");
}

Я попытался поиграть, убрав Accept-Encoding или установив его в «identity». В результате сервер отправляет обратно половину страницы, а затем прерывается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...