IE 2016

Парсинг товаров сайта средствами 1С 8

Опубликовал opx в раздел Обмен - Интеграция с WEB

В этой статье я постараюсь описать процесс парсинга сайтов средствами 1С с примером. Это статья не является инструкцией к применению, а лишь демонстрирует возможности 1С.

Что мы имеем?

   1. Сайт в интернете, на котором располагается список товаров. В моем случае – это интернет магазин салона «Связной»
   2. Понимание основ сайтостроения… хотя бы знание HTML тегов
   3. Умение кодить в 1С 8

Все вышеперечисленные пункты в арсенале? Тогда читаем далее

Для начала парсинга стоит определиться с тем что мы хотим спарсить и какая у нас будет иерархия. В моем случае это - категория сотовых телефонов. Верхний уровень иерархии будет - производители. Почему именно так? Потому что я так захотел. Вы же вправе использовать любую иерархию. Далее нам будут интересны такие поля как: Наименование, Цена, Картинка и Описание... ну и пожалуй захватим операционную систему, чтобы пример получился более наглядным.

  1. Создаем внешнюю обработку. Те, кто не знают как это сделать - дальше могут не читать
  2. Создаем форму обработки с командной панелью снизу и сверху (они могут быть полезными)
  3. Размещаем на ней Панель и обзываем первую страницу "СамСайт"
  4. Кладем на страницу "СамСайт" ПолеHTMLДокумента и обзываем его к примеру "Сайт"
  5. Переименовываем кнопку "Выполнить", которая находится на нижней панели в "Загрузить сайт"
  6. Описываем процедуру нажатия на эту кнопку так:
ЭлементыФормы.Сайт.Перейти("http://www.svyaznoy.ru/catalog/phone/224"); //Категория с мобильными телефонами
  1. Проверяем работу нашей обработки. У меня появился сайт связного. А у Вас?


Дальше сложнее. Все еще хочешь парсить сайты? Тогда читай.

Сам парсинг сайта заключается в обходе всех элементов загруженной страницы, выдергивания необходимой информации и запихивания их в табличную часть. Для этого:

  1. Создадим табличную часть "Производители" с реквизитами "Отметка" (Булево), "Наименование" (Строка 100) и "Ссылка" (Строка 300).
  2. Добавляем еще одну страницу на панели и обзываем ее "Производители"
  3. Размещаем на этой странице одноименную табличную часть
  4. Добавляем на нижней панели кнопку "Заполнить производителей" с кодом:
Для Каждого Стр из ЭлементыФормы.Сайт.Документ.body.all Цикл
    Если Стр.tagName = "H1" и Стр.innerText = "Производители" Тогда
        Для Каждого опСтр из Стр.nextSibling.children Цикл
            новСтр = Производители.Добавить();
            новСтр.Наименование = опСтр.innerText;
            новСтр.Ссылка = опСтр.firstChild.href;
        КонецЦикла;
        Возврат;
    КонецЕсли;
КонецЦикла;

   Здесь напрашиваются небольшие пояснения:
   tagName - имя HTML тега в HTML документе
   nextSubling - следующий элемент HTML документа от текущего
   children - список дочерних элементов
   firstChild - первый дочерний элемент от текущего

  1. Проверяем. При проверке важно находиться на странице "СамСайт", чтобы заполнять производителей


Производители заполнены. Теперь к самим телефонам

  1. Создаем табличную часть "Товары" с реквизитами "Производитель" (Строка 100), "Наименование" (Строка 100), "Цена" (Число 10,2), "Картинка" (Строка 300), "Описание" (Строка Неограниченная), "ОС" (строка 100), "Ссылка" (Строка,300)
  2. Добавляем еще одну страницу на панели и обзываем ее "Товары"
  3. Размещаем на этой странице одноименную табличную часть
  4. Добавляем на нижней панели кнопку "Заполнить товары" с кодом:
Для Каждого Стр из Производители Цикл
    //Если отметку сняли - то не трогаем этого производителя
    Если Не Стр.Отметка Тогда
        Продолжить;
    КонецЕсли;
    Форма = ПолучитьФорму("ФормаТоваров");
    Форма.ЭлементыФормы.Сайт.Перейти(Стр.Ссылка);
    Форма.ТекущийПроизводитель = Стр;
    Форма.ОткрытьМодально();
КонецЦикла;
  1. Создаем форму обработки "ФормаТоваров"
  2. Кладем на "ФормаТоваров" ПолеHTMLДокумента и называем его "Сайт"
  3. На событие ДкументСформирован у ПоляHTMLДокумента пишем код:
Если ЭлементыФормы.Сайт.Документ.body.all.length>1 Тогда
    ГрузимТовары();
КонецЕсли;
  1. Создаем переменную в модуле формы
Перем ТекущийПроизводитель Экспорт;
  1. Создаем процедуру ГрузимТовары():
Процедура ГрузимТовары()
    Для Каждого Стр из ЭлементыФормы.Сайт.Документ.body.all Цикл
        Если Стр.className = "ct_desc cleared" Тогда
            новСтр = Товары.Добавить();
            Для Каждого опСтр из Стр.children Цикл
                Если опСтр.className = "pic_and_comp" Тогда
                    новСтр.Картинка = СтрЗаменить(Сред(опСтр.firstChild.style.backgroundImage,5),")","")
                КонецЕсли;
                Если опСтр.className = "name" Тогда
                    новСтр.Наименование = опСтр.innerText;
                    новСтр.Ссылка = опСтр.firstChild.href;
                КонецЕсли;
                Если опСтр.className = "price" Тогда
                    новСтр.Цена = Число(СтрЗаменить(СтрЗаменить(опСтр.innerText,"-","")," ",""));
                КонецЕсли;
                Если опСтр.className = "desc" Тогда
                    новСтр.Описание = опСтр.innerText;//опСтр.innerHTML - если нужно вместе с тегами
                КонецЕсли;
            КонецЦикла;
        КонецЕсли;
    КонецЦикла;
    Закрыть();
КонецПроцедуры
  1. Проверяем. Все работает.

Дело осталось за "операционной системой" и еще надо загрузить картинки. Давайте по порядку. Чтобы получить "ОС" нам надо открыть этот товар и считать "ОС" оттуда. Для этого делаем следующее:

  1. Добавляем на нижней панели кнопку "Доп Инфо" с кодом:
Для Каждого Стр из Товары Цикл
    Форма = ПолучитьФорму("ФормаДопИнфо");
    Форма.ЭлементыФормы.Сайт.Перейти(Стр.Ссылка);
    Форма.ТекущийТовар = Стр;
    Форма.ОткрытьМодально();
КонецЦикла;
  1. Создаем форму обработки "ФормаДопИнфо"
  2. Кладем на "ФормаДопИнфо" ПолеHTMLДокумента и называем его "Сайт"
  3. На событие ДкументСформирован у ПоляHTMLДокумента пишем код:
Если ЭлементыФормы.Сайт.Документ.body.all.length>1 Тогда
    ГрузимДопИнфо();
КонецЕсли;
  1. Создаем переменную в модуле формы
Перем ТекущийТовар Экспорт;
  1. Создаем процедуру ГрузимДопИнфо():
Процедура ГрузимДопИнфо();
    Для Каждого Стр из ЭлементыФормы.Сайт.Документ.body.all Цикл
        Если Стр.className = "card_spec" Тогда
            Для Каждого опСтр из Стр.children Цикл
                Если Найти(опСтр.innerText,"Операционная система:") Тогда
                    ТекущийТовар.ОС = СокрЛП(СтрЗаменить(опСтр.innerText,"Операционная система:",""));
                КонецЕсли;
            КонецЦикла;
        КонецЕсли;
    КонецЦикла;
    Закрыть();
КонецПроцедуры
  1. Проверяем и переходим к последнему пункту


Заметили как похожи две последние инструкции? То-то же. Стремился к универсальности. Ну и наконец последний этап - сохраним все изображения к примеру на диск "С" в папку "Svyaznoy". Поехали:

  1. Добавляем на нижней панели кнопку "Сохранить Картинки" с кодом:
Для Каждого Стр из Товары Цикл
    путьСамФайл = Лев(Стр.Картинка,Найти(Стр.Картинка,".jpg/") + 3);
    самФайл = СтрЗаменить(СтрЗаменить(ПутьСамФайл,"http://static.svyaznoy.ru/upload/iblock/",""),"/","");
    Стр.Картинка = СохранитьКартинкуСайта("C:\Svyaznoy",ПутьСамФайл,СамФайл);
КонецЦикла;
  1. Добавляем функцию СохранитьКартинкуСайта:
Функция СохранитьКартинкуСайта(КаталогСохранения,КартинкаНаСайте,КартинкаУНас)
    ИмяФайлаКартинки = КаталогСохранения + "\" + КартинкаУНас;
    ГетЗапрос = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
    ГетЗапрос.SetTimeouts(10000, 10000, 10000, 10000);
    БазовыйУРЛ = КартинкаНаСайте;
    Хидер1 = "Content-Type";
    Хидер2 = "image/jpg"; // Тип рисунка.
    ГетЗапрос.Open("GET", БазовыйУРЛ, False); // Синхронный режим.
    ГетЗапрос.setRequestHeader(Хидер1, Хидер2);
    ГетЗапрос.Send();
    СтатусОтправки = ГетЗапрос.status;
    Если СтатусОтправки <> 200 Тогда
        Сообщить("Ошибка отправки запроса на: "
                 + КартинкаНаСайте);
        Возврат "";
    КонецЕсли;       

    Стрим = Новый COMОбъект("ADODB.Stream");
    Стрим.Mode = 3;
    Стрим.Type = 1;
    Стрим.Open();
    Стрим.Write(ГетЗапрос.responseBody);

    Стрим.SaveToFile(ИмяФайлаКартинки, 2);
    Стрим.Close();
    Возврат ИмяФайлаКартинки;
КонецФункции

На этом наша эпопея с парсингом закончена. Это всего лишь пример того, как это можно сделать. Приложив сюда немного своего кода - можно сделать парсер для любого сайта.

Имея парсер 1С - я могу спарсить все, кроме этого парсера. Имея два парсера 1С - я могу спарсить все :)

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

Наименование Файл Версия Размер Кол. Скачив.
Обработка парсинга
.epf 15,72Kb
02.08.11
480
.epf 15,72Kb 480 Скачать

См. также

Лучшие комментарии

24. maloi_a (файл скачал) 08.08.2011 09:34
Замечание.
Процедуру для кнопки "Заполнить производителей"
надо начать с
Производители.Очистить();
Ответили: (25)
+ 1 [ opx; ]
# Ответить
4. BigB 02.08.2011 21:30
Вот тут http://infostart.ru/public/61194/ парсер JSONа. Может чем и пригодится.
Ответили: (7)
+ 1 [ msw2009; ]
# Ответить

Комментарии

1. opx 02.08.2011 18:17
Комментарии можете и сюда писать, но на своем блоге я их читаю чаще
# Ответить
2. cool.vlad4 02.08.2011 18:36
Я честно говоря 1С в этом плане невзлюбил...использую C# + htmlagilitypack(для более сложных случаев Watin)+ разбор xml (xpath/xslt или даже xquery- особенно удобно в качестве хранимых процедур в ms sql)...для пользователей делаю как правило консольные утилитки - url строка - и через stdin получение результата/либо через файл/либо через базу.
# Ответить
3. cool.vlad4 02.08.2011 18:40
Что для этого может понадобится....fiddler(локальный прокси, перехватывающий запросы для дебаггинга ), любой преобразователь html-xml(главное потом не забыть делать тесты именно на конечном xml, а не на html)-tidy,sgmlreader, htmlagilitypack и т.д. Что еще, какая-нибудь xpath тулза, их много...
# Ответить
4. BigB 02.08.2011 21:30
Вот тут http://infostart.ru/public/61194/ парсер JSONа. Может чем и пригодится.
Ответили: (7)
+ 1 [ msw2009; ]
# Ответить
5. alexk-is 02.08.2011 22:02
Может это поможет...
http://infostart.ru/public/19856/
Ответили: (6)
# Ответить
6. opx 02.08.2011 22:41
(5)Это вы про то, что надо было код подкрасить? Просто лень качать и устанавливать что-то. Было бы здорово, если б разработчики добавили такой функционал прямо в редактор на сайте
# Ответить
7. opx 02.08.2011 22:42
(4) И казалось бы... Причем тут крокодилы :) ) Без обид, но это совсем другая тема
# Ответить
8. Yashazz 02.08.2011 22:48
Ну и что? Очередной примитивный парсинг, частный случай. Такого тут бывало дофига.
Причём волшебная аббревиатура DOM тут так и не прозвучала. А жаль, я было понадеялся на настоящий обзор.
Ответили: (9)
# Ответить
9. opx 03.08.2011 01:38
(8) Что по-вашему должно было войти в настоящий обзор?
# Ответить
10. opx 03.08.2011 10:43
Если у кого-нибудь получилось по этой инструкции спарсить сайт - напишите. Будет интересно
Ответили: (52)
# Ответить
11. freest 03.08.2011 11:47
Когда-то давно писал парсер, цепляя эксплорер через COM соединение и пользуя его внутренний парсер.. скорость парсинга удручающая. С выходом 8.2 переписал, используя ЧтениеHTML и ПостроительДОМ, скорость возросла в десяток раз.

К чему я все это.. Я правильно понимаю, что ПолеHTMLДокумента - это фактически IE? И парсинг идет встроенным парсером эксплорера?
Ответили: (12) (13)
# Ответить
12. opx 03.08.2011 12:01
(11) Интересная тема про DOM. Может опишите свои методы парсинга?
Ответили: (14)
# Ответить
13. cool.vlad4 03.08.2011 12:06
(11) Да ПолеHtmlДокумента это обертка над IE. IE - это не один activex, а целый зоопарк. Часто используют shdocvw.dll и mshtml.dll. Первая это широко любимый, но медленный WebBrowser , а второй синтаксический html анализатор. Фиг знает, чего там в 8.2 быстрее, но терзают смутные сомнения, что 1С до сих пор эксплуатирует IE, возможно добавили свои примочки. Насчет быстродействия - а технология com никогда не отличалась быстротой. Здесь надо понимать задачи - если парсинг простейший как в описанной статье, то использовать браузер нецелесообразно, делайте get запрос, получайте html - трансформируйте в xml - затем получайте свою информацию (для данного случая - связного обход товаров через //div[contains(@class,'ct_el') ] затем /div[@class='name'] и т.д.) . Браузер нужен, когда используются более сложные технологии, которые другим путем не получить, например ajax.
Ответили: (14) (15)
# Ответить
14. freest 03.08.2011 12:20
(12) Я не являюсь экспертом в этой области, по этому не претендую на максимально оптимальный в плане быстродействия алгоритм. Но все же опишу. HTML код страницы получаю через HTTPСоединение

Соединение = Новый HTTPСоединение(Сервер);
Соединение.Получить(Адрес,ИмяФайла);

Далее полученный код загружаем в ЧтениеHTML.

ЧтениеХТМЛ = Новый ЧтениеHTML();
ЧтениеХТМЛ.ОткрытьФайл(ИмяФайла);

Ну и далее загружем в 1с-ный парсер xml и html - ПостроительDOM.

ПостроительДОМ = Новый ПостроительDOM;
ДокументХТМЛ = ПостроительДОМ.Прочитать(ЧтениеХТМЛ);

Работа с построителемДОМ схожа с работой парсера ИЕ, методы читать в хелпе. (Та же работа с коллекциями тегов - перебор, получение именованных тегов и т.д.)


(13) Все-таки построительDOM - встроенный парсер html и xml, имхо, IEшный он не использует.
Ответили: (17) (18)
# Ответить
15. opx 03.08.2011 12:20
(13) А что, если сайт использует куки? Как например их использует связной для подстановки города. А надо по другим городам парсить. Только браузером.
Ответили: (16) (17)
# Ответить
16. freest 03.08.2011 12:29
(15) Куки можно передавать 3м параметром "заголовки" у HTTPСоединение:

Соединение.Получить(Адрес,ИмяФайла,Заголовки);
# Ответить
17. cool.vlad4 03.08.2011 12:30
(15) куки передаются протоколом http, любой клиент http может передать куки, необязательно браузер.
(14) а пруфлинки по поводу Построителя есть или это догадки?
# Ответить
18. cool.vlad4 03.08.2011 12:33
(14) Он доступен под сервером, так, что по всей видимости они написали наконец-то свой, потому и быстрее. А работа похожа на IE , также как и на Mozzila , также как и т.п. DOM он везде DOM
Ответили: (19)
# Ответить
19. freest 03.08.2011 12:38
(18) Ну и хорошо, потому что пруфлинков не было у меня, только личные ощущения ;)
# Ответить
20. makeya (файл скачал) 05.08.2011 13:45
отличная обработка! хоть по мнению некоторых это и "примитивный парсинг", но меня натолкнуло на множество идей (хоть раньше и стояла задача по парсингу информации с сайта, парсить это средствами 1С даже в голову не приходило!).
спасибо автору за такое подробное описание и приятный код :)
Ответили: (21)
# Ответить
21. cool.vlad4 05.08.2011 14:13
(20)и что за идеи?
Ответили: (22)
# Ответить
22. makeya (файл скачал) 05.08.2011 14:30
(21) Просто идеи по созданию подобной обработки для решения своих задач (едва ли это касается этой ветки), достаточно удобно делать это средствами 1С, чтоб потом сразу же без лишних обменов данными и т.д. использовать собранную информацию. Хотя то, что вы описали во втором комментарии тоже чудно.
Ответили: (23)
# Ответить
23. opx 05.08.2011 16:05
(22) Все верно. Эта обработка и была сюда выложена для того, чтоб у людей появились собственные идеи и чтоб не делать всякие обмены и т.д.
# Ответить
24. maloi_a (файл скачал) 08.08.2011 09:34
Замечание.
Процедуру для кнопки "Заполнить производителей"
надо начать с
Производители.Очистить();
Ответили: (25)
+ 1 [ opx; ]
# Ответить
25. opx 08.08.2011 10:49
(24) Верное замечание.
# Ответить
26. Medvedik (файл скачал) 19.08.2011 09:41
Попробую использовать материал для написания парсера сайта конкурентов :)
Сдернуть у них описание и пикчи (в свой стартап, да такой я редис), в дальнейшем - мониторить цены (тут еще яндекс.маркет нужно будет анализировать, но это другая тема).
От меня +
Ответили: (27) (28)
# Ответить
27. opx 19.08.2011 15:28
(26) Я тоже думал о похожем стартапе. По идеи можно выдавать по 2-3 готовых интернет магазина в неделю. Главное наладить процесс. А, скажем, через год иметь более 100 сайтов и что-то да продавать. Вот такой вот я дорвейщик :)
# Ответить
28. djd.sf 19.08.2011 17:47
(26)Это не Вы ли парсите, что яндекс не работает? :D
Ответили: (29)
# Ответить
29. opx 20.08.2011 00:14
(28)откуда ты знаешь?
# Ответить
30. ac86 25.08.2011 17:59
А работает ли это чудо с установленным ИЕ9?
Ответили: (31)
# Ответить
31. opx 26.08.2011 15:01
(30) Я не знаю. По идеи - ничто не должно препятствовать этому. Попробуйте, чтобы знать наверняка
# Ответить
33. morfeus (файл скачал) 05.10.2011 09:19
Этот парсер только для одного сайта, а я делал для любого количества сайтов (Логика была в настройке закономерностей на основе тегов)
Ответили: (34)
# Ответить
34. opx 05.10.2011 18:19
(33)Я тоже сначала думал сделать универсальным с логикой на тегах, но это бы ограничило количество возможных сайтов для парсинга. Хотя может я и ошибаюсь. Я же не вижу вашей обработки.
Да и в целом - парсингом занимаются в основном программисты, а не конечные пользователи. Все равно код править.
# Ответить
35. Anton_prezident 12.02.2012 16:00
Спасибо,теперь ясно как работать в 1с с парсингом сайта
# Ответить
36. borrman 28.03.2012 23:40
А парсинг просто с использованием рег. выражений не будет работать быстрее? Или с ними будет больше мороки, чем реальной пользы?
Ответили: (37)
# Ответить
37. opx 29.03.2012 11:30
(36)Быстрее может и будет. Я не проверял. Меня вполне устраивает этот способ парсинга. Если наловчиться и использовать такие инструменты как firebug в firefox'е, 1с ну и конечно же мой подход - парсинг одного сайта с заливкой базу данных 1с займет около 3-4 часов. Регулярные выражения - для меня тема далекая (пользовался всего пару раз), да и штатных средств у 1с для работы с ними нет. А костыли я не люблю использовать.
А так конечно каждому самому выбирать. Что удобно - тем и пользоваться.
# Ответить
38. tolyan_ekb 02.05.2012 13:51
Плюсанул. Понятное введение и пример. Интересно было бы почитать про парсинг многостраничных сайтов с переходами внутри страничек.
Ответили: (39)
# Ответить
39. ksnik 15.08.2012 20:39
(38) tolyan_ekb, в открытой обработке http://infostart.ru/public/147622/ поддерживается многостраничность!
Только заметил эту статью, благодарю автора!
# Ответить
40. alexlights 18.08.2012 21:43
Хороший парсер. На основании этой обработки написал бота для браузерной игры :)
# Ответить
41. Masich (файл скачал) 16.09.2012 13:29
Спасибо.
Очень полезная статья для "входа в тему".
# Ответить
42. porfirius 25.06.2013 13:21
Спасибо, попробуем поработать в 1с с парсингом сайта
# Ответить
43. RBEvgenyPN (файл скачал) 02.09.2013 18:32
Добрый день. Скачал, попробовал, не работает. Не грузит нечего. Предположил что сайт немного видоизменили.
Немного подправил, получилось загрузить Производителей. После чего столкнулся с проблемкой.
Кто нибудь может мне растолковать как работает:"ЭлементыФормы.Сайт.Документ.body.all.length>1" на событие ДкументСформирован у ПоляHTMLДокумента. Почему то у меня пишет : "Поле объекта не обнаружено (length)". Что я делаю не так?
Ответили: (45)
# Ответить
44. sunlit (файл скачал) 29.10.2013 01:21
RBEvgenyPN тоже скачал и тоже не работает - расскажи, что поправил.
# Ответить
45. plevakin 12.12.2013 10:12
(43) RBEvgenyPN, не то, что ЭлементыФормы.Сайт.Документ.body.all.length не работает, а даже на all ругается. Заменил на Для Каждого Стр из ЭлементыФормы.Сайт.Документ.body.childNodes Цикл вроде пошло дело, но стало ругаться на следующую строчку, пришлось добавить заглушку
Попытка рТипУзла=Стр.nodeType Исключение рТипУзла=0 КонецПопытки;
Если рТипУзла<>1 Тогда Продолжить КонецЕсли;
Но производителей все равно не грузит, видимо действительно на сайте все стало по другому и тегов H1 там больше нет.
# Ответить
46. Makushimo 10.01.2014 07:58
а как вы выяснили, откуда грузить производителей и откуда сами телефоны?
от темы далек, но интересно
Ответили: (47)
# Ответить
47. opx 10.01.2014 09:43
(46)Любой сайт - это набор HTML тегов (инструкций для браузера как выводить информацию). По этим тегам и выясняем откуда грузить.
# Ответить
48. gosizo 31.01.2014 21:05
А как можно пройти авторизацию (логин и пароль есть) и затем пропарсить содержимое нужных страниц ?
Ответили: (49)
# Ответить
49. opx 01.02.2014 23:08
(48)Удивлен, что Вас заинтересовал этот метод парсинга. Сам я уже давно по-другому делаю. Этот пример скорее всего стоит пометить заголовком "Как не надо парсить сайты" )).
Способы авторизации разные бывают. Дайте сайт посмотреть.
Ответили: (50)
# Ответить
50. rustork 23.04.2014 14:08
(49) opx, А по-другому это как? Может статейку? :-)
# Ответить
51. angernaughts 20.11.2014 16:15
Описал немного иной способ парсить сайт, аналогичный этому, но без использования браузера на форме - http://infostart.ru/public/314045/
# Ответить
52. Alexey_A 08.01.2016 00:03
(10) opx, спасибо! начал путь парсинга с Вашей статьи!
к сожалению ДкументСформирован срабатывает совсем не как планируется, поэтому я сделал через предупреждение с паузой.
# Ответить
Внимание! За постинг в данном форуме $m не начисляются.
Внимание! Для написания сообщения необходимо авторизоваться
Текст сообщения*
Прикрепить файл






IE 2016