gifts2017

Мои опыты чтения динамических WEB-страниц

Опубликовал Александр (mai) в раздел Программирование - Практика программирования

В предлагаемой вашему вниманию обработке реализованы 13 вариантов чтения содержимого динамических WEB - страниц (для 1С-Предприятия 7.7) , а в сопутствующей ей статье - анализ недостатков и достоинств этих вариантов.

    (см. продолжение Еще раз о чтении динамических WEB-страниц)

    Понадобилось мне читать довольно быстро (несколько раз в минуту) меняющиеся данные на одной из динамических WEB - страниц, чтобы набрать некоторую статистику. В интернете обнаружилось довольно много материала на эту тему (см. ссылки), а в типовых конфигурациях  - примеров успешной реализации подобных задач. Например, это касалось отслеживания курса валют на сайте Центрального Банка Российской Федерации. В типовых конфигурациях для этого использовалась внешняя компонента v7plus.dll, ее объект AddIn.V7HttpReader и методы  ПолучитьКакСтроку(Адрес, Стр) и ПолучитьКакФайл(Адрес, Файл).

     Раньше мне не приходилось решать таких задач, поэтому я решил пойти проторенной дорожкой и использовать эти опробованные практикой "родные" для 1С средства. Однако первый же опыт применения ПолучитьКакСтроку(Адрес, Стр) дал отрицательный результат: динамическая WEB-страница читалась очень быстро (за секунды), но, к моему сожалению, урезалась до 1 - 2 кб (по разному для разных страниц и методов).   Попробовал ПолучитьКакФайл(Адрес, Файл) - та же история. Поняв, что с налету мне эту задачу не осилить, решил заняться более капитально. Сделал небольшую обработку ЧтениеWEBстраницы.ert , в которой протестировал несколько вариантов решения задачи, упоминавшихся в интернете в статьях и на форумах. (см. скриншот обработки)

    В качестве динамической WEB-страницы я использовал страницу файлового архива моего сайта http://www.almazsoft.ru/ (информация о скачиваниях файлов на ней меняется). При работе с этой обработкой Вы также можете использовать этот адрес http://www.almazsoft.ru/index.php?option=com_remository&Itemid=34&func=select&id=5, или ввести адрес любой другой известной Вам динамической WEB-страницы.

  • Вариант 3. V7HttpReader: Получить(Адрес,Результат, 1) - в файл и вариант 4. V7HttpReader: Получить(Адрес,Стр, 2) - в строку дали те же результаты, что и упомянутые выше варианты 1. V7HttpReader: ПолучитьКакСтроку(Адрес, Стр) и 2. V7HttpReader: ПолучитьКакФайл(Адрес, Результат). Их реализация не отняла много времени, по сути они делают одно и то же.
  • А вот с вариантом 5. V7HttpReader: Получить(Адрес,Стрим, 3) - в ADODB.Stream пришлось повозиться.   В интернете материалов по этой связке (1С +  v7plus.dll +  V7HttpReader: Получить(Адрес,Стрим, 3) +  ADODB.Stream) мне найти не удалось, пришлось искать в статьях похожие связки и пытаться их править под свою задачу. Однако, когда вариант удалось реализовать, он дал те же результаты, что и предыдущие 4 варианта: отличную скорость чтения и урезание содержимого страницы.
  • Вариант 6. ФС.КопироватьФайл(Адрес,Результат) пришлось добавить, потому, что в одном из форумов (http://www.itland.ru/forum/lofiversion/index.php/t21318.html) было высказано такое утверждение:  "И еще проще:
    КопироватьФайл("http://img.yandex.net/i/yandex-v9.gif","C:\temp.gif")". Пришлось его проверить. Как я понял, речь шла об  ФС.КопироватьФайл. Так вот, команда ФС.КопироватьФайл(Адрес,ФайлКопии) отрабатывает моментально и без ошибок, но ФайлКопии даже не создается. Что и ожидалось. Уж слишком просто.
  • Вариант 7. WinHttp.WinHttpRequest.5.1 вначале исследовался как 7. MSScriptControl + WinHttp + ADODB.Stream. Он был сделан на основе статьи http://www.itland.ru/forum/lofiversion/index.php/t21318.html путем небольшой модификации предложенного в ней кода. Вариант отрабатывал без ошибок, но в файл результата попадало только первые 3 символа текста динамической WEB-страницы. Дальнейшее изучение возможностей WinHttpRequest (см. http://msdn.microsoft.com/en-us/library/aa384106%28VS.85%29.aspx) и примера его использования в Visual Basic 6 (см. Retrieving Data Using Visual Basic) показало, что объекты  MSScriptControl и ADODB.Stream в этом коде вообще не нужны!. После их удаления и небольшой правки получился простой и понятный работающий код, полностью считывающий содержимое динамической WEB-страницы. Правда, скорость чтения примерно в 3 раза медленнее, чем в первых 5 вариантах.
  • Вариант 8. InternetExplorer.Application был реализован без проблем. Правда, работает он в 3-4 раза медленнее варианта 7. Но благодаря наличию у COM-объекта InternetExplorer.Application свойства document и метода getElementsByTagName(TagName) в этом варианте с динамической WEB-страницы может читаться не все содержимое, а только содержимое указанных тэгов. Это может значительно облегчить последующий парсинг содержимого. Поскольку разбор прочитанного содержимого динамической WEB-страницы выходит за рамки этой статьи, то не будем на нем останавливаться. По моему мнению (его надо проверить опытным путем), выгоды предварительного парсинга не компенсируют медленную скорость чтения. Парсинг - не такая уж сложная задача и не требует много времени.

Выводы

  1. По результатам вариантов 1-5 можно высказать утверждение, что внешняя компонента v7plus.dll и ее объект AddIn.V7HttpReader не годятся для чтения  динамических WEB-страниц.
  2. Для чтения часто меняющихся данных динамических WEB - страниц наиболее подходит вариант 7. WinHttp.WinHttpRequest.5.1.

На этом я собирался прекратить опыты и довольствоваться полученными результатами. Но, как оказалось, я рано обрадовался и поторопился с выводами по вариантам 7 и 8 . При новых опытах нашлась страница http://www.vezetmne.ru/rating?top500, на которой эти варианты заткнулись: в варианте 7 страница урезалась до 330 символов, а вариант 8 выдал ошибку доступа к странице. А в тех вариантах, в которых эта страница прочиталась,  оказалось, что вместо кириллицы в файле результата знаки вопроса, хотя При ручном сохранении этой страницы в htm или txt кириллица пишется в файл правильно.
Кроме того, один из участников обсуждения статьи предложил добавить вариант, использующий СоздатьОбъект("MSXML2.XMLHTTP"). Поэтому я решил продолжить опыты и опробовал еще 5 вариантов чтения динамических WEB - страниц. (см. новый скриншот обработки).

  • Вариант 9. MSXML2.XMLHTTP  сделан без использования MSScriptControl. Читает быстро. В заголовке запроса имеет средства для указания желаемой кодировки текста, получаемого от сервера, но манипуляции с ними не помогли избавиться от знаков вопроса в файле результата вместо кириллицы.
  • Вариант 10. WinHttp.WinHttpRequest.5.1 + MSScriptControl. Также работает  быстро. В заголовке запроса имеет богатые средства для настройки кодировки текста, но избавиться от знаков вопроса в файле результата вместо кириллицы не удалось.
  • Вариант 11.MSXML2.XMLHTTP +  MSScriptControl  + VBScript. Используется запуск встроенного скрипта, сделанного на основе vbs-скрипта HTTP-test.vbs, скачанного по ссылке в статье  Получение и отправка данных с других web-сайтов из asp-скрипта.  Страницу http://www.vezetmne.ru/rating?top500 прочитал без знаков вопроса в файле результата вместо кириллицы. Но читал очень долго, больше минуты, несколько раз запрашивал разрешения на продолжение чтения. 
  • Вариант 12. MSXML2.XMLHTTP (http-test.vbs + WScript.Shell) . Используется запуск указанного в варианте 11 внешнего vbs-скрипта HTTP-test.vbs. Работает аналогично варианту 11. Совершенно неприемлемая скорость чтения.
  • Вариант 13. Microsoft.XMLHTTP+ MSScriptControl+ADODB.Stream. Сделан на основе процедуры СохранитьФайлИзИнтернета(Ссылка), найденной в статье V7HttpReader, проблемы с его методами. Несмотря  на то, что это устаревший объект (был разработан еще для ИЕ 5.5), он, в отличие от современных объектов MSXML2.XMLHTTP и XMLHttpRequest, справился со всеми моими проблемами: показал вполне приемлемую скорость чтения и прочитал нормально ВСЕ предлагаемые ему динамические WEB - страницы,  в том числе и  каверзную страницу http://www.vezetmne.ru/rating?top500, причем нормально прочитал и кириллицу.  Наконец-то я  нашел то, что нужно.

Кстати, занятное совпадение: вариант 13, сегодня пятница, 13-е ноября. Сколько плохих примет. А у меня такая удача. Вот и верь после этого в несчастливые числа и плохие приметы!

Ссылки:

 

Скачать файлы

Наименование Файл Версия Размер Кол. Скачив.
Опыт чтения динамических WEB-страниц
.ert 17,00Kb
13.11.09
395
.ert 17,00Kb 395 Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. dushelov (Душелов) 07.11.09 20:44
2. Евгений Мартыненков (JohnyDeath) 07.11.09 22:16
Добротно написано, хорошие ссылки. Автор постарался. Плюс без разговоров!
3. Андрей (AndrewEv) 08.11.09 00:44
Звезда в шоке - то, о чём звезда мечтала прочитать...
+
4. Андрей (Свой) 08.11.09 02:02
5. Александр (mai) 08.11.09 13:33
Люди! Я очень благодарен вам за лестные отзывы и плюсы.
Но больше мне хотелось бы получить замечания, предложения и поправки, особенно от тех, кто уже сталкивался с такими задачами. Тем более, что в этих 8 вариантах, я уверен, можно найти ошибки или улучшения, а значит и мои выводы в статье могут оказаться не верными.
Прошу конструктивной критики.
6. Доржи Цыденов (support) 08.11.09 14:03
Подредактируйте текст, а то все сливается. Выделите списки, отделите абзацы. Там в редакторе есть замечательная кнопка "Full screen".
7. Александр (mai) 08.11.09 14:23
8. Алексей Плутенко (Noy) 08.11.09 14:29
Хорошее исследование. Правда я отдаю предпочтение варианту 8 - в большинстве случаев парсинг составляет 90% кода в подобных обработках.
Если же данные нужно получать быстро, то InternetExplorer.Application конечно проигрывает...
9. Александр (mai) 08.11.09 14:31
(6) Пытался в статье вместо ссылки на скриншот вставить саму картинку в натуральную величину и не смог. Требует УРЛ картинки и ссылку на путь к файлу на моем компе не понимает.
Подскажите, пожалуйста, как это сделать?
10. Александр (mai) 08.11.09 14:35
(8) А Ваш код по варианту 8 отличается от моего?
11. Алексей Плутенко (Noy) 08.11.09 14:36
8+ кстати InternetExplorer.Application можно несколько "ускорить" - обычно много времени тратится на загрузку - при этом 1С ждет пока загрузится страница (пустой цикл или слееп через вк)... я обычно кидаю на форму активикс, а 1С++ позволяет обрабатывать события активикс, а не тупо ждать загрузки. Такой метод позволяет почти "в фоне" загружать инфу
12. Алексей Плутенко (Noy) 08.11.09 14:37
(10) сорри, сейчас код посмотреть не могу (дома 1С-ки нет). В понедельник гляну - если что - подправлю комментарий.
13. Александр (mai) 08.11.09 14:39
14. Сергей (Che) Коцюра (CheBurator) 08.11.09 16:31
вопрос не в том, как прочитать вариантов7/8 - а почему предыдущие варианты не работают..???
15. Александр (mai) 09.11.09 05:26
Как оказалось, я рано обрадовался и поторопился с выводами по вариантам 7 и 8 .
При новых опытах нашлась страница http://www.vezetmne.ru/rating?top500, на которой эти варианты заткнулись: в варианте 7 страница урезалась до 330 символов, а вариант 8 выдал ошибку доступа к странице.
Возможно, это особая страница, которая имеет спец.защиту от автоматического "нечеловеческого" чтения роботами (где-то я видел упоминание о таких защитах).
А может руки кривые, и можно как-то улучшить код?

(14) Сам не понимаю почему варианты 1-5 не работают. Хотелось бы их использовать, читают они очень быстро. Может, удастся их усовершенствовать?
16. Алексей Плутенко (Noy) 09.11.09 12:45
(15) ты пробовал эту ссылку открывать руками в ИЕ? у меня не открывается.
Кстати, добавь еще метод чтения через СоздатьОбъект("MSXML2.XMLHTTP")

ЗЫ Код не понравился :(
17. Александр (mai) 09.11.09 13:26
(16) Точно, ИЕ вылетает с ошибкой. А в Firefoxe у меня нормально грузится. Поэтому и вариант 8 с этой страницей не работает.
Вариант с СоздатьОбъект("MSXML2.XMLHTTP") опробую и добавлю, если получится (С ХМЛ я еще не работал).
А какой код не понравился? Чем плох?

Ты же обещал свой код показать.Где он?
18. Алексей Плутенко (Noy) 09.11.09 14:31
(17) Мой код есть например тут: http://infostart.ru/public/19066/ - ничем не лучше твоего.
А код не понравился потому что ... просто не понравился. Это сугубо ИМХО - можешь не обращать внимания.
19. Александр (mai) 10.11.09 04:52
Напрасно скромничаешь. Код хорош. Нашел для себя много полезного. Спасибо. Плюс
Меня извиняет, что это просто тестовая обработка :oops:
20. Александр (mai) 11.11.09 05:16
По предложению (16) добавил вариант 9. MSXML2.XMLHTTP.
При этом выявилась еще одна пакость: при чтении некоторых страниц (например, http://www.vezetmne.ru/rating?top500) вместо кириллицы в файле результата знаки вопроса. Хотя, вроде бы, все сделал, чтобы кириллица читалась правильно:
XMLHTTP.SetRequestHeader("Connection", "close");
XMLHTTP.SetRequestHeader("Cache-Control", "no-cache");
XMLHTTP.SetRequestHeader("Accept-Language", "ru, en");
XMLHTTP.SetRequestHeader("Accept-Charset", "windows-1251;q=1, koi8-r;q=0.6, ISO-8859-5;q=0.4, ISO-8859-1;q=0.1");
XMLHTTP.SetRequestHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
При ручном сохранении этой страницы в htm или txt кириллица пишется в файл правильно.
Вопрос к гуру: как это поправить?
21. Артур Аюханов (artbear) 11.11.09 21:59
22. Александр (mai) 13.11.09 21:08
Добавил еще 5 вариантов в обработку, кое-что исправил. Добавил описания в статью. Наконец-то нашел то, что мне нужно - вариант 13. Microsoft.XMLHTTP+ MSScriptControl+ADODB.Stream. Он справился со всеми моими проблемами: показал вполне приемлемую скорость чтения и прочитал нормально ВСЕ предлагаемые ему динамические WEB - страницы, в том числе и каверзную страницу http://www.vezetmne.ru/rating?top500, причем нормально прочитал и кириллицу.

Кстати, занятное совпадение: вариант 13, сегодня пятница, 13-е ноября. Сколько плохих примет. А у меня такая удача. Вот и верь после этого в несчастливые числа и плохие приметы!
23. K Anna (annak2980) 01.12.09 01:52
Отличный анализ, ссылки - есть над чем поразмыслить и что попробовать.
Особенно на фоне убивающих бесполезностью публикаций типа очередная загрузка-выгрузка аля-"клиент-банк".
24. JD (elsystem) 04.01.10 06:00
Отлично! Приятно читать. Сам бы на такой отчет не решился !
+
25. mdbm (mdbm) 15.01.10 15:04
Прикольная статья. Плюс.
26. Виктор Азаров (azar323) 25.02.10 20:56
Сам использую WinHttpRequest для передачи информации на сайт из 7.7. Иногда случается, что сайт недоступен. В таком случае выполнение зависает. Причём применение метода SetTimeouts помогает мало. При установке таймаута в 1 секунду по его истечению вызывается исключение, отображающее соотв. ошибку, а вот дальше примерно 13 секунд объект WinHttpRequest не может уничтожиться (я использовал приравнивание его к нулю или к пустой строке, результат одинаков). Программа зависает и не реагирует ни на какие действия. С чем это может быть связано?
Кстати, а у XMLHTTP вообще невозможно установить таймаут - нет соотв. метода, так что там зависания ещё длительнее.
27. Денис (KrakoZyabl) 29.04.10 16:19
Спасибо за труд, полезная статья и обработка на примере какой можно учиться, набрел на статью случайно, выручила меня. ПЛЮС однозначно! ;)
28. Sergey (zsrg) 13.09.10 12:27
Неплохая подборка способов работы с веб-страничками.
Однако поправлю.
AddIn.V7HttpReader прекрасно работает с любыми страницами и качает всю как надо. Проблема в самих страницах, которые не отдают заголовок "Content-length". Поэтому по умолчанию используется 1Кб. Со своими сайтами решаем проблему легко, просто добавляем отдачу заголовка, а вот с другими "нерадивыми" сайтами можно работать предложенными в Ваше работе способами.

P.S. Заголовок "Content-length" не отдают, как правило, динамические страницы работающие на языках вроде PHP, так как на момент отправки заголовков еще не известен размер передаваемой страницы. Решается проблема использованием буфера вывода страницы. Сначала выводим страницу в буфер, затем определяем размер данных, передаем заголовок и только потом выдаем полученные данные. Для PHP делается просто:

ob_start();

.... код страницы
....
// Определяем размер
$size=ob_get_length();
// Передаем заголовок
header("Content-Length: $size");
// Выводим данные из буфера
ob_end_flush();
// Передаем все браузеру
flush();
29. Алексей Антонов (mezdrin) 13.09.10 13:25
Спасибо большое. Очень полезный анализ.
30. Александр (mai) 14.09.10 20:58
(28) Похоже, Вы хорошо разбираетесь в этом вопросе. Поэтому просьба: не могли бы Вы привести здесь или выслать мне рабочий пример на 1С, позволяющий читать динамические страницы с использованием AddIn.V7HttpReader. Я думаю, многим он был бы очень полезен.
31. Sergey (zsrg) 14.09.10 22:09
2mai, так Ваш пример и есть рабочий! Повторюсь, дело не в AddIn.V7HttpReader, а в отсутствии информации о размере полученной страницы. Прочтите еще раз внимательное мое сообщение. Я уже все подробно описал.
Вы молодец и примеры очень хорошие, я только уточнил почему себя так ведет AddIn.V7HttpReader . :)
32. Вадим Янчук (vadimlp77) 03.12.12 19:00
Молодец, я намучался искать почему моё "Получить" из v7plus режет xml от яндекс мэп. Спасибо за материал.
33. Вадим Карасев (2vadmaster) 14.11.13 17:22
"Мои опыты" - где нибудь в серьезном проекте твои опыты учавствуют? :-) Ставлю + за старания :-)
34. Александр (mai) 14.11.13 20:11
Все эти опыты - как раз поиск решения для одного моего проекта. Правда серьезным его назвать я не рискну.
35. Вадим Карасев (2vadmaster) 15.11.13 09:59
(34) mai, Мои "3 строки кода" стабильно и быстро работают в механизмах интеграции нескольких крупных компаний через WS (в том числе и не 1С) на Soap и JSON
36. Александр (mai) 15.11.13 11:01
(35) 2vadmaster, эти "3 строки кода" я могу посмотреть?
37. Вадим Карасев (2vadmaster) 15.11.13 15:53
(36) mai, Тут у меня http://infostart.ru/public/202482/ чел dimas103 сослался на вашу публикацию

3. dimas103 14.11.2013 16:57
И раз Опыт
И два Поиск в помощь
Вопросы были риторические, и ответа не требовали.
Обработка не содержит ничего интересного.
Вернее вопрос один сколько строчек кода?

Я ему попытался объяснить, что этот код работает и для HTTPS (просто 3 строчки кода как пример скачивания файлов) - видимо он не понял.

Я подумал, что эта разработка его, оказалось, что он просто на вашу публикацию сослался
38. Alexandr Климчук (undo) 30.12.13 01:59
Сначала использовал метод 7, но на некоторых сайтах получал проблему с кодировкой, но вариант 13 решил данную проблему работает чуть медленнее, но для меня это не критично.
"ADODB.Stream" использовал в обоих вариантах, так как информация приходит в utf-8
39. Алексей Алексеев (Aleksey_3) 11.07.16 15:33
Дано гугл картинки по адресу https://drive.google.com/file/...../view
Справился только 7 метод
1-4 методы Компонента V7Plus : Попытка использования недопустимого протокола обмена
5-6 файлы нулевого размера
8 метод скачал 1/5 часть страницы (причем хвостик в конце)
9 - ошибка доступа
10 - просто завис, устал ждать
11-12 - нулевой размер
13 - x.Send(); msxml3.dll: Access is denied.

При этом при попытки скачать картинку (https://lh6.googleusercontent.com/.....................)
только 13 метод смог скачать ей, остальные или нулевой размер или файл размером 10 байт с текстом "yOya.DExif" внутри
40. Сергей (Che) Коцюра (CheBurator) 06.11.16 17:48
"ФС.КопироватьФайл(Адрес,ФайлКопии) отрабатывает моментально и без ошибок, но ФайлКопии даже не создается. Что и ожидалось. Уж слишком просто."
возможно, отсутсвуют права на месторасположения файла-приемника
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа