Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.67
noeine
0 / 0 / 0
Регистрация: 31.07.2013
Сообщений: 45
#1

Получение информации с сайта - C++

06.08.2013, 15:57. Просмотров 1310. Ответов 11
Метки нет (Все метки)

Подскажите пожалуйста как получить данные с сайта. На данный момент меня не интересует никакая обработка информации, я пытаюсь лишь получить в программу исходный код страницы, но при попытке сделать это, у меня всегда в конце массива остается мусор. Подскажите как с этим бороться:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <Windows.h>
#include <WinInet.h>
#pragma comment ( lib, "Wininet.lib" )
 
#include<iostream>
#include<cstring>
 
 
using namespace std;
int main(){
HINTERNET connect = InternetOpen("MyBrowser",INTERNET_OPEN_TYPE_PRECONFIG,NULL, NULL, 0);
 
   if(!connect){
      cout<<"Connection Failed or Syntax error";
      return 0;
   }
 
HINTERNET OpenAddress = InternetOpenUrl(connect,"http://www.myip.ru/ru-RU/index.php", NULL, 0, INTERNET_FLAG_PRAGMA_NOCACHE|INTERNET_FLAG_KEEP_CONNECTION, 0);
 
   if ( !OpenAddress )
   {
      DWORD ErrorNum = GetLastError();
      cout<<"Failed to open URL \nError No: "<<ErrorNum;
      InternetCloseHandle(connect);
      system("pause");
      return 0;
   }
 
   char DataReceived[4096]; //Определение массива заведомо бОльшего размера
   DWORD NumberOfBytesRead = 0; //ну типа скидываем количество засосанных байтов на 0, хотя в справке написано что функция сама сбрасывает их на 0 перед началом работы
   int counter=0; //Инициализируем счетчик, в который потом будет записано содержимое NumberOfBytesRead (количество прочитанных байтов)
   while(InternetReadFile(OpenAddress, DataReceived, 4096, &NumberOfBytesRead) && NumberOfBytesRead ) //Скачиваем побайтово ответ сервера
   {
        //cout << "NumofBRead" << NumberOfBytesRead;
        cout << DataReceived;
        counter = NumberOfBytesRead;
        //cout << counter << endl;
   }
   cout << endl << "Bytes Reciaved Counter="<<counter << endl; //отображаем счетчик, сколько в итоге мы получили полезных байт
   int i; //инициируем счетчик цикла
   
   char * test = new char[counter]; //вроде бы создаем указатель на массив, с размерностью = количеству полученных 
   for (i=0; i<counter; i++) { //С нулевой ячейки массива и до couter методично переносим данные из одного массива в другой, с целью получить массив без мусора, правильно законченный.
       test[i] = DataReceived[i]; //поочередно переносим каждый полезный байт из большего массива в массив заданной размерности счетчиком counter
   }
   
   cout << "v The full test char array:" << endl;
   cout << test << endl<< "^ The end of a test char array" << endl;
   cout << endl << "Data from the end of array test"<< ":"<< endl;
    cout << "test["<<counter+7<<"] ="<< test[counter+7] << endl;
    cout << "test["<<counter+6<<"] ="<< test[counter+6] << endl;
    cout << "test["<<counter+5<<"] ="<< test[counter+5] << endl;
    cout << "test["<<counter+4<<"] ="<< test[counter+4] << endl;
    cout << "test["<<counter+3<<"] ="<< test[counter+3] << endl;
    cout << "test["<<counter+2<<"] ="<< test[counter+2] << endl;
    cout << "test["<<counter+1<<"] ="<< test[counter+1] << endl;
   cout << "test["<<counter<<"] ="<< test[counter] << endl;
   cout << "test["<<counter-1<<"] ="<< test[counter-1] << endl;
   cout << "test["<<counter-2<<"] ="<< test[counter-2] << endl;
   cout << "test["<<counter-3<<"] ="<< test[counter-3] << endl;
   cout << "test["<<counter-4<<"] ="<< test[counter-4] << endl;
   cout << "test["<<counter-5<<"] ="<< test[counter-5] << endl;
   cout << "test["<<counter-6<<"] ="<< test[counter-6] << endl;
   cout << "test["<<counter-7<<"] ="<< test[counter-7] << endl;
   cout << "test["<<counter-8<<"] ="<< test[counter-8] << endl;
   cout << "test["<<counter-9<<"] ="<< test[counter-9] << endl;
 
 
   InternetCloseHandle(OpenAddress);
   InternetCloseHandle(connect);
 
   system("pause");
}
Я полагаю что моя попытка работы с массивами ошибочна. Я сначала определяю массив заведомо бОльшего размера чем код страницы и далее уже из того массива исходя из количества полученных байт создаю новый массив, в который потом побайтно переношу в цикле переношу всю ценную информацию. Проблема в том что в конце у меня всё равно мусор, хоть его и вроде бы не много. Подскажите как правильно завершить массив чтобы в нем не было ничего кроме html кода страницы?

В конечном итоге моей целью на данный момент является получение переменной содержащей внутри себя код страницы который я потом буду обрабатывать например регулярными выражениями.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
06.08.2013, 15:57     Получение информации с сайта
Посмотрите здесь:

Получение информации об ОС - C++
Есть программа которая показывает следующие функции: 1 Имя компьютера 2 Системная информация 3 Системные цвета 4 Директорию Windows...

Получение информации о файле - C++
Помогите реализовать получение информации о некотором файле *.* и запись её в текстовый файл, получить надо следующее: Расположение...

Получение системной информации о компьютере С++ - C++
Нужна программа которая выводит информацию о версии операционной системы о свободном месте на логических дисках, данные о памяти и.ид....

Получение информации из бинарного файла - C++
Собственно есть такая ситуация. Есть программа DatEdit. Принцип её работы в следующем. Мы скармливаем ему структуру и загружаем dat файл....

Получение информации о всех переферийных устройствах - C++
Здравствуйте. Необходимо получить информацию о всех подключенных периферийных устройствах(мыши, клавиатуры, принтеры, сканеры, мониторы и...

Получение информации о дисках установленных на компьютере - C++
Здравствуйте! Помогите мне пожалуйста написать консольное приложени на с++. В универе задали на лаб. работу.. Цель: изучение...

Получение системной информации средствами WinAPI и/или C++ - C++
Здравствуйте! Если кто может, посоветуйте, пожалуйста. Требуется на программном уровне (из приложения) получить информацию о системе:...

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Tulosba
:)
Эксперт С++
4393 / 3236 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
06.08.2013, 16:11     Получение информации с сайта #2
noeine, если уж в цикле считываете, то и счетчик надо инкрементировать:
C++
1
counter += NumberOfBytesRead;
Цитата Сообщение от noeine Посмотреть сообщение
test[i] = DataReceived[i]; //поочередно переносим каждый полезный байт из большего массива в массив заданной размерности счетчиком counter
Это вообще с ума сойти
noeine
0 / 0 / 0
Регистрация: 31.07.2013
Сообщений: 45
06.08.2013, 16:30  [ТС]     Получение информации с сайта #3
Цитата Сообщение от Tulosba Посмотреть сообщение
noeine, если уж в цикле считываете, то и счетчик надо инкрементировать:
C++
1
counter += NumberOfBytesRead;

Это вообще с ума сойти
Если я буду инкриминировать счетчик, то тогда он получит явно не верное значение ведь в NumberOfBytesRead функция InternetReadFile записывает общее количество скачанных байтов. В данном случае этот счетчик нужен лишь из-за того, что за пределами цикла while NumberOfBytesRead не видна.

Это вообще с ума сойти
А как тогда я могу перенести данные из одного массива в другой, при этом не захватив из первого массива - мусор? Я думал создание второго массива точно известной размерности (исходя из counter, несущего в себе значение NumberOfBytesRead при последней итерации) - подходящий вариант, но как оказалось у меня всё же захватывается мусор с собой

То есть мой текущий код таки выводит мне в cmd html код запрашиваемой страницы, но он еще захватывает непонятную мне строку после </HTML>:

HTML5
1
¤¤¤¤ллллллллюв–*
Tulosba
:)
Эксперт С++
4393 / 3236 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
06.08.2013, 16:38     Получение информации с сайта #4
Цитата Сообщение от noeine Посмотреть сообщение
Если я буду инкриминировать счетчик,
Подумайте, что делает каждая итерация цикла while.
Дают ответ: считывает порцию данных в DataReceived, но не больше 4096. Считанное кол-во возвращается в NumberOfBytesRead.
Наводящий вопрос: сколько раз выполнится цикл при получении страницы, размер которой > 4K?
Буфер DataReceived каждый раз перезаписывается по новой. Поэтому на каждой итерации уже нужно делать копирование. И, конечно же, не делать это побайтно. Используйте memcpy() хотя бы уж.
noeine
0 / 0 / 0
Регистрация: 31.07.2013
Сообщений: 45
06.08.2013, 17:51  [ТС]     Получение информации с сайта #5
Ушел над осмыслением ответа

Добавлено через 1 час 4 минуты
У меня опять та же проблема - наличие мусора в массиве:
C++
1
2
3
4
5
6
7
8
9
   char DataReceived[128]; //Определение массива заведомо бОльшего размера
   DWORD NumberOfBytesRead = 0; //ну типа скидываем количество засосанных байтов на 0, хотя в справке написано что функция сама сбрасывает их на 0 перед началом работы
   int counter=0; //Инициализируем счетчик, в который потом будет записано содержимое NumberOfBytesRead (количество прочитанных байтов)
   cout << "DataReceived" << DataReceived << endl;
   while(InternetReadFile(OpenAddress, DataReceived, 128, &NumberOfBytesRead) && NumberOfBytesRead ) //Скачиваем ответ сервера
   {
        cout << DataReceived << endl;
        system("pause");
   }
Используя этот код я пытаюсь малыми порциями скачать содержимое страницы и далее с помощью функции memcpy перенести эту информацию в новый массив. До работы с массивами не дошло, даже когда я пытаюсь получить 128 байт информации, я всё равно на выходе имею массив забитый в конце мусором:
HTML5
1
2
3
4
5
<HTML>
<HEAD>
<TITLE>┬р° IP-рфЁхё. в•™чэрЄ№ IP рфЁхё, юяЁхфхышЄ№ IP-рфЁхё, юяЁхфхышЄ№ ётющ IP</T
ITLE><BASE target=_top>
<meta HTTPв•*в•*в•*в•*в•*в•*в•*в•*в•*в•*в•*в•*в•*в•*в•*в•*в•*в•*в•*в•*в™Ђ
Что я делаю не так при считывании хотя бы одной порции данных не известной мне заранее длинны?
Бендерродригез
Сгибальщик
42 / 42 / 3
Регистрация: 18.05.2013
Сообщений: 220
Завершенные тесты: 1
06.08.2013, 17:58     Получение информации с сайта #6
Может таки потому, что ты массив DataReceived не заполняешь нулями? А находиться там может что памяти угодно.
C++
1
char DataReceived[4096] = {0};
noeine
0 / 0 / 0
Регистрация: 31.07.2013
Сообщений: 45
06.08.2013, 18:05  [ТС]     Получение информации с сайта #7
Цитата Сообщение от Бендерродригез Посмотреть сообщение
Может таки потому, что ты массив DataReceived не заполняешь нулями? А находиться там может что памяти угодно.
C++
1
char DataReceived[4096] = {0};
Правильно ли я понимаю что заполнение массива 0 можно осуществлять таким образом:
C++
1
2
3
4
5
char DataReceived[128]; //Определение массива заведомо бОльшего размера
   int i; //инициируем счетчик цикла
   for (i=0; i<128; i++) {
       DataReceived[i]=0;
   }
В этом случае да, попытка отобразить массив DataReceived до использования функции InternetReadFile не выводит никакого мусора, после же использования функции InternetReadFile, в массиве снова появляется мусор в конце
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠♀
Tulosba
:)
Эксперт С++
4393 / 3236 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
06.08.2013, 18:13     Получение информации с сайта #8
noeine, выводить надо столько, сколько считали, а не весь буфер целиком. К тому же, когда выводите
C++
1
cout << DataReceived
то вывод идет до первого нулевого символа '\0', а его вообще может не быть там (скорее всего и нет), и происходит выход за границы. Т.е. выводится реально больше, чем размер буфера (до первого нуля, который случайно окажется где-то в памяти).
Поэтому имеет смысл читать хотя бы на 1 байт меньше, чем размер буфера (чтобы можно было поместить ноль в конце), а после чтения (но перед выводом на экран) сделать так:
C++
1
DataReceived[NumberOfBytesRead] = 0;
Бендерродригез
Сгибальщик
42 / 42 / 3
Регистрация: 18.05.2013
Сообщений: 220
Завершенные тесты: 1
06.08.2013, 18:17     Получение информации с сайта #9
Можно и в цикле, но зачем?
noeine
0 / 0 / 0
Регистрация: 31.07.2013
Сообщений: 45
06.08.2013, 18:41  [ТС]     Получение информации с сайта #10
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <Windows.h>
#include <WinInet.h>
#pragma comment ( lib, "Wininet.lib" )
 
#include<iostream>
#include<cstring>
 
 
using namespace std;
int main(){
HINTERNET connect = InternetOpen("MyBrowser",INTERNET_OPEN_TYPE_PRECONFIG,NULL, NULL, 0);
 
   if(!connect){
      cout<<"Connection Failed or Syntax error";
      return 0;
   }
 
HINTERNET OpenAddress = InternetOpenUrl(connect,"http://www.myip.ru/ru-RU/index.php", NULL, 0, INTERNET_FLAG_PRAGMA_NOCACHE|INTERNET_FLAG_KEEP_CONNECTION, 0);
 
   if ( !OpenAddress )
   {
      DWORD ErrorNum = GetLastError();
      cout<<"Failed to open URL \nError No: "<<ErrorNum;
      InternetCloseHandle(connect);
      system("pause");
      return 0;
   }
 
   char DataReceived[4096]={0}; //Определение массива заведомо бОльшего размера, заполненного нулями.
   
   DWORD NumberOfBytesRead = 0; //ну типа скидываем количество засосанных байтов на 0, хотя в справке написано что функция сама сбрасывает их на 0 перед началом работы
   int counter=0; //Инициализируем счетчик, в который потом будет записано содержимое NumberOfBytesRead (количество прочитанных байтов)
   while(InternetReadFile(OpenAddress, DataReceived, 4095, &NumberOfBytesRead) && NumberOfBytesRead ) //Скачиваем ответ сервера, заведомо на 1 байт меньше максимального размера буффера
   {
        //cout << DataReceived << endl;
        counter += NumberOfBytesRead;
   }
   DataReceived[counter] = 0; //После того как мы считали информацию, записываем в последний считанный байт 0
   cout << DataReceived ; //Выводим полученную информацию
 
   InternetCloseHandle(OpenAddress); 
   InternetCloseHandle(connect);
   system("pause");
}
На данный момент у меня читается исходный код страницы, в массиве при выводе в консоль отсутствует мусор, подскажите мне еще следующий момент:
Функцией InternetReadFile я считал количество байт, которое помещено в переменную NumberOfBytesRead, далее я записываю значение этой переменной в переменную couter определенную до цикла while. Делаю я запись в другую переменную т.к. за пределами цикла while NumberOfBytesRead мне не видна. И далее руководствуясь полученным значением присваиваю элементу массива.
C++
1
DataReceived[counter] = 0;
Я правильно понимаю что этим действием за "завершаю" массив, что в далеком будущем мне поможет избежать таких вещей как "Переполнение буфера"?
Tulosba
:)
Эксперт С++
4393 / 3236 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
06.08.2013, 18:56     Получение информации с сайта #11
noeine, чтение не правильно сделано. Если нужно иметь результат (страницу целиком в памяти), то надо на каждой итерации добавлять данные в какой-то контейнер.
Короче говоря, как-то так например:

C++
1
2
3
4
5
6
7
8
9
10
const int bufSize = 4096;
char dataBuffer[bufSize];
std::string page; // здесь будет храниться страница целиком
   
DWORD NumberOfBytesRead = 0; 
while(InternetReadFile(OpenAddress, dataBuffer, bufSize, &NumberOfBytesRead) && NumberOfBytesRead ) 
{
    page.append( dataBuffer, dataBuffer + NumberOfBytesRead ); // добавляем считанную порцию
}
cout << page; //Выводим страницу целиком
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.08.2013, 19:31     Получение информации с сайта
Еще ссылки по теме:

Получение информации о частоте и длительности из звукового файла. - C++
Нужно получить информацию ТОЛЬКО о частотах и длительностях звукового файла. Откуда такую инфу проще достать? Мне кажется, что из PCM или...

Работа с файлами(получение информации о файлах, которые будут архивироватся) - C++
Функция записывает в текстовый файл общий размер информационного блока||размер 1файла||имя файла||размер 2 файла и т.д. Пытаюсь найти...

Получение данных с сайта - C++
Добрый день! Я только начинающий программист. Хочу слепить программку для себя. Суть программы в следующем: Есть сайт который...

Вытягивание информации из урл сайта - C++
Здравствуйте. Нужна помощь. Подскажите, какая функция может отыскать в урл сайта например это &quot;&lt;li class=&quot;ruda-block&quot; title=&quot;Руды:...

Получение IP адреса (Си) - C++
Есть ли функция или библиотека для С для определения своего реального интернет IP адреса? Или может есть сервис?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
noeine
0 / 0 / 0
Регистрация: 31.07.2013
Сообщений: 45
06.08.2013, 19:31  [ТС]     Получение информации с сайта #12
Огромное спасибо, а где я могу найти некий "список зависимостей" с++?. Я смог запустить это код только благодаря тому что через 10 минут поисков случайно наткнулся на код с использованием std, где было еще указано:
C++
1
#include<string>
Yandex
Объявления
06.08.2013, 19:31     Получение информации с сайта
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru