Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Как раскодировать полученную html-страницу?  (Прочитано 15169 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Maybe
Гость
« : 08-12-2009 13:24 » 

Здравствуйте.
Пишу программу, которая получает текст html-страницы и выбирает русские слова.

Однако проблема состоит в том, что некоторые сайты вместо русских букв выводят какую-то совершенно непонятную ерунду. Яркий тому пример yandex.ru. Если заменить адрес сайта, например, не яндекс, а, скажем, google.ru, то все русские буковки выводятся замечательно. Понимаю, что дело в кодировках этих самых сайтов, а как же тогда из этой кодировки получить нормальный русский текст?

Код:
	char fileURL[] = "http://www.yandex.ru";
int i;

HINTERNET hSession = InternetOpen(L"Internet Explorer", INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0);

HINTERNET hURL;
const int BufferSize = 80000; // берем массив с избытком, на всякий случай
char Buffer[BufferSize];
DWORD BufferLen;

//обнуляем весь массив, иначе в конце массива будет записана всякая ерунда
for (i=0; i<BufferSize; i++){
Buffer[i]='\0';
}

hURL = InternetOpenUrlA(hSession,fileURL,0,0,INTERNET_FLAG_NO_COOKIES,0);

// весь html-файл считываем за раз
InternetReadFile(hURL, Buffer, sizeof(Buffer), &BufferLen);

InternetCloseHandle(hURL);
InternetCloseHandle(hSession);
« Последнее редактирование: 08-12-2009 16:32 от Sel » Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 08-12-2009 13:53 » 

Яндекс тоже умеет отвечать в UTF-8, надо только сообщить, что клиенту надо - через параметр заголовка (не знаю, как его скормить данному компоненту):

Accept-Charset: UTF-8;q=1
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
zubr
Гость
« Ответ #2 : 08-12-2009 16:33 » 

В 3-й параметр функции InternetOpenUrl передаешь заголовок в котором указываешь язык запроса accept-language: ru, в 4-й - длину заголовка.
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 08-12-2009 17:38 » 

zubr, язык еще не определяет кодировку. Т.ч. Accept-Charset тоже надо передавать.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
zubr
Гость
« Ответ #4 : 08-12-2009 18:18 » 

Согласен.
Записан
Maybe
Гость
« Ответ #5 : 08-12-2009 21:09 » 

Сделал, как вы написали и метод InternetOpenUrlA стал возвращать NULL (что-то нехорошее тут произошло). Соответственно и метод InternetReadFile перестал возвращать код html-страницы.

Посмотрите ребята, может я неправильно составил HTTP-headers?

Вот обновленный код:

Код:
char fileURL[] = "http://www.yandex.ru";
int i;

HINTERNET hSession = InternetOpen(L"Internet Explorer", INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0);

HINTERNET hURL;
const int BufferSize = 80000; // берем массив с избытком, на всякий случай
char Buffer[BufferSize];
DWORD BufferLen;

//обнуляем весь массив, иначе в конце массива будет записана всякая ерунда
for (i=0; i<BufferSize; i++){
Buffer[i]='\0';
}

char lpszHeaders[] = "GET / HTTP/1.1\r\nHost: http://www.yandex.ru\r\nAccept-Charset: UTF-8;q=1\r\nAccept-Language: ru\r\n\r\n";
UINT dwHeadersLength = strlen(lpszHeaders);
hURL = InternetOpenUrlA(hSession, fileURL, lpszHeaders, dwHeadersLength, INTERNET_FLAG_NO_COOKIES, 0);

// весь html-файл считываем за раз
InternetReadFile(hURL, Buffer, sizeof(Buffer), &BufferLen);

InternetCloseHandle(hURL);
InternetCloseHandle(hSession);
Записан
Maybe
Гость
« Ответ #6 : 08-12-2009 21:34 » 

GetLastError выдает ошибку номер 12150
ERROR_HTTP_HEADER_NOT_FOUND  -------  The requested header could not be located.

Как правильно? Уже много вариантов перепробовал, ничего не получилось...  Здесь была моя ладья...
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #7 : 09-12-2009 05:03 » 

Maybe, полагаю, что не нужно передавать полный заголовок - достаточно только модифицируемые поля. GET и Host уж точно не надо - зачем бы тогда URL передавать...

Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
zubr
Гость
« Ответ #8 : 09-12-2009 10:27 » 

Если мне не изменяет память, там надо еще выравнивать заголовок. В общем несколько лет назад я реализовывал подобное, но я долго не заморачиваясь в http-снифере подсмотрел, что IE выдает в своем заголовке. Если найду у себя в архиве тот проект, то подкину часть кода с заголовком.
Есть вариант, чтобы весь заголовок не создавать, воспользоваться функцией HttpAddRequestHeaders. Но тут немного другая схема чтения контента: InternetOpen -> InternetConnect -> HttpOpenRequest -> HttpAddRequestHeaders -> HttpSendRequest -> InternetReadFile -> HttpEndRequest
Записан
Maybe
Гость
« Ответ #9 : 09-12-2009 17:12 » 

Поищите пожалуйста. Очень буду рад хоть какому-нибудь исходнику.
Позже попробую вторым способом сделать.
Записан
zubr
Гость
« Ответ #10 : 09-12-2009 19:08 » 

1. У меня заголовок
char lpszHeaders[] = "Accept-Charset: UTF-8;q=1\r\nAccept-Language: ru";
работает.
2. Пробовал разные кодировки в запросе передавать на сервер yandex.ru - он все равно выдает результат запроса в кодировке UTF-8.
3. Правильнее будет после получения результата запроса определить заголовок ответа (HttpQueryInfo), а в нем кодировку ответа. Исходя из кодировки ответа раскодировать текст. Вот мой код потока, который умеет посылать данные формы на сервер, приаттаченный файл, получать данные с сервера в ассинхронном режиме:
Код:
DWORD WINAPI ClientWinHttpThreadProc(LPVOID pParam)
{
   CSendRequestHttp* srh=(CSendRequestHttp*)pParam;
   HINTERNET hSession = NULL,
             hConnect = NULL,
             hRequest = NULL;
   INTERNET_BUFFERS BufferIn;
   int i, j, len, pos=0;
   CString s, s1, s2, s_pred, s_post, WriteData="";
   char* bufer=NULL;
   char* buf1=NULL;
   char* buf2=NULL;
   char* buffile=NULL;
   char* buffiletemp=NULL;
   char* buffiletemp2=NULL;
   DWORD dwBytesWritten;
   DWORD dwBytesToWrite;
   DWORD dwStatusSize;
   CAtlFile file;
   ULONGLONG lenfilesize=0, lenbuffiles=0, posbuffile=0;
   BOOL flag_attach=FALSE;
   BOOL flag_postdata=FALSE;
   //CAtlArray<CParamAttach> ExtParamsAttach;

   if(srh->getIsProxy())
   {
   hSession=::InternetOpen(srh->getAppName(), INTERNET_OPEN_TYPE_PROXY,
srh->getProxyName(), srh->getProxyBypass(), 0);
   }
   else
   {
       hSession=::InternetOpen(srh->getAppName(), /*INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY*/INTERNET_OPEN_TYPE_PRECONFIG, NULL,
NULL, 0);
   };
   if(hSession==NULL)
   {
       ::MessageBox(NULL, "InternetOpen filed", "Error", MB_OK | MB_ICONERROR);
       srh->m_RequestState=SESSION_CLOSE;
   return 0;
   };
   srh->m_RequestState=SESSION_OPEN;
   if(srh->pRequestStateProc!=NULL)
   srh->pRequestStateProc(srh->m_RequestState, srh->m_OutHeader, srh->m_OutData, WriteData);
   
   switch(srh->getTypeProtocol())
   {
       case TYPE_HTTP:
         hConnect=::InternetConnect(hSession, srh->getServerName(), srh->getPort()/*INTERNET_DEFAULT_HTTP_PORT*/,
  srh->getUserName(), srh->getPassword(), INTERNET_SERVICE_HTTP, 0, NULL);
   break;
       case TYPE_HTTPS:
         hConnect=::InternetConnect(hSession, srh->getServerName(), INTERNET_DEFAULT_HTTPS_PORT,
  srh->getUserName(), srh->getPassword(), INTERNET_SERVICE_HTTP, 0, NULL);
   break;
   };

   
   if(hConnect==NULL)
   {
srh->WriteMsgToLog("InternetConnect filed");
        srh->m_RequestState=SESSION_CLOSE;
return 0;
   };
   srh->m_RequestState=CONNECT;
   if(srh->pRequestStateProc!=NULL)
   srh->pRequestStateProc(srh->m_RequestState, srh->m_OutHeader, srh->m_OutData, WriteData);

   switch(srh->getTypeProtocol())
   {
       case TYPE_HTTP:
         hRequest=::HttpOpenRequest(hConnect, srh->getTypeRequest(), srh->getObjectName(),
       NULL, NULL, NULL, /*INTERNET_FLAG_NO_CACHE_WRITE*/INTERNET_FLAG_KEEP_CONNECTION, NULL);
   break;
       case TYPE_HTTPS:
         hRequest=::HttpOpenRequest(hConnect, srh->getTypeRequest(), srh->getObjectName(),
       NULL, NULL, NULL, INTERNET_FLAG_SECURE, NULL);
   break;
   };
   
   if(hRequest==NULL)
   {
   srh->WriteMsgToLog("HttpOpenRequest filed");
   srh->m_RequestState=SESSION_CLOSE;
   return 0;
   };
   srh->m_RequestState=OPEN_REQUEST;
   if(srh->pRequestStateProc!=NULL)
   srh->pRequestStateProc(srh->m_RequestState, srh->m_OutHeader, srh->m_OutData, WriteData);

   if(srh->getSendData()=="")
   {
      if(srh->getpRequestAttachParam()!=NULL)
  {
  if(srh->getpRequestAttachParam()->getCountFileAttachParams()>0)
  {
              for(int i=0; i<srh->getpRequestAttachParam()->getCountFileAttachParams(); i++)
  {
if(SUCCEEDED(file.Create(srh->getpRequestAttachParam()->getFileAttachParamAt(i).getAttachFilePatch(),
  GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING)))
{
                    if(SUCCEEDED(file.GetSize(lenfilesize)))
{
                        s=CString("-----------------------------7d636b240634")+CString("\r\n")+
                     CString("Content-Disposition: form-data; name=")+CString('"')+
srh->getpRequestAttachParam()->getFileAttachParamAt(i).getNameParamFormFileName()+
CString('"')+CString("; filename=")+CString('"')+srh->getpRequestAttachParam()->getFileAttachParamAt(i).getNameFileAttach()+
                     CString('"')+CString("\r\n")+CString("Content-Type: application/octet-stream")+CString("\r\n\r\n");
if(i>0)
s=CString("\r\n")+s;
                        if(buffiletemp!=NULL)
{
delete [] buffiletemp;
                            buffiletemp=NULL;
};
buffiletemp=new char[s.GetLength()+lenfilesize];
                        ::ZeroMemory(buffiletemp, s.GetLength()+lenfilesize);
strcpy(buffiletemp, s);
                        if(SUCCEEDED(file.Read(&buffiletemp[s.GetLength()], lenfilesize)))
                        {
                            if(!flag_attach)
{
                               flag_attach=TRUE;
                               srh->getpRequestHeaderParam()->AddRequestHeader("Content-Type: multipart/form-data; boundary=---------------------------7d636b240634");
};
                            lenbuffiles+=s.GetLength()+lenfilesize;
                            if(buffiletemp2!=NULL)
{
    delete [] buffiletemp2;
                                buffiletemp2=NULL;
};
                            buffiletemp2=new char[lenbuffiles];
                            ::ZeroMemory(buffiletemp2, lenbuffiles);
if(buffile!=NULL)
{
                                memcpy(buffiletemp2, buffile, posbuffile);
};
memcpy(&buffiletemp2[posbuffile], buffiletemp, s.GetLength()+lenfilesize);
posbuffile=lenbuffiles;
                            if(buffile!=NULL)
{
    delete [] buffile;
                                buffile=NULL;
};
                            buffile=new char[lenbuffiles];
                            ::ZeroMemory(buffile, lenbuffiles);
                            memcpy(buffile, buffiletemp2, lenbuffiles);
};
file.Close();
};
};
  };
  if(buffile==NULL)
  {
                 flag_attach=FALSE;
srh->getpRequestHeaderParam()->DelRequestHeader("Content-Type: multipart/form-data; boundary=---------------------------7d636b240634");
  };
  };
  };
   };
 
  if(srh->getpRequestPostDataParam()!=NULL)
   {
      if(srh->getpRequestPostDataParam()->GetRequestPostData()!="")
  {
         flag_postdata=TRUE;
if(flag_attach)
{
            s=srh->getpRequestPostDataParam()->GetRequestPostData();
do
{
   s1=s;
   i=s.Find("&", 0);
               if(i!=-1)
   {
      s1.Delete(i, s1.GetLength()-i);
  s.Delete(0, i+1);
   };
   j=s1.Find("=", 0);
   if(j==-1)
   {
      if(i==-1)
  break;
  else
      continue;
   };
               s2=s1;
   s1.Delete(j, s1.GetLength()-j);
   s2.Delete(0, j+1);
   srh->getpRequestAttachParam()->AddExtAttachParam(s1, s2);
}while(i!=-1);
}
else
         srh->getpRequestHeaderParam()->AddRequestHeader("Content-Type: application/x-www-form-urlencoded");
  };
   };
   
   if(srh->getpRequestHeaderParam()!=NULL)
   {
  if(srh->getpRequestHeaderParam()->GetRequestHeaders()!="")
  {
     if(!HttpAddRequestHeaders(hRequest, srh->getpRequestHeaderParam()->GetRequestHeaders(),
srh->getpRequestHeaderParam()->GetRequestHeaders().GetLength(), HTTP_ADDREQ_FLAG_ADD))
         {
            srh->WriteMsgToLog("HttpAddRequestHeaders filed");
         }
     else
     {
            srh->m_RequestState=ADD_REQUEST_HEADERS;
            if(srh->pRequestStateProc!=NULL)
            srh->pRequestStateProc(srh->m_RequestState, srh->m_OutHeader, srh->m_OutData, WriteData);
     };
  };
   };

   BufferIn.dwStructSize=sizeof(INTERNET_BUFFERS); // Must be set or error will occur
   BufferIn.Next=NULL;
   BufferIn.lpcszHeader=NULL;
   BufferIn.dwHeadersLength=0;
   BufferIn.dwHeadersTotal=0;
   if((!flag_postdata)||(flag_attach))
   {
      BufferIn.lpvBuffer=NULL;               
      BufferIn.dwBufferLength=0;
   }
   else
   {
  if(flag_postdata)
  {
     buf2=new char[srh->getpRequestPostDataParam()->GetRequestPostData().GetLength()+1];
     ::ZeroMemory(buf2, srh->getpRequestPostDataParam()->GetRequestPostData().GetLength()+1);
     strcpy(buf2, srh->getpRequestPostDataParam()->GetRequestPostData()+"\n");
     BufferIn.lpvBuffer=buf2;               
         BufferIn.dwBufferLength=srh->getpRequestPostDataParam()->GetRequestPostData().GetLength()+1;
  }
  else
  {
         BufferIn.lpvBuffer=NULL;               
         BufferIn.dwBufferLength=0;
  };
   };

   if(!flag_attach)
   {
       BufferIn.dwBufferTotal=srh->getSendData().GetLength(); // This is the only member used other than dwStructSize
       len=BufferIn.dwBufferTotal;
   }
   else
   { 
  s_pred=srh->getpRequestAttachParam()->getExtAttachParam();
          s_post=CString("\r\n-----------------------------7d636b240634--");
  BufferIn.dwBufferTotal=s_pred.GetLength()+lenbuffiles+s_post.GetLength();
  len=lenbuffiles;
   };
   BufferIn.dwOffsetLow=0;
   BufferIn.dwOffsetHigh=0;

   if(!::HttpSendRequestEx(hRequest, &BufferIn, NULL, 0, 0))
   {
       srh->WriteMsgToLog("HttpSendRequestEx filed");
       srh->m_RequestState=SESSION_CLOSE;
   return 0;
   };
   srh->m_RequestState=SEND_REQUEST;
   if(srh->pRequestStateProc!=NULL)
   srh->pRequestStateProc(srh->m_RequestState, srh->m_OutHeader, srh->m_OutData, WriteData);

   if(len>0)
   {
       if(flag_attach)
   {
   if(bufer!=NULL)
   {
              delete [] bufer;
  bufer=NULL;
   };
   bufer=new char[s_pred.GetLength()+1];
   ::ZeroMemory(bufer, s_pred.GetLength()+1);
   strcpy(bufer, s_pred);
   bufer[s_pred.GetLength()]=0;
   if(::InternetWriteFile(hRequest, bufer, s_pred.GetLength(), &dwBytesWritten))
   {
   do
           {
                  if(len<=1024)
  {
dwBytesToWrite=len;
                     //len=0;
          }
          else
          {
                      dwBytesToWrite=1024;
          };
                  if(bufer!=NULL)
          {
                     delete [] bufer;
         bufer=NULL;
          };
                  bufer=new char[dwBytesToWrite];
          ::ZeroMemory(bufer, dwBytesToWrite);
         
  memcpy(bufer, &buffile[pos], dwBytesToWrite);
 
                  pos+=1024;
      len-=1024;
          if(!::InternetWriteFile(hRequest, bufer, dwBytesToWrite, &dwBytesWritten))
          {
             srh->WriteMsgToLog("InternetWriteFile filed");
         break;
          }
          else
          {
                     WriteData=CString(bufer);
             srh->m_RequestState=WRITE_DATA;
                     if(srh->pRequestStateProc!=NULL)
                     srh->pRequestStateProc(srh->m_RequestState, srh->m_OutHeader, srh->m_OutData, WriteData);
          };
           }while(len>0);
               if(bufer!=NULL)
       {
                  delete [] bufer;
      bufer=NULL;
       };
               bufer=new char[s_post.GetLength()+1];
       ::ZeroMemory(bufer, s_post.GetLength()+1);
       strcpy(bufer, s_post);
               bufer[s_post.GetLength()]=0;
       if(!::InternetWriteFile(hRequest, bufer, s_post.GetLength(), &dwBytesWritten))
               srh->WriteMsgToLog("InternetWriteFile filed");
   }
   else
           srh->WriteMsgToLog("InternetWriteFile filed");
   }
   else
   {
      do
      {
              if(bufer!=NULL)
      {
                 delete [] bufer;
     bufer=NULL;
      };
  bufer=new char[1024];
  if(len<=1024)
      {
         s=srh->getSendData().Mid(pos, len);
                 dwBytesToWrite=len;
                 len=0;
      }
      else
      {
                  s=srh->getSendData().Mid(pos, 1024);
                  pos+=1024;
      len-=1024;
                  dwBytesToWrite=1024;
      };
      ::ZeroMemory(&bufer[0], 1024);
      strcpy(bufer, s);
      if(!::InternetWriteFile(hRequest, bufer, dwBytesToWrite, &dwBytesWritten))
      {
         srh->WriteMsgToLog("InternetWriteFile filed");
     break;
      }
      else
      {
                  WriteData=s;
      srh->m_RequestState=WRITE_DATA;
                  if(srh->pRequestStateProc!=NULL)
                  srh->pRequestStateProc(srh->m_RequestState, srh->m_OutHeader, srh->m_OutData, WriteData);
     };
     
      }while(len!=0);
   };
   };
   WriteData="";

   if(!::HttpEndRequest(hRequest, NULL, 0, 0))
   {
       srh->WriteMsgToLog("HttpEndRequest filed");
   }
   else
   {
      srh->m_RequestState=END_REQUEST;
      if(srh->pRequestStateProc!=NULL)
      srh->pRequestStateProc(srh->m_RequestState, srh->m_OutHeader, srh->m_OutData, WriteData);
   };

   dwStatusSize=0;
   ::HttpQueryInfo(hRequest, HTTP_QUERY_RAW_HEADERS_CRLF, NULL, &dwStatusSize, NULL);
   buf1=new char[dwStatusSize];
   ZeroMemory(buf1, dwStatusSize);
   ::HttpQueryInfo(hRequest, HTTP_QUERY_RAW_HEADERS_CRLF, buf1, &dwStatusSize, NULL);
   srh->m_OutHeader=buf1;
   delete [] buf1;
   buf1=NULL;
   srh->m_RequestState=READ_HEADER;
   if(srh->pRequestStateProc!=NULL)
   srh->pRequestStateProc(srh->m_RequestState, srh->m_OutHeader, srh->m_OutData, WriteData);

   srh->m_OutData="";
   do
   {
dwStatusSize=0;
if(!::InternetQueryDataAvailable(hRequest, &dwStatusSize, 0, 0))
{
            srh->WriteMsgToLog("InternetQueryDataAvailable filed");
            srh->m_RequestState=SESSION_CLOSE;
    return 0;
};
if(dwStatusSize>0)
{
           buf1=new char[dwStatusSize+1];
   ::ZeroMemory(buf1, dwStatusSize+1);
           if(!::InternetReadFile(hRequest, buf1, dwStatusSize, &dwBytesWritten))
   {
               srh->WriteMsgToLog("InternetQueryDataAvailable filed");
   delete [] buf1;
   buf1=NULL;
               srh->m_RequestState=SESSION_CLOSE;
       return 0;
   }
   else
   {
              srh->m_RequestState=READ_DATA;
              if(srh->pRequestStateProc!=NULL)
              srh->pRequestStateProc(srh->m_RequestState, srh->m_OutHeader, CString(buf1), WriteData);
   };
   srh->m_OutData+=buf1;
           delete [] buf1;
   buf1=NULL;
};
   }while (dwStatusSize>0);

   if(hRequest!=NULL)
   ::InternetCloseHandle(hRequest);
   if(hConnect!=NULL)
   ::InternetCloseHandle(hConnect);
   if(hSession!=NULL)
   ::InternetCloseHandle(hSession);

   srh->m_RequestState=SESSION_CLOSE;
   if(srh->pRequestStateProc!=NULL)
   {
      srh->m_OutHeader="";
      srh->m_OutData="";
      WriteData="";
      srh->pRequestStateProc(srh->m_RequestState, srh->m_OutHeader, srh->m_OutData, WriteData);
   };

   return 0;
};
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines