Задание: В 1С для каждой торговой точки записан адрес, необходимо по адресу торговой точки получить ее координаты, для последующего отображения на карте.
Решение: Для получения координат ТТ по адресу используется Google Maps Geocoding API, описание и документация здесь: https://developers.google.com/maps/documentation/geocoding/intro?hl=ru
"Быстрое" решение - использование функций v7plus.dll:
"Быстрое" решение было рабочим, однако, периодически ответ сервера усекался до 1-2 килобайт. При этом если строку запроса вставить в браузер - всегда возвращается нормальный ответ.
Оказалось, проблема известная, рассматривалась неоднократно:
1. V7Plus не полностью выкачивает страничку
"AddIn.V7HttpReader прекрасно работает с любыми страницами и качает всю как надо. Проблема в самих страницах, которые не отдают заголовок "Content-length". Поэтому по-умолчанию используется 1Кб."
2.V7HttpReader метод получить файл
"С помощью метода ПолучитьКакФайл пытаюсь с сайта выгрузить файл xml нужного формата. Проблема - файл не загружается полностью. ... Пробовал по всякому и через ПолучитьКакСтроку и с циклом после получения (типа для докачивания, если оно в фоне).
Все-равно файл загружается не полностью. Если через браузер все скачивается без проблем."
"Это не работает, когда динамически генерируется страница через пост-запрос. ПолучитьКакФайл работает для скачивания ТОЛЬКО статического содержимого."
И приводится код решения:
В итоге, пришлось переписать процедуру на вариант с использованием Microsoft.XMLHTTP +
ADODB.Stream + MSScriptControl.ScriptControl.
Код функции под катом:
Функция ПолучитьКоординатыТТПоАдресу1С(_Адрес)
сз = СоздатьОбъект("СписокЗначений");
ПолноеИмяФайла = КаталогВременныхФайлов() + "geocoding_answer.xml";
Имя = "";
Пароль = "";
Адрес = "http://maps.googleapis.com/maps/api/geocode/xml?address=";
Адрес = Адрес + "ukraine" + "," + СокрЛП(_Адрес);
Адрес = Адрес + "&components=country:UA";
XMLHTTP = CreateObject("Microsoft.XMLHTTP");
XMLHTTP.Open("GET", Адрес, 0, Имя, Пароль);
XMLHTTP.Send();
Stream = CreateObject("ADODB.Stream");
Stream.Mode = 3;
Stream.Type = 1;
Stream.Open();
Скрипт = СоздатьОбъект("MSScriptControl.ScriptControl");
Скрипт.language = "vbscript";
Скрипт.AddObject("Stream", Stream);
Скрипт.AddObject("XMLHTTP", XMLHTTP);
Скрипт.Eval("Stream.Write(XMLHTTP.responseBody)");
// сохраняем результат во временный файл
Stream.SaveToFile(ПолноеИмяФайла, 2);
// а теперь прочитаем полученный и записанный файл
XMLАнализатор = СоздатьОбъект("AddIn.XMLParser");
док = XMLАнализатор.СоздатьДокумент();
//док.Кодировка="UTF-8"; // пока работает и без этого
Попытка
док.Загрузить(СокрЛП(ПолноеИмяФайла));
Исключение
Сообщить("Операция не вполнена: " + ОписаниеОшибки());
Сообщить("Файл " + СокрЛП(ПолноеИмяФайла) + " поврежден или удален.");
Возврат 0;
КонецПопытки;
КорневойУзел = док.ЭлементДокумента; // корневой узел документа
УзелСтатуса = КорневойУзел.ВыбратьУзел("status");
сз.ДобавитьЗначение(УзелСтатуса.Значение, "СтатусОтветаСервера");
УзелРезультата = КорневойУзел.ВыбратьУзел("result");
УзелАдреса = УзелРезультата.ВыбратьУзел("formatted_address");
сз.ДобавитьЗначение(УзелАдреса.Значение, "АдресGoogle");
Узел_geometry = УзелРезультата.ВыбратьУзел("geometry");
Узел_location = Узел_geometry.ВыбратьУзел("location");
УзелШироты = Узел_location.ВыбратьУзел("lat");
сз.ДобавитьЗначение(Число(УзелШироты.Значение), "ШиротаGoogle");
УзелДолготы = Узел_location.ВыбратьУзел("lng");
сз.ДобавитьЗначение(Число(УзелДолготы.Значение), "ДолготаGoogle");
Узел_location_type = Узел_geometry.ВыбратьУзел("location_type");
сз.ДобавитьЗначение(Узел_location_type.Значение, "ТипОтветаСервера");
//
XMLHTTP = 0;
Stream = 0;
Скрипт = 0;
XMLАнализатор = 0;
//
Возврат сз;
КонецФункции
Решение: Для получения координат ТТ по адресу используется Google Maps Geocoding API, описание и документация здесь: https://developers.google.com/maps/documentation/geocoding/intro?hl=ru
"Быстрое" решение - использование функций v7plus.dll:
Функция ПолучитьОтветСлужбыГеокодирования(_Адрес)
Попытка
Соединение = СоздатьОбъект("Addin.V7HttpReader");
Соединение.КоличествоПопытокАвторизации = 10;
Исключение
Сообщить("Не удалось создать объект Addin.V7HttpReader!");
Возврат 0;
КонецПопытки;
// можем указать json или xml
Соединение = СоздатьОбъект("Addin.V7HttpReader");
Соединение.КоличествоПопытокАвторизации = 10;
Исключение
Сообщить("Не удалось создать объект Addin.V7HttpReader!");
Возврат 0;
КонецПопытки;
// можем указать json или xml
Адрес = "http://maps.googleapis.com/maps/api/geocode/xml?address=";
Адрес = Адрес + "ukraine" + "," + СокрЛП(_Адрес);
Адрес = Адрес + "&components=country:UA";
Адрес = Адрес + "&components=country:UA";
Стр = ""; // сюда вернется xml или json ответ сервера, который
Попытка
Соединение.Получить(Адрес, Стр, 2); //строка
Исключение
Исключение
Сообщить("Неудачная попытка соединения.");
КонецПопытки;
Возврат стр;
КонецФункции
КонецПопытки;
Возврат стр;
КонецФункции
"Быстрое" решение было рабочим, однако, периодически ответ сервера усекался до 1-2 килобайт. При этом если строку запроса вставить в браузер - всегда возвращается нормальный ответ.
Оказалось, проблема известная, рассматривалась неоднократно:
1. V7Plus не полностью выкачивает страничку
"AddIn.V7HttpReader прекрасно работает с любыми страницами и качает всю как надо. Проблема в самих страницах, которые не отдают заголовок "Content-length". Поэтому по-умолчанию используется 1Кб."
2.V7HttpReader метод получить файл
"С помощью метода ПолучитьКакФайл пытаюсь с сайта выгрузить файл xml нужного формата. Проблема - файл не загружается полностью. ... Пробовал по всякому и через ПолучитьКакСтроку и с циклом после получения (типа для докачивания, если оно в фоне).
Все-равно файл загружается не полностью. Если через браузер все скачивается без проблем."
"Это не работает, когда динамически генерируется страница через пост-запрос. ПолучитьКакФайл работает для скачивания ТОЛЬКО статического содержимого."
И приводится код решения:
Скрипт = СоздатьОбъект("MSScriptControl.ScriptControl");
Скрипт.language = "vbscript";
x = CreateObject("Microsoft.XMLHTTP");
x.Open("GET", АдресСтраницы, 0,"","");
x.Send();
s = CreateObject("ADODB.Stream");
s.Mode = 3;
s.Type = 1;
s.Open();
Скрипт.AddObject("s",s);
Скрипт.AddObject("x",x);
Скрипт.Eval("s.Write(x.responseBody)");
s.SaveToFile(ИмяФайлаЗагрузки, 2);
3. Наиболее подробно и полно вопрос рассматривается здесь: Мои опыты чтения динамических WEB-страниц- Вариант 1-5 - различные модификации использования V7HttpReader, и делается вывод, что внешняя компонента v7plus.dll и ее объект AddIn.V7HttpReader не годятся для чтения динамических WEB-страниц.
- Вариант 6: ФС.КопироватьФайл(Адрес,Результат) - нерабочий
- Вариант 7: WinHttp.WinHttpRequest.5.1
- Вариант 8: InternetExplorer.Application
- Вариант 9. MSXML2.XMLHTTP
- Вариант 10. WinHttp.WinHttpRequest.5.1 + MSScriptControl
- Вариант 11.MSXML2.XMLHTTP + MSScriptControl + VBScript
- Вариант 12. MSXML2.XMLHTTP (http-test.vbs + WScript.Shell)
- Вариант 13. Microsoft.XMLHTTP+ MSScriptControl+ADODB.Stream
В итоге, пришлось переписать процедуру на вариант с использованием Microsoft.XMLHTTP +
ADODB.Stream + MSScriptControl.ScriptControl.
Код функции под катом:
Функция ПолучитьКоординатыТТПоАдресу1С(_Адрес)
сз = СоздатьОбъект("СписокЗначений");
ПолноеИмяФайла = КаталогВременныхФайлов() + "geocoding_answer.xml";
Имя = "";
Пароль = "";
Адрес = "http://maps.googleapis.com/maps/api/geocode/xml?address=";
Адрес = Адрес + "ukraine" + "," + СокрЛП(_Адрес);
Адрес = Адрес + "&components=country:UA";
XMLHTTP = CreateObject("Microsoft.XMLHTTP");
XMLHTTP.Open("GET", Адрес, 0, Имя, Пароль);
XMLHTTP.Send();
Stream = CreateObject("ADODB.Stream");
Stream.Mode = 3;
Stream.Type = 1;
Stream.Open();
Скрипт = СоздатьОбъект("MSScriptControl.ScriptControl");
Скрипт.language = "vbscript";
Скрипт.AddObject("Stream", Stream);
Скрипт.AddObject("XMLHTTP", XMLHTTP);
Скрипт.Eval("Stream.Write(XMLHTTP.responseBody)");
// сохраняем результат во временный файл
Stream.SaveToFile(ПолноеИмяФайла, 2);
// а теперь прочитаем полученный и записанный файл
XMLАнализатор = СоздатьОбъект("AddIn.XMLParser");
док = XMLАнализатор.СоздатьДокумент();
//док.Кодировка="UTF-8"; // пока работает и без этого
Попытка
док.Загрузить(СокрЛП(ПолноеИмяФайла));
Исключение
Сообщить("Операция не вполнена: " + ОписаниеОшибки());
Сообщить("Файл " + СокрЛП(ПолноеИмяФайла) + " поврежден или удален.");
Возврат 0;
КонецПопытки;
КорневойУзел = док.ЭлементДокумента; // корневой узел документа
УзелСтатуса = КорневойУзел.ВыбратьУзел("status");
сз.ДобавитьЗначение(УзелСтатуса.Значение, "СтатусОтветаСервера");
УзелРезультата = КорневойУзел.ВыбратьУзел("result");
УзелАдреса = УзелРезультата.ВыбратьУзел("formatted_address");
сз.ДобавитьЗначение(УзелАдреса.Значение, "АдресGoogle");
Узел_geometry = УзелРезультата.ВыбратьУзел("geometry");
Узел_location = Узел_geometry.ВыбратьУзел("location");
УзелШироты = Узел_location.ВыбратьУзел("lat");
сз.ДобавитьЗначение(Число(УзелШироты.Значение), "ШиротаGoogle");
УзелДолготы = Узел_location.ВыбратьУзел("lng");
сз.ДобавитьЗначение(Число(УзелДолготы.Значение), "ДолготаGoogle");
Узел_location_type = Узел_geometry.ВыбратьУзел("location_type");
сз.ДобавитьЗначение(Узел_location_type.Значение, "ТипОтветаСервера");
//
XMLHTTP = 0;
Stream = 0;
Скрипт = 0;
XMLАнализатор = 0;
//
Возврат сз;
КонецФункции
Комментариев нет:
Отправить комментарий