2 / 2 / 1
Регистрация: 31.07.2013
Сообщений: 45
1

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

06.08.2013, 15:57. Показов 4169. Ответов 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 кода страницы?

В конечном итоге моей целью на данный момент является получение переменной содержащей внутри себя код страницы который я потом буду обрабатывать например регулярными выражениями.
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
06.08.2013, 15:57
Ответы с готовыми решениями:

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

Получение информации о файле
Помогите реализовать получение информации о некотором файле *.* и запись её в текстовый файл,...

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

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

11
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
06.08.2013, 16:11 2
noeine, если уж в цикле считываете, то и счетчик надо инкрементировать:
C++
1
counter += NumberOfBytesRead;
Цитата Сообщение от noeine Посмотреть сообщение
test[i] = DataReceived[i]; //поочередно переносим каждый полезный байт из большего массива в массив заданной размерности счетчиком counter
Это вообще с ума сойти
0
2 / 2 / 1
Регистрация: 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
¤¤¤¤ллллллллю■
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
06.08.2013, 16:38 4
Цитата Сообщение от noeine Посмотреть сообщение
Если я буду инкриминировать счетчик,
Подумайте, что делает каждая итерация цикла while.
Дают ответ: считывает порцию данных в DataReceived, но не больше 4096. Считанное кол-во возвращается в NumberOfBytesRead.
Наводящий вопрос: сколько раз выполнится цикл при получении страницы, размер которой > 4K?
Буфер DataReceived каждый раз перезаписывается по новой. Поэтому на каждой итерации уже нужно делать копирование. И, конечно же, не делать это побайтно. Используйте memcpy() хотя бы уж.
1
2 / 2 / 1
Регистрация: 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╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠♀
Что я делаю не так при считывании хотя бы одной порции данных не известной мне заранее длинны?
0
Сгибальщик
42 / 42 / 4
Регистрация: 18.05.2013
Сообщений: 220
06.08.2013, 17:58 6
Может таки потому, что ты массив DataReceived не заполняешь нулями? А находиться там может что памяти угодно.
C++
1
char DataReceived[4096] = {0};
1
2 / 2 / 1
Регистрация: 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, в массиве снова появляется мусор в конце
╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠♀
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
06.08.2013, 18:13 8
noeine, выводить надо столько, сколько считали, а не весь буфер целиком. К тому же, когда выводите
C++
1
cout << DataReceived
то вывод идет до первого нулевого символа '\0', а его вообще может не быть там (скорее всего и нет), и происходит выход за границы. Т.е. выводится реально больше, чем размер буфера (до первого нуля, который случайно окажется где-то в памяти).
Поэтому имеет смысл читать хотя бы на 1 байт меньше, чем размер буфера (чтобы можно было поместить ноль в конце), а после чтения (но перед выводом на экран) сделать так:
C++
1
DataReceived[NumberOfBytesRead] = 0;
1
Сгибальщик
42 / 42 / 4
Регистрация: 18.05.2013
Сообщений: 220
06.08.2013, 18:17 9
Можно и в цикле, но зачем?
0
2 / 2 / 1
Регистрация: 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;
Я правильно понимаю что этим действием за "завершаю" массив, что в далеком будущем мне поможет избежать таких вещей как "Переполнение буфера"?
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
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; //Выводим страницу целиком
1
2 / 2 / 1
Регистрация: 31.07.2013
Сообщений: 45
06.08.2013, 19:31  [ТС] 12
Огромное спасибо, а где я могу найти некий "список зависимостей" с++?. Я смог запустить это код только благодаря тому что через 10 минут поисков случайно наткнулся на код с использованием std, где было еще указано:
C++
1
#include<string>
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
06.08.2013, 19:31
Помогаю со студенческими работами здесь

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru