helpf.pro
Регистрация
 +1 
Распечатать

Как мы писали парсер сайта с ценами для 1С

Недавно, мой постоянный клиент решил проводить маркетинговые исследования по изменению цен на товары у конкурентов... и эти данные захотел использовать в 1С в связке с его прайс-листом + куча отчетов с графиками и процентным отклонением от цен основного конкурента

В результате этого, была написана обработка собирающая данные со страниц разных сайтов. Из целей конфиденциальности - сайты раскрывать не буду...

Вид обработки загрузки данных с сайта в 1С

Ниже код загрузки данных со страницы сайта, смысл такой :

  • в функция передается адрес страницы сайта
  • полученный текст страницы обрабатывается, удаляются теги
  • из полученного текста формируется ТЗ с данными
  • По названию ищется поставщик из вспомогательного справочника Справочники.Pr_Поставщики.НайтиПоНаименованию(, если нет - создается
  • на выходе ТЗ с данными
Код 1C v 8.х
 Функция ПолучитьТаблицуДанных(Строка)
	
	тзДанных = Новый ТаблицаЗначений;
	Сервер = "site.ru";
	
	Соединение = Новый HTTPСоединение(Сервер);			
	Заголовки = Новый Соответствие;
	Заголовки.Вставить("host", Сервер);
	ТекАдрес = СтрЗаменить(Строка.Наименование.УРЛСтраницы,"http://","");
	ТекАдрес = СтрЗаменить(ТекАдрес,Сервер,"");
	Запрос = Новый HTTPЗапрос(ТекАдрес, Заголовки);
	Ответ =Соединение.Получить(Запрос);
	Если Ответ.КодСостояния = 200 Тогда // Данные получены, обрабатываем их
		Содержимое= Ответ.ПолучитьТелоКакСтроку();
		//Выведем тест полученной страницы
		НачалоБлока = "<table id=" + """" + "table-price" + """" + " cellspacing=" + """" + "0" + """" + " border=" + """" + "1" + """" + " bordercolor=" + """" + "#dedede" + """" + " class=" + """" + "tablesorter" + """" + " >";
		//НачалоБлока = "<div class=" + """" + "w100fl" + """" + " id=" + """" + "kurs" + """" + ">";
		КонецБлока = "</table>";
		ТекстБлока = Сред(Содержимое, Найти(Содержимое, НачалоБлока) + СтрДлина(НачалоБлока), Найти(Содержимое, КонецБлока) - Найти(Содержимое, НачалоБлока) - СтрДлина(НачалоБлока));
		    				
		//Обработаем тест  				
		обрТекст = СтрЗаменить(ТекстБлока,"<tr>","");
		обрТекст = СтрЗаменить(обрТекст,"</tr>",Символы.ПС);
		обрТекст = СтрЗаменить(обрТекст," >", ">");
		обрТекст = СтрЗаменить(обрТекст,"</th> <th>", " | ");
		обрТекст = СтрЗаменить(обрТекст,"</td> <td>", " | ");
	   	обрТекст = СтрЗаменить(обрТекст,"</th> <th class=" + """" + "sortable_header" + """" + ">", " | ");
		обрТекст = СтрЗаменить(обрТекст,"</th> <th >", " | ");
		обрТекст = СтрЗаменить(обрТекст,"</th><th>", " | ");
		обрТекст = СтрЗаменить(обрТекст,"</td><td>", " | ");
		обрТекст = СтрЗаменить(обрТекст," >", ">");
		RegExp = Новый COMОбъект("VBScript.RegExp");
		RegExp.IgnoreCase = Ложь; 
		RegExp.Global = Истина;    
		RegExp.MultiLine = Истина;    
		
		RegExp.Pattern = "<[^>]*>"; //Ищем теги HTML   
		обрТекст=RegExp.Replace(обрТекст, "");
		//Сообщить(обрТекст);
		
		Если СокрЛП(обрТекст) = "Ни одной позиции не найдено." Тогда
			Сообщить(Строка(Строка.Наименование)+ " = Ни одной позиции не найдено! Строка " + Строка.Наименование);
			Возврат тзДанных;
		КонецЕсли;


		Если Найти(обрТекст, "Страница не найдена") > 0 Тогда
			Сообщить(Строка(ТекАдрес)+" = Страница не найдена, строка " + Строка.Наименование);
			Возврат тзДанных;  
		КонецЕсли;
		
		//Преобразуем полученный текст в таблицу
		Для н=1 По СтрЧислоСтрок(обрТекст)Цикл
			СтрТекста=СтрПолучитьСтроку(обрТекст,н);
			Если Найти(СтрТекста, "Длина Цена") > 0 Тогда
				СтрТекста = СтрЗаменить(СтрТекста, "Длина Цена", "Длина | Цена");
			КонецЕсли;
			Если Найти(СтрТекста, "Марка стали Цена") > 0 Тогда
				СтрТекста = СтрЗаменить(СтрТекста, "Марка стали Цена", "Марка стали | Цена");
			КонецЕсли;
			Если Найти(СтрТекста, ",  Поставщик") > 0 Тогда
				СтрТекста = СтрЗаменить(СтрТекста, ",  Поставщик", " | Поставщик");
			КонецЕсли;
			//Выводим текст страницы построчно
			мсДанных = ПолучитьМассивИзСтрокиСРазделителем(СтрТекста, "|", Истина);
			Если н=1 Тогда
				Для Каждого ткЗнач из мсДанных Цикл
					СтрЗапрещСимволов = " .,<>""\/-";
					ИмяКолонки = ткЗнач;
					Для сч33 = 1 по СтрДлина(СтрЗапрещСимволов) Цикл
						ЗапрещСимв = Сред(СтрЗапрещСимволов, сч33, 1);
						ИмяКолонки = СтрЗаменить(ИмяКолонки, ЗапрещСимв, "_");
					КонецЦикла;
					
					// добавим нужное количество колонок- если перед колонкой Поставщик не хватает
					// бывает, что в шапке определяется меньше колонок, чем реально в таблице
					Если НРег(ИмяКолонки) = "поставщик" Тогда
						Для Сч_дк = (Строка.Наименование.Родитель.Поставшик - 2) по тзДанных.Колонки.Количество() Цикл
							тзДанных.Колонки.Добавить("Колонка_" + (тзДанных.Колонки.Количество() + 1));
						КонецЦикла;
					КонецЕсли;
					
					тзДанных.Колонки.Добавить(ИмяКолонки);
				КонецЦикла;
				тзДанных.Колонки.Добавить("ном", , , 7);
			Иначе 
				НовСтр = тзДанных.Добавить(); нмас=0;
				Для Каждого ткЗнач из мсДанных Цикл
					НовСтр[нмас] = ткЗнач;
					нмас=нмас+1;
				КонецЦикла;
				НовСтр.ном = н;
			КонецЕсли;
			//Сообщить(стр);
		КонецЦикла;
		тзДанных.Колонки.Добавить("ЕстьСоответствие", Новый ОписаниеТипов("Булево"));
		тзДанных.Колонки.Добавить("СпрPr_Поставщики", Новый ОписаниеТипов("СправочникСсылка.Pr_Поставщики"));
		
		Для каждого стр из тзДанных Цикл
			текПоставщик = Справочники.Pr_Поставщики.НайтиПоНаименованию(стр[Строка.Наименование.родитель.Поставшик-1]);
			Если текПоставщик = Справочники.Pr_Поставщики.ПустаяСсылка() Тогда
				НовЭлем = Справочники.Pr_Поставщики.СоздатьЭлемент();
				НовЭлем.Наименование = СокрЛП(стр[Строка.Наименование.родитель.Поставшик-1]);
				НовЭлем.Записать();
				текПоставщик = НовЭлем.Ссылка;
			КонецЕсли;
			стр.СпрPr_Поставщики = текПоставщик;
		КонецЦикла;
	Иначе
		тзДанных.Колонки.Добавить("ЕстьСоответствие", Новый ОписаниеТипов("Булево"));
		тзДанных.Колонки.Добавить("СпрPr_Поставщики", Новый ОписаниеТипов("СправочникСсылка.Pr_Поставщики"));
		
		Сообщить("Ошибка получения данных для строки " + Строка.Наименование);
	КонецЕсли;
	
	Возврат тзДанных;
	
КонецФункции   

В коде используется вспомогательная функция ПолучитьМассивИзСтрокиСРазделителем 

Код 1C v 8.2 УП
 // Функция разбивает строку разделителем.
// 
// Параметры:
//  пСтрока      - Строка - которую разбиваем;
//  *пРазделитель - Строка, "." - символ-разделитель;
//  *ОбрезатьНепечатныеСимволы - Булево, *Ложь.
//
// Возвращаемое значение:
//  Массив - фрагментов.
//
Функция ПолучитьМассивИзСтрокиСРазделителем(Знач Стр, Разделитель = ".", ОбрезатьНепечатныеСимволы = Ложь) Экспорт
	
	МассивСтрок = Новый Массив;
	
	Если Разделитель = " " Тогда
		Стр = СокрЛП(Стр);
		Пока 1=1 Цикл
			Поз = Найти(Стр,Разделитель);
			Если Поз=0 Тогда
				МассивСтрок.Добавить(Стр);
				Возврат МассивСтрок;
			КонецЕсли;
			МассивСтрок.Добавить(Лев(Стр,Поз-1));
			Стр = СокрЛ(Сред(Стр,Поз));
		КонецЦикла;
	Иначе
		ДлинаРазделителя = СтрДлина(Разделитель);
		Пока 1=1 Цикл
			Поз = Найти(Стр,Разделитель);
			Если Поз=0 Тогда
				Фрагмент = Стр;
				Если ОбрезатьНепечатныеСимволы Тогда
					Фрагмент = СокрЛП(Фрагмент);
				КонецЕсли;
				МассивСтрок.Добавить(Фрагмент);
				Возврат МассивСтрок;
			КонецЕсли;
			Фрагмент = Лев(Стр,Поз-1);
			Если ОбрезатьНепечатныеСимволы Тогда
				Фрагмент = СокрЛП(Фрагмент);
			КонецЕсли;
			МассивСтрок.Добавить(Фрагмент);
			Стр = Сред(Стр,Поз+ДлинаРазделителя);
		КонецЦикла;
	КонецЕсли;


	Возврат МассивСтрок;
		
КонецФункции // ПолучитьМассивИзСтрокиСРазделителем()   

Конечно, перед тем как мы начали это делать - прошерстили интернет и нашли несколько решений ), вот они:

Код 1C v 8.х
 Соединение = ПолучитьCOMОбъект("","Microsoft.XMLHTTP");
ИмяВременногоФайла=ПолучитьИмяВременногоФайла("htm");

Соединение.open("GET", "http://mamba.ru/my", 0);
Соединение.send();

//status: //404 - Not Found //200 - Ok
ТаймАут = 200;
Начало=ТекущаяДата();
Пока Соединение.readyState <> 4 И (ТаймАут=0 ИЛИ ТекущаяДата()-Начало<ТаймАут) Цикл
бфДиалоги.ксОбработкаПрерыванияПользователя();
КонецЦикла;

//Сохраняем во временный файл
обСохранитьДвоичныйБуферВФайл(Соединение.responseBody, ИмяВременногоФайла);

Соединение.open("POST", "http://mamba.ru/my");
Соединение.send("login=xxx&password=&&&");


Функция обСохранитьДвоичныйБуферВФайл(Буфер, ИмяФайла) Экспорт
    Поток = Новый COMОбъект("ADODB.Stream");
    Поток.Type = 1;  //Бинарный
       Поток.Mode = 3; 
    Поток.Open();
    Поток.Write(Буфер);
    Поток.SaveToFile(ИмяФайла);
    Поток.Close();
КонецФункции   
Код 1C v 8.х
     НТТР = ПолучитьCOMОбъект("","Microsoft.XMLHTTP");
    ИмяФайлаОтвета = КаталогВременныхФайлов() + "filename.tmp";           
    НТТР.open("GET", "www.google.com",0,,); 
    НТТР.send();
    StreamTypeEnum = Новый Структура("adTypeBinary, adTypeText", 1, 2);
    ConnectModeEnum = Новый Структура(
            "adModeRead, adModeReadWrite, adModeRecursive, adModeShareDenyNone,
            |adModeShareDenyRead, adModeShareDenyWrite, adModeShareExclusive, 
            |adModeUnknown, adModeWrite", 1, 3, 4194304, 16, 4, 8, 12, 0, 2);
    SaveOptionsEnum = Новый Структура("adSaveCreateNotExist, adSaveCreateOverWrite", 1, 2);
    StreamOut = Новый COMОбъект("ADODB.Stream");
    StreamOut.Type = StreamTypeEnum.adTypeBinary;
    StreamOut.Mode = ConnectModeEnum.adModeReadWrite; //Нужны и чтение и запись   
    StreamOut.Open(); //Открыли на чтение и запись
    StreamOut.Write(НТТР.responseBody); 
    StreamOut.SaveToFile(ИмяФайлаОтвета, SaveOptionsEnum.adSaveCreateOverWrite); //"2" - перезапись файла
    StreamOut.Close();   

И даже не этом сайте есть статья : Парсер сайта связного на 1С


Нужен парсер сайта в 1С!? - Обращайтесь, контакты в профиле )
Разместил:   Версии: | 8.x | 8.2 УП | 8.3 |  Дата:   Прочитано: 23235
 +1 
Распечатать
Возможно, вас также заинтересует
1C: Enterprise Development Tools 52
И вот случилось долгожданное: Вышел 1C: Enterprise Development Tools - это среда для разработки конфигурации в IDE Eclipse. С сайта 1С: « 1C:Enterprise Development Tools » – это инструмент нового поколения для разработчиков бизнес-приложений систем
1С 7.x : Как получить курсы валют с сайта НБУ http://www.bank.gov.ua/ за любую дату ? 6
Функция ПолучитьТаблицуКурсовНБУ(ДатаКурса, Ежедневно = 1) // если в качестве второго параметра указать число отличное от 1 - получем валюты, которые котируются на ежемесячной основе Перем Reader, Url, Точки, HtmlTab, Строк, Р, НомСтроки, НомЯче
Cодержимое указанного ниже веб-сайта в этом приложении блокируется... Aboutsecurity_1cv8c.exe 2
Проблема: После обновления на 1С:Бухгалтерию предприятия 3-й версии, при нажатии на закладку командного интерфейса 1С:предприятие, выскакивает ошибка: Aboutsecurity_1cv8c.exe или Aboutsecurity_1cv8.exe «Содержимое указанного ниже веб-узла в э
PostgreSQL: установка, настройка, обслуживание 12
PostgreSQL напрямую "из коробки" применяться для использования с 1С Предприятем не может. Необходима именно адаптированная версия от 1С, превращающая PostgreSQL в блокировочник, причем нужно понимать, что блокировки будут накладываться на всю таблиц
Автоматическая архивация баз 1С с использованием Cobian Backup и VBS скриптов 9
Клиент попросил настроить автоматическую архивацию баз 1С раз в три дня и выгрузку архивов на Dropbox и на FTP Сервер. Кроме 1С нужно архивировать папку с рабочими документами. Хочет - так хочет, делаем: Первым делом настроим автоматическую архивац
Посмотреть все результаты поиска похожих
Вы не можете отправить комментарий анонимно, пожалуйста войдите или зарегистрируйтесь.
Загрузка... Дождитесь завершения!