Информация о web-ресурсах
Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain
Имеется в базе данных список с URL-адресами. Нужно получить краткую информацию о каждом из этих ресурсов: например строку, которая отображается в заголовке веб-браузера при загрузке данной страницы. Либо получить ответ, что такой сетевой адрес не существует.
Каким наиболее простым способом это можно сделать?
Каким наиболее простым способом это можно сделать?
Можно через компонент CWebBrowser2, загружая в него страницу.
Информация о веб-странице, отображаемая в заголовке окна веб-браузера, содержится в в тегах title. В HTML-коде это так выглядит:
[html]
<title>Название страницы...</title>
[/html]
Обычно эти тэги располагаются в начале HTML-файла, а тебе нужно лишь распознать их в тексте и извлечь соответствующую строку.
Примитивный алгоритм для этого на C++/CLI примерно так выглядит:
Дело ещё в том, что текст в разных веб-страницах может иметь разную кодировку, поэтому его придётся перекодировать для правильного отображения. Кодировка текста обозначается ключевым словом charset.
В HTML-коде она обычно так представлена:
[html]
<meta content="text/html;charset=windows-1251" http-equiv="Content-Type">
[/html]
[html]
<title>Название страницы...</title>
[/html]
Обычно эти тэги располагаются в начале HTML-файла, а тебе нужно лишь распознать их в тексте и извлечь соответствующую строку.
Примитивный алгоритм для этого на C++/CLI примерно так выглядит:
Код: Выделить всё
#include "stdafx.h"
using namespace System;
String^ GetHtmlTitle(String^ text)
{
String^ tag = L"<title>";
int nTitle = text->IndexOf(tag);
int nTitleEnd = text->IndexOf(L"</title>", nTitle);
return text->Substring(nTitle, nTitleEnd-nTitle)->Replace(tag, L"");
}
int main(array<String ^> ^args)
{
array<String^> ^urlList =
{
L"[URL]http://www.microsoft.com[/URL]",
L"[URL]http://www.google.com[/URL]",
L"[URL]http://www.yahoo.com[/URL]",
L"[URL]http://www.apple.com[/URL]",
L"[URL]http://www.ibm.com[/URL]",
L"[URL]http://www.sun.com[/URL]",
L"[URL]http://www.mail.ru[/URL]",
L"[URL]http://www.Akhgf337458hiksjdl.com[/URL]" // bad address
};
//
Net::WebClient^ wc = gcnew Net::WebClient();
for each (String^ url in urlList)
{
try
{
String^ text = wc->DownloadString(url);
if (text->Length > 0)
{
Console::InputEncoding = Text::Encoding::UTF8;
Console::WriteLine(GetHtmlTitle(text));
}
}
catch (Net::WebException^ ex)
{
Console::WriteLine(ex->Message);
}
}
Console::Read();
//
return 0;
}
Дело ещё в том, что текст в разных веб-страницах может иметь разную кодировку, поэтому его придётся перекодировать для правильного отображения. Кодировка текста обозначается ключевым словом charset.
В HTML-коде она обычно так представлена:
[html]
<meta content="text/html;charset=windows-1251" http-equiv="Content-Type">
[/html]
Спасибо, WinMain. Твой пример замечательно работает, только мне теперь и к базе данных придётся обращаться через don't Net. А я по старинке все запросы к СУБД делаю через MFC.
Можно и обычными функциями Win32API обойтись. Если будет интересно, могу пример написать.
А ты чего платформу .NET называешь "don't Net"?
Это типа I don't like the Net? Чем она тебя не так устраивает?
А ты чего платформу .NET называешь "don't Net"?
Это типа I don't like the Net? Чем она тебя не так устраивает?
- Romeo
- Сообщения: 3126
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
Я подозреваю, что он пишет то, что на слуху воспринял
Читается dot net, а он услышал don't net 


Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
WinMain, если не трудно, напиши ещё пару своих примеров на тему закачки данных из сети. А я тогда уже выберу тот способ, который мне больше понравится.
Самый простой способ (на Win32API) загрузить файл по HTTP-протоколу - это вызвать функцию URLDownloadToFile или с помощью функции URLOpenBlockingStream читать данные прямо из потока.
Вот пример:
Правда здесь есть одно ограничение: таким образом использовать функцию можно для небольших файлов. Если нужно загрузить большой файл, то в качестве параметра функции нужно передавать указатель на интерфейс IBindStatusCallback, который нужно будет самому имплементировать. Тогда через его метод OnProgress можно получать информацию о текущем состоянии процесса загрузки.
Ещё проблема: эта функция не работает в сетях, где требуется дополнительная аутентификация пользователя при входе в интернет, а так же через модем может не работать.
Вот пример:
Код: Выделить всё
[size=84][color=#0000ff][size=84][color=#0000ff]#include[/color][/size][/color][/size][size=84][color=#800000][size=84][color=#800000]"stdafx.h"[/color][/size]
[/color][/size][size=84][color=#0000ff][size=84][color=#0000ff]#include[/color][/size][/color][/size][size=84][color=#800000][size=84][color=#800000]<UrlMon.h>[/color][/size][/color][/size]
[size=84][color=#0000ff][size=84][color=#0000ff]#pragma [/color][/size][/color][/size][size=84][color=#0000ff][size=84][color=#0000ff]comment[/color][/size][/color][/size][size=84] ([/size][size=84][color=#0000ff][size=84][color=#0000ff]lib[/color][/size][/color][/size][size=84], [/size][size=84][color=#800000][size=84][color=#800000]"urlmon.lib"[/color][/size][/color][/size][size=84])[/size]
[size=84][color=#0000ff][size=84][color=#0000ff]int[/color][/size][/color][/size][size=84] _tmain([/size][size=84][color=#0000ff][size=84][color=#0000ff]int[/color][/size][/color][/size][size=84] argc, _TCHAR* argv[])[/size]
[size=84]{[/size]
[size=84] LPCTSTR pszUrl = _T([/size][size=84][color=#800000][size=84][color=#800000]"http://www.yandex.ru"[/color][/size][/color][/size][size=84]);[/size]
[size=84] LPCTSTR pszFile = _T([/size][size=84][color=#800000][size=84][color=#800000]"yandex.html"[/color][/size][/color][/size][size=84]);[/size]
[size=84] ::URLDownloadToFile(NULL, pszUrl, pszFile, 0, NULL);[/size]
[size=84] _fputts(_T([/size][size=84][color=#800000][size=84][color=#800000]"Downloading has been completed.\n"[/color][/size][/color][/size][size=84]), stdout);[/size]
[size=84] _gettc(stdin);[/size]
[size=84][color=#0000ff][size=84][color=#0000ff] return[/color][/size][/color][/size][size=84] 0;[/size]
[size=84]}[/size]
Ещё проблема: эта функция не работает в сетях, где требуется дополнительная аутентификация пользователя при входе в интернет, а так же через модем может не работать.
Спасибо, WinMain. У меня эта функция нормально работает.
А готовый пример имплементации IBindStatusCallback у тебя имеется?
А готовый пример имплементации IBindStatusCallback у тебя имеется?
Используй мой вариант имплементации в качестве базового класса. Унаследуйся от него и переопредели в нём метод OnProgress ().
Есть ещё готовая имплементация в библиотеке ATL в виде шаблона, но тот вариант лучше использовать в контексте разрабатываемого СОМ-объекта.
Код: Выделить всё
class CBindStatusImpl : public IBindStatusCallback
{
public:
virtual ULONG STDMETHODCALLTYPE
AddRef(void){return 0U;}
virtual ULONG STDMETHODCALLTYPE
Release(void){return 0U;}
virtual HRESULT STDMETHODCALLTYPE
QueryInterface(REFIID iid, void ** ppvObject){return S_OK;}
//
virtual HRESULT STDMETHODCALLTYPE
GetBindInfo(DWORD *grfBINDF, BINDINFO *pbindinfo){return S_OK;}
virtual HRESULT STDMETHODCALLTYPE
GetPriority(LONG *pnPriority){return S_OK;}
virtual HRESULT STDMETHODCALLTYPE
OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed){return S_OK;}
virtual HRESULT STDMETHODCALLTYPE
OnObjectAvailable(REFIID riid, IUnknown *punk){return S_OK;}
virtual HRESULT STDMETHODCALLTYPE
OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText){return S_OK;}
virtual HRESULT STDMETHODCALLTYPE
OnStartBinding(DWORD dwReserved, IBinding *pib){return S_OK;}
virtual HRESULT STDMETHODCALLTYPE
OnStopBinding(HRESULT hresult,LPCWSTR szError){return S_OK;}
virtual HRESULT STDMETHODCALLTYPE
OnLowResource(DWORD reserved){return S_OK;}
};