Web страницы представляют собой очень привлекательный источник информации. Можно придумать массу примеров, когда целесообразно в автоматическом режиме осуществлять серфинг по страницам Всемирной Паутины и извлекать необходимые сведения.
Особенности задачи. Web страницы представляют собой очень привлекательный источник информации. Можно придумать массу примеров, когда целесообразно в автоматическом режиме осуществлять серфинг по страницам Всемирной Паутины и извлекать необходимые сведения. Например, можно следить за появлением новых ссылок по интересующему предмету, сканируя страницы, генерируемые различными поисковыми системами; можно регистрировать новые сведения, появляющиеся на страницах конкурирующих компаний; можно извлекать мировые новости и генерировать собственные дайджесты; можно фильтровать и преобразовывать необходимую информацию для Web Parts собственных Digital Dashboard. Для осуществления подобных планов вполне подходит любое приложение Microsoft Office. Так, для работы со ссылками или числовыми показателями, удобно импортировать информацию из Internet прямо на рабочие листы Excel. Тексты можно записывать в документы Word. Web Parts генерировать непосредственно из Outlook. А реализовать задуманное, как всегда, поможет VBA. Для этого, необходимо научиться, программным путем запускать Internet Explorer из приложений Office. В отличие от других задач связывания различных приложений, работа с Internet Explorer имеет ряд особенностей. Общая схема: "создать объект Application => открыть документ => выполнить обработку => закрыть документ и приложение", в случае с Internet Explorer неприменима. Для документов Internet Explorer не существует метода Open. Вместо этого, используется метод Navigate, который только инициирует операцию открытия документа, а дальше, уж как "карта ляжет". Любой, кто работал с браузерами Internet, не мог не заметить, что эти приложения работают в фоновом режиме, оставляя массу свободного времени для других программ. То же самое произойдет и при запуске Internet Explorer из Office. Explorer немедленно возвратит управление вызывающему модулю, хотя до окончания загрузки необходимого документа еще далеко. Чтобы не заблокировать систему, необходимо решить задачу синхронизации параллельно работающих приложений. Обычно для этой цели в VBA используется таймер, в сочетании с функцией DoEvents, передающей управление операционной системе для обработки событий и выполнения других программ. В языке VB подобные действия выполнить гораздо проще с помощью функции Sleep. Вторая особенность использования Internet Explorer заключается в многообразии библиотек, содержащих компоненты необходимой объектной модели. Одинаковых результатов можно достигнуть с помощью различных инструментов, поэтому требуется предварительно ознакомиться с составом той или иной DLL, доступными свойствами, методами и событиями для одноименных объектов. В описываемом примере используются две самые распространенные библиотеки, обычно расположенные в папке C:WINDOWSSYSTEM, это: Microsoft Internet Controls (SHDOCVW.DLL) и Microsoft HTML Object Library (MSHTML.DLL). Для того чтобы помещенные ниже процедуры выполнялись, необходимо в проекте VBA отметить применение указанных библиотек. Это делается с помощью команды "Сервис.Ссылки…", выбираемой в меню редактора VBA. Обращение к Internet Explorer. Как уже отмечалось, при работе с Internet Explorer, следует позаботиться о синхронизации параллельных процессов. Рекомендуемым этапом решения такой задачи является построение специального класса, позволяющего использовать события внешнего приложения. Для этого, в VBA проекте необходимо создать новый модуль класса и описать в нем объектную переменную с ключевым словом WithEvents. Как только это сделано, в списке процедур для описанного объекта появятся все предусмотренные события. Объект Internet Explorer имеет изрядное количество событий, не в пример объектам Application Office. Для целей нашего примера достаточно использовать одно единственное: DocumentComplete. Это событие возникает, когда какой-либо документ полностью загружен и в строке состояния Internet Explorer появляется знакомое всем сообщение "Готово". Соответствующий модуль класса показан ниже. Option Explicit '-- Класс InternetExplorerWithEvents Public WithEvents IE As InternetExplorer Private Sub IE_DocumentComplete(ByVal pDisp As Object, URL As Variant) '-- Событие DocumentComplete, свидетельствующее, '-- что страница загружена полностью Debug.Print "Document Complete, URL = " & URL '-- Вызов обработчика документа DocumentComlete URL End Sub После того, как объект Internet Explorer надлежащим образом определен, можно перейти к процедурам главного модуля проекта. Поскольку предполагается параллельная работа, не обойтись без глобальных переменных, служащих для хранения информации между вызовами процедур. В нашем случае их три: Public gobjWithEvents As Object Public gblnInternetExplorerIsOpen As Boolean Public gstrURL As String Первая переменная очевидна - это указатель на открытый экземпляр Internet Explorer. Вторая переменная - флаг открытого состояния, введена для реализации в среде VBA Office'97, где по непонятной причине отсутствует, хотя и упоминается в справочной системе, функция IsNothing, проверяющая связь ссылочной переменной с реальным объектом. Необходимость в третьей, строковой переменной будет понятна из дальнейшего изложения. После того, как необходимые переменные определены, можно приступить к программированию процедур, первая из которых, открывает новый экземпляр приложения Internet Explorer: Public Sub InternetExplorerOpen(blnSilent As Boolean, _ blnVisible As Boolean) '-- Процедура запускает новый Internet Explorer, '-- создает и инциализирует глобальный объект '-- Internet Explorer With Events, '-- инициализирует глобальную переменную '-- gblnInternetExplorerIsOpen для контроля '-- открытого состояния InternetExplorer Dim objIE As New InternetExplorer If blnSilent Then '-- Проверка режима Offline If (objIE.Offline = True) Then gblnInternetExplorerIsOpen = False Exit Sub End If '-- Отключение диалогов objIE.Silent = True Else '-- Включение диалогов objIE.Silent = False End If '-- Включение видимости If blnVisible Then objIE.Visible = True '-- Создается глобальный объект IE With Events '-- и связывается с реально открытым экземпляром IE Set gobjWithEvents = New InternetExplorerWithEvents Set gobjWithEvents.IE = objIE Set objIE = Nothing gblnInternetExplorerIsOpen = True End Sub При открытии Internet Explorer устанавливаются два свойства: Silent и Visible. Свойство Silent разрешает или запрещает диалоговое общение Internet Explorer с пользователем, а свойство Visible определяет видимость окна Internet Explorer на экране дисплея. По умолчанию, Internet Explorer запускается невидимым. Вторая процедура выполняет действия прямо противоположные. Internet Explorer закрывается с помощью метода Quit, объектная переменная освобождается, и флаг открытого состояния сбрасывается: Public Sub InternetExplorerClose() '-- Процедура закрывает Internet Explorer, '-- и освобождает глобальную объектную переменную If gblnInternetExplorerIsOpen Then '-- Закрывается копия IE gobjWithEvents.IE.Quit Set gobjWithEvents = Nothing gblnInternetExplorerIsOpen = False End If End Sub Третья процедура выполняет более содержательную работу, а именно инициирует поиск и загрузку необходимой Web страницы. Как уже отмечалось выше, загрузка страницы только "заказывается", а что произойдет в действительности, зависит от состояния компонентов сети. На всякий случай, "заказанный" URL страницы запоминается в глобальной переменной. Это позволит в дальнейшем проверить, та ли страница открыта, которая требовалась. Обратите внимание на параметры, которые передаются процедуре обработки события DocumentComplete. Один из этих параметров - URL открытой страницы. Именно его следует сравнивать с исходным значением. Здесь, как говорится, возможны варианты. Причина несоответствия URL заключается не только в отсутствии нужной страницы или отказе сервера. Проблемы возникают и при открытии страниц с фреймами. Так, например, если необходимая страница содержит три фрейма, то состояние DocumentComplete возникает целых семь раз: три раза с пустым значением URL в процессе разметки, три раза с URL страниц, загружаемых во фреймы, и, наконец, с URL страницы, указанной при вызове метода Navigate. Есть еще одна особенность, которую следует учитывать при сравнении URL. В строковом параметре URL метода Navigate необходимо обязательно указывать протокол в виде "http://", "ftp://" или "file://", если вдруг понадобится открыть документ на локальном компьютере. В последнем случае, префикс "file://", при возникновении события DocumentComplete, будет опущен. Процедура, предусматривающая этот нюанс, приведена ниже. Public Sub InternetExplorerNavigate(ByVal strURL As String) '-- Процедура вызывает метод Navigate '-- для открытия необходимой Web страницы '-- и сохраняет URL в глобальной переменной If gblnInternetExplorerIsOpen Then '-- Сохранение URL в глобальной переменной If Left(strURL, 7) <> "file://" Then gstrURL = strURL Else gstrURL = Mid(strURL, 8) End If With gobjWithEvents.IE '-- URL страницы отравляется на сервер .Navigate strURL End With End If End Sub Обработка HTML документа. Все процедуры, представленные выше, имеют общий характер, и могут использоваться в разных приложениях в неизменном виде. Непосредственно обработка загруженной Web страницы зависит от конкретных потребностей. Ниже будут показаны только начальные возможности. Прежде всего, следует уяснить, что введенный объект Internet Explorer построен на основе объектной модели Microsoft Internet Controls, которая не содержит каких-либо средств доступа непосредственно к содержимому документа. Свойство InternetExplorer.document предоставляет только ссылку на некий обобщенный объект, не имеющий собственных свойств и методов. Очевидно, это сделано потому, что компонента Microsoft Internet Controls, предназначена для реализации различных протоколов Internet, а не для работы с документами. Поэтому, первое, что необходимо сделать, это обеспечить процедуру обработки необходимой объектной моделью документа. Раз уж речь зашла о Web страницах, то в качестве объектной модели следует использовать Microsoft HTML Object Library, то есть именно ту среду, с которой оперируют всевозможные JavaScript и VBScript, создаваемые Web программистами. В нашем случае, процедура обработки документа вызывается обработчиком события DocumentComplete из модуля класса Internet Explorer With Events. Это означает, что некий документ полностью загружен, и самое время создавать нужный объект. Создание объекта выполнятся традиционно. Используется описание объектной переменной класса HTMLDocument и инструкция Set, присваивающая объектной переменной ссылку на объект, адресуемый свойством document объекта Internet Explorer. Все остальные объявления зависят от конкретного применения процедуры. В приведенном ниже примере, дополнительно описана объектная переменная класса HTMLLinkElement, обеспечивающая доступ к семейству гиперссылок. В начале процедуры выполняется сравнение URL, необходимость которого была обоснована выше. Public Sub DocumentComlete(varURL As Variant) '-- Процедура вызывается событием DocumentComlete, '-- сравнивает URL загруженной страницы, '-- создает объект HTML Document '-- и выполняет необходимые действия с '-- содержимым Web страницы Dim objDoc As HTMLDocument Dim objLink As HTMLLinkElement Dim strLink As String '-- Проверка URL загруженной страницы If varURL <> gstrURL Then Exit Sub '-- Создание объекта HTML Document Set objDoc = gobjWithEvents.IE.document '-- Обработка документа With objDoc '-- Отладачная печать всех полных ссылок For Each objLink In .links strLink = objLink.toString If Left(strLink, 4) = "http" Then Debug.Print strLink & " " & objLink.innerText End If Next '-- Отладочная печать текста и HTML кода документа Debug.Print .body.innerText Debug.Print .body.innerHTML End With Set objDoc = Nothing End Sub В приведенной в качестве примера, процедуре обработки документа, выполнятся хорошо знакомая всем офисным программистам конструкция For Each… Next. С помощью этой конструкции осуществляется просмотр множества всех ссылок в документе с целью выделения и печати ссылок с полным URL. Нечто подобное можно использовать при анализе страниц порталов и поисковых систем. После цикла обработки ссылок помещены два оператора, печатающие различные представления документа в целом. Такие же свойства можно использовать для разбора (parse) как текста, так и HTML кода, по собственному алгоритму. Реализация процесса. Выше были представлены четыре процедуры, составляющие основу механизма взаимодействия проекта Office с Internet Explorer. Эти процедуры открывают приложение Internet Explorer, запускают процесс навигации, обрабатывают полученный результат и закрывают приложение. При этом процессы навигации и обработки могут повторяться многократно, сообразно интересам пользователя. Список URL открываемых страниц можно задавать заранее или формировать динамически, основываясь на анализе данных, полученных при обработке предшествующих страниц. Можно даже некоторым образом повторить работу таких приложений как Teleport Pro, скачивающих из сети целые сайты. Как бы то ни было, совершенно очевидно, что для создания работающего проекта необходима еще одна программа, осуществляющая планирование и диспетчеризацию обращения к перечисленным процедурам. Необходимость в такой внешней программе - мониторе, вызвана еще и тем, что в процессе задействованы ненадежные компоненты и оплачиваемые средства коммуникации. Вряд ли следует, запустив навигацию, беспечно ожидать непременного наступления события DocumentComplete. Весь опыт работы с Internet в интерактивном режиме свидетельствует об обратном. Поэтому, при разработке монитора, необходимо позаботится о постоянном контроле над состоянием в режиме online и предусмотреть переключение процедур, если загрузка очередной страницы затягивается сверх установленного лимита времени. Если попытаться сформулировать требования к монитору, то получится, что эта программа должна обеспечивать следующие функции: - открывать и закрывать Internet Explorer, в том числе и по желанию пользователя;
- хранить и обновлять список URL, запланированных для обработки;
- хронометрировать продолжительность загрузки отдельной страницы и всего сеанса работы с Internet;
- запускать очередной процесс навигации, как после завершения обработки очередной страницы, так и по истечению заданного лимита времени;
- переключать режим визуального отображения окна Internet Explorer;
- отображать состояние процесса загрузки очередной страницы.
К этим требованием можно добавить также ведение протокола процесса, если, конечно, процедуры обработки не предусматривают вывод результатов непосредственно в открытые документы Office. Совершенно очевидно, что для удовлетворения всех требований вполне подходит форма VBA c обычными элементами управления, оснащенная таймером. Пример такой формы приведен на рис. 1. Рис. 1. Монитор чтения Web страниц в процессе работы. Список URL хранится в элементе управления ListBox, что позволяет управлять им проще, чем в случае использования динамических массивов. Элементы управления CheckBox напрямую связаны с соответствующими свойствами объекта InternetExplorer. Запуск и остановка процесса выполняется с помощью командных кнопок. Время и состояние отображаются в обычных окнах TextBox. При этом номер шага и общее количество шагов, берутся непосредственно из свойств ListIndex и ListCount списка URL. Наглядности ради, продолжительность загрузки страницы изображается в виде имитации ProgressBar. Что же касается состояния процесса загрузки, то здесь необходимо сделать некоторые пояснения. Объект InternetExplorer имеет очень полезное для контроля состояния свойство, которое носит имя readyState. Это свойство принимает пять значений от 0 до 4. Значение 4 соответствует состоянию Complete, переход в которое, в нашем примере вызывает прерывание и вызов процедуры обработки. Отображая значения указанного свойства в окне состояния, можно прекрасно ориентироваться в происходящем "за кадром". Из приведенного описания программы - монитора и соответствующей формы становится ясно, что ключевую функцию в процессе несет процедура, вызываемая таймером. Именно в этой процедуре происходит анализ состояния, визуальное отображение и переключение процесса. Полный текст этой процедуры помещен ниже. Private Sub IeTimer_Timer() '-- Обработка окончания паузы ожидания: '-- отображение состояния IE, '-- инициация загрузки следующей страницы, '-- завершение работы, когда список страниц исчерпан. TextTime.Value = Format(Now - datStart, "hh:mm:ss") '-- проверка состояния IE If gblnInternetExplorerIsOpen Then Select Case gobjWithEvents.IE.readyState Case READYSTATE_COMPLETE TextReadyState.Value = "Complete" blnDone = True Case READYSTATE_INTERACTIVE TextReadyState.Value = "Interactive" blnDone = False Case READYSTATE_LOADED TextReadyState.Value = "Loaded" blnDone = False Case READYSTATE_LOADING TextReadyState.Value = "Loading" blnDone = False Case READYSTATE_UNINITIALIZED TextReadyState.Value = "Uninitialized" blnDone = False Case Else TextReadyState.Value = "Undefined" blnDone = False End Select End If '-- проверка продолжительности загрузки If LabelBar.Width intBarInc < TIME_LIMIT Then LabelBar.Width = LabelBar.Width + intBarInc Else blnDone = True End If '-- загрузка следующей страницы или конец работы If blnDone Then If ListURL.ListIndex < ListURL.ListCount - 1 Then ListURL.ListIndex = ListURL.ListIndex + 1 TextStep.Value = (ListURL.ListIndex + 1) & _ " / " & ListURL.ListCount LabelBar.Width = 0 InternetExplorerNavigate ListURL.Value Else InternetExplorerClose IeTimer.Enabled = ValFalse End If End If End Sub Как видно из приведенного текста, переход к очередному этапу осуществляется с помощью булевской переменной blnDone, которая принимает значение ИСТИНА в случае исчерпания времени ожидания или появления значения свойства readyState = READYSTATE_COMPLETE. Поскольку прерывание от таймера наступает позже, чем событие DocumentComplete (наша машина однопроцессорная!) то переход в это состояние означает, что обработка станицы уже завершена. Справедливости ради следует отметить, что в ряде случаев обработку страницы можно начинать и при readyState = READYSTATE_INTERACTIVE. Это то самое состояние, когда Internet Explorer позволяет просматривать страницу в интерактивном режиме, хотя еще не все еще компоненты загружены. Начиная с этого состояния, HTML код вполне пригоден для обработки. Если для решения задач пользователя, кода HTML достаточно, то можно несколько ускорить процесс, поместив вызов обработчика страниц в приведенную выше процедуру в конструкцию Select Case для состояний READYSTATE_INTERACTIVE и READYSTATE_COMPLETE. В этом случае, событие DocumentComplete нужно заблокировать. Для того чтобы уж совсем минимизировать время загрузки, необходимо использовать пару событий NavigateComplete2 и DownloadComplete. Событие NavgateComplete2 возникает, когда документ объявляется найденным и его URL попадает в стек навигации и становится доступным для проверки. Событие DounloadComplete, не имеющее параметров вызова, возникает неоднократно. Вначале перед событием NavigateComplete2, а потом, после него. Именно наступление события DounloadComplete вслед за событием NavigateComplete2 соответствует переходу в состояние READYSTATE_INTERACTIVE и может использоваться для вызова процедуры обработки кода Web страницы. Надеюсь, что приведенные примеры послужат хорошей отправной точкой разработчикам офисных приложений и стимулируют создание интересных проектов, использующих неисчерпаемый источник информации - Internet. Оригинал статьи Просмотров: 12125
Ваш коментарий будет первым | | |