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



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

Что мы имеем?

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

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

Заметка 2025 года: Это очень плохой способ парсинга. Даже не помню были тогда в 1С те средства, которыми можно парсить или нет. Хороший способ есть тут

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

  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С — я могу спарсить все 🙂

51 Comments

  1. opx

    Комментарии можете и сюда писать, но на своем блоге я их читаю чаще

    Reply
  2. cool.vlad4

    Я честно говоря 1С в этом плане невзлюбил…использую C# + htmlagilitypack(для более сложных случаев Watin)+ разбор xml (xpath/xslt или даже xquery- особенно удобно в качестве хранимых процедур в ms sql)…для пользователей делаю как правило консольные утилитки — url строка — и через stdin получение результата/либо через файл/либо через базу.

    Reply
  3. cool.vlad4

    Что для этого может понадобится….fiddler(локальный прокси, перехватывающий запросы для дебаггинга ), любой преобразователь html-xml(главное потом не забыть делать тесты именно на конечном xml, а не на html)-tidy,sgmlreader, htmlagilitypack и т.д. Что еще, какая-нибудь xpath тулза, их много…

    Reply
  4. BigB

    Вот тут http://infostart.ru/public/61194/ парсер JSONа. Может чем и пригодится.

    Reply
  5. alexk-is

    Может это поможет…

    http://infostart.ru/public/19856/

    Reply
  6. opx

    (5)Это вы про то, что надо было код подкрасить? Просто лень качать и устанавливать что-то. Было бы здорово, если б разработчики добавили такой функционал прямо в редактор на сайте

    Reply
  7. opx

    (4) И казалось бы… Причем тут крокодилы 🙂 ) Без обид, но это совсем другая тема

    Reply
  8. Yashazz

    Ну и что? Очередной примитивный парсинг, частный случай. Такого тут бывало дофига.

    Причём волшебная аббревиатура DOM тут так и не прозвучала. А жаль, я было понадеялся на настоящий обзор.

    Reply
  9. opx

    (8) Что по-вашему должно было войти в настоящий обзор?

    Reply
  10. opx

    Если у кого-нибудь получилось по этой инструкции спарсить сайт — напишите. Будет интересно

    Reply
  11. freest

    Когда-то давно писал парсер, цепляя эксплорер через COM соединение и пользуя его внутренний парсер.. скорость парсинга удручающая. С выходом 8.2 переписал, используя ЧтениеHTML и ПостроительДОМ, скорость возросла в десяток раз.

    К чему я все это.. Я правильно понимаю, что ПолеHTMLДокумента — это фактически IE? И парсинг идет встроенным парсером эксплорера?

    Reply
  12. opx

    (11) Интересная тема про DOM. Может опишите свои методы парсинга?

    Reply
  13. cool.vlad4

    (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.

    Reply
  14. freest

    (12) Я не являюсь экспертом в этой области, по этому не претендую на максимально оптимальный в плане быстродействия алгоритм. Но все же опишу. HTML код страницы получаю через HTTPСоединение

    Соединение = Новый HTTPСоединение(Сервер);

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

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

    ЧтениеХТМЛ = Новый ЧтениеHTML();

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

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

    ПостроительДОМ = Новый ПостроительDOM;

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

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

    (13) Все-таки построительDOM — встроенный парсер html и xml, имхо, IEшный он не использует.

    Reply
  15. opx

    (13) А что, если сайт использует куки? Как например их использует связной для подстановки города. А надо по другим городам парсить. Только браузером.

    Reply
  16. freest

    (15) Куки можно передавать 3м параметром «заголовки» у HTTPСоединение:

    Соединение.Получить(Адрес,ИмяФайла,Заголовки);

    Reply
  17. cool.vlad4

    (15) куки передаются протоколом http, любой клиент http может передать куки, необязательно браузер.

    (14) а пруфлинки по поводу Построителя есть или это догадки?

    Reply
  18. cool.vlad4

    (14) Он доступен под сервером, так, что по всей видимости они написали наконец-то свой, потому и быстрее. А работа похожа на IE , также как и на Mozzila , также как и т.п. DOM он везде DOM

    Reply
  19. freest

    (18) Ну и хорошо, потому что пруфлинков не было у меня, только личные ощущения 😉

    Reply
  20. makeya

    отличная обработка! хоть по мнению некоторых это и «примитивный парсинг», но меня натолкнуло на множество идей (хоть раньше и стояла задача по парсингу информации с сайта, парсить это средствами 1С даже в голову не приходило!).

    спасибо автору за такое подробное описание и приятный код 🙂

    Reply
  21. cool.vlad4

    (20)и что за идеи?

    Reply
  22. makeya

    (21) Просто идеи по созданию подобной обработки для решения своих задач (едва ли это касается этой ветки), достаточно удобно делать это средствами 1С, чтоб потом сразу же без лишних обменов данными и т.д. использовать собранную информацию. Хотя то, что вы описали во втором комментарии тоже чудно.

    Reply
  23. opx

    (22) Все верно. Эта обработка и была сюда выложена для того, чтоб у людей появились собственные идеи и чтоб не делать всякие обмены и т.д.

    Reply
  24. maloi_a

    Замечание.

    Процедуру для кнопки «Заполнить производителей»

    надо начать с

    Производители.Очистить();

    Reply
  25. opx

    (24) Верное замечание.

    Reply
  26. Medvedik

    Попробую использовать материал для написания парсера сайта конкурентов 🙂

    Сдернуть у них описание и пикчи (в свой стартап, да такой я редис), в дальнейшем — мониторить цены (тут еще яндекс.маркет нужно будет анализировать, но это другая тема).

    От меня +

    Reply
  27. opx

    (26) Я тоже думал о похожем стартапе. По идеи можно выдавать по 2-3 готовых интернет магазина в неделю. Главное наладить процесс. А, скажем, через год иметь более 100 сайтов и что-то да продавать. Вот такой вот я дорвейщик 🙂

    Reply
  28. djd.sf

    (26)Это не Вы ли парсите, что яндекс не работает? 😀

    Reply
  29. opx

    (28)откуда ты знаешь?

    Reply
  30. Aleanza

    А работает ли это чудо с установленным ИЕ9?

    Reply
  31. opx

    (30) Я не знаю. По идеи — ничто не должно препятствовать этому. Попробуйте, чтобы знать наверняка

    Reply
  32. morfeus

    Этот парсер только для одного сайта, а я делал для любого количества сайтов (Логика была в настройке закономерностей на основе тегов)

    Reply
  33. opx

    (33)Я тоже сначала думал сделать универсальным с логикой на тегах, но это бы ограничило количество возможных сайтов для парсинга. Хотя может я и ошибаюсь. Я же не вижу вашей обработки.

    Да и в целом — парсингом занимаются в основном программисты, а не конечные пользователи. Все равно код править.

    Reply
  34. Anton_prezident

    Спасибо,теперь ясно как работать в 1с с парсингом сайта

    Reply
  35. borrman

    А парсинг просто с использованием рег. выражений не будет работать быстрее? Или с ними будет больше мороки, чем реальной пользы?

    Reply
  36. opx

    (36)Быстрее может и будет. Я не проверял. Меня вполне устраивает этот способ парсинга. Если наловчиться и использовать такие инструменты как firebug в firefox’е, 1с ну и конечно же мой подход — парсинг одного сайта с заливкой базу данных 1с займет около 3-4 часов. Регулярные выражения — для меня тема далекая (пользовался всего пару раз), да и штатных средств у 1с для работы с ними нет. А костыли я не люблю использовать.

    А так конечно каждому самому выбирать. Что удобно — тем и пользоваться.

    Reply
  37. tolyan_ekb

    Плюсанул. Понятное введение и пример. Интересно было бы почитать про парсинг многостраничных сайтов с переходами внутри страничек.

    Reply
  38. ksnik

    (38) tolyan_ekb, в открытой обработке http://infostart.ru/public/147622/ поддерживается многостраничность!

    Только заметил эту статью, благодарю автора!

    Reply
  39. alexlights

    Хороший парсер. На основании этой обработки написал бота для браузерной игры 🙂

    Reply
  40. Masich

    Спасибо.

    Очень полезная статья для «входа в тему».

    Reply
  41. porfirius

    Спасибо, попробуем поработать в 1с с парсингом сайта

    Reply
  42. RBEvgenyPN

    Добрый день. Скачал, попробовал, не работает. Не грузит нечего. Предположил что сайт немного видоизменили.

    Немного подправил, получилось загрузить Производителей. После чего столкнулся с проблемкой.

    Кто нибудь может мне растолковать как работает:»ЭлементыФормы.Сайт.Документ.body.all.length>1″ на событие ДкументСформирован у ПоляHTMLДокумента. Почему то у меня пишет : «Поле объекта не обнаружено (length)». Что я делаю не так?

    Reply
  43. sunlit

    RBEvgenyPN тоже скачал и тоже не работает — расскажи, что поправил.

    Reply
  44. plevakin

    (43) RBEvgenyPN, не то, что ЭлементыФормы.Сайт.Документ.body.all.length не работает, а даже на all ругается. Заменил на Для Каждого Стр из ЭлементыФормы.Сайт.Документ.body.childNodes Цикл вроде пошло дело, но стало ругаться на следующую строчку, пришлось добавить заглушку

    Попытка рТипУзла=Стр.nodeType Исключение рТипУзла=0 КонецПопытки;

    Если рТипУзла<>1 Тогда Продолжить КонецЕсли;

    Но производителей все равно не грузит, видимо действительно на сайте все стало по другому и тегов H1 там больше нет.

    Reply
  45. Makushimo

    а как вы выяснили, откуда грузить производителей и откуда сами телефоны?

    от темы далек, но интересно

    Reply
  46. opx

    (46)Любой сайт — это набор HTML тегов (инструкций для браузера как выводить информацию). По этим тегам и выясняем откуда грузить.

    Reply
  47. gosizo

    А как можно пройти авторизацию (логин и пароль есть) и затем пропарсить содержимое нужных страниц ?

    Reply
  48. opx

    (48)Удивлен, что Вас заинтересовал этот метод парсинга. Сам я уже давно по-другому делаю. Этот пример скорее всего стоит пометить заголовком «Как не надо парсить сайты» )).

    Способы авторизации разные бывают. Дайте сайт посмотреть.

    Reply
  49. rustork

    (49) А по-другому это как? Может статейку? 🙂

    Reply
  50. angernaughts

    Описал немного иной способ парсить сайт, аналогичный этому, но без использования браузера на форме — http://infostart.ru/public/314045/

    Reply
  51. Alexey_A

    (10) спасибо! начал путь парсинга с Вашей статьи!

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

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *