Компонент Парсер — различия между версиями

Материал из Oktell
Перейти к: навигация, поиск
(Язык OQuery для HTML)
м (Язык OQuery для HTML)
 
(не показаны 53 промежуточные версии этого же участника)
Строка 14: Строка 14:
  
 
В этой статье подробно рассматривается применение каждого алгоритма и примеры использования парсера.  
 
В этой статье подробно рассматривается применение каждого алгоритма и примеры использования парсера.  
 +
 +
 +
[[Файл:Парсер-001.png | center | 500 px]]
 +
  
  
 
=== Язык OQuery для HTML ===  
 
=== Язык OQuery для HTML ===  
  
Алгоритм OQuery применяется для разбора гипертекста или XML-структуры.
+
'''Язык OQuery''' применяется для разбора гипертекста или XML-структуры.  
  
Помимо разбора Web-страниц, в Oktell часто встречается задача обработки контента. Контентом называется идентификационная информация по линии, абоненту, времени, а также перечень всех коммутаций с указанием имени сценария, :идентификатора и имени оператора, времени начала, времени конца, продолжительности и пр. Контент хранится в виде XML-структуры и доступен в служебном сценарии обработки контента в качестве параметра запуска.  
+
Для тестирования запросов применяется программа [[Media:OQuery-tester.zip|'''OQuery-tester.exe''']].
  
vvv
+
Рассмотрим следующую XML-структуру:
  
   <?xml version="1.0" encoding="utf-16"?>
+
  <?xml version="1.0" encoding="utf-16"?>
 +
<info>
 +
<list index="1" name="matrix33">
 +
<row id="1" name="aaa">
 +
<col id="1" name="r1c1" />
 +
<col id="2" name="r1c2" />
 +
<col id="3" name="r1c3" />
 +
</row>
 +
<row id="2" name="bbb">
 +
<col id="1" name="r2c1" />
 +
<col id="2" name="r2c2" />
 +
<col id="3" name="r2c3" />
 +
</row>
 +
<row id="3" name="ccc">
 +
<col id="1" name="r3c1" />
 +
<col id="2" name="r3c2" />
 +
<col id="3" name="r3c3" />
 +
</row>
 +
</list>
 +
<list index="2" name="matrix22">
 +
<row id="1" name="ddd">
 +
<col id="1" name="element11" />
 +
<col id="2" name="element12" />
 +
</row>
 +
<row id="2" name="eee">
 +
<col id="1" name="element21" />
 +
<col id="2" name="element22" />
 +
</row>
 +
</list>
 +
<list index="3" name="matrixnull">
 +
        </list>
 +
</info>
  
Разберем использование алгоритма OQuery с помощью контента. Структура выглядит следующим образом:
+
XML-структура представляет из себя два листа, на первом листе матрица 3x3, на другом матрица 2x2. Ниже приведены запросы как можно добраться до каждого компонента в представленной структуре.
 +
 
 +
 
 +
* '''info''' - запрос отображает все теги ''<info>'' и их содержимое.
 +
 
 +
* '''list''' - запрос отображает все теги ''<list>'' и их содержимое. В примере, информация по двум листам.
 +
 
 +
* '''list[index="2"]''' - запрос отображает все теги ''<list index="2">'' (у которых атрибут index=2) и их содержимое. В примере, вся информация во втором листе.
 +
 
 +
* '''col[id="2"]''' - запрос отображает все теги ''<col id="2">'' (у которых атрибут id="2"). В примере, все элементы во втором столбце в обеих матрицах.
 +
 
 +
* '''list[index="2"] col[id="2"]''' - запрос отображает все теги ''<col id="2">'', которые находятся в ''<list index="2">''. В примере, это все элементы во втором столбце, которые находятся на втором листе.
 +
 
 +
* '''col[id="2"][name="element22"]''' - запрос отображает все теги ''<col id="2" name="element22" />''
 +
 
 +
* '''(col[id="1"]):last:parent''' - запрос отображает родительский тег ('':parent'') у последнего тега ('':last'')'' <col id="1"''>.
 +
 
 +
 
 +
После того, как вы доберетесь до нужного тега, например ''<col id="1" name="element21" />'' вы можете определить значение каждого атрибута (id, name). Для этого воспользуйтесь свойством компонента "'''Функция'''" и выберите "'''Значения атрибута'''", а в поле "'''Атрибут'''" введите название, например name.
 +
 
 +
Если запрос возвращает несколько тегов, вы можете перебрать каждый в цикле, воспользовавшись полем "'''Номер элемента'''". Количество найденных тегов можно найти с помощью функции "'''Количество элементов'''".
 +
 
 +
Синтаксис языка '''OQuery''' также описан в технической документации: [[Общие_компоненты_сценариев#.D0.9F.D0.B0.D1.80.D1.81.D0.B5.D1.80_.D1.82.D0.B5.D0.BA.D1.81.D1.82.D0.B0 | Парсер]]
 +
 
 +
Пример использования: [[Служебный_сценарий_обработки_контента]]
 +
 
 +
 
 +
[[Файл:Парсер-002.png | center | 700 px]]
 +
 
 +
=== Регулярные выражения ===
 +
 
 +
'''Регулярные выражения''' - формальный язык поиска и осуществления манипуляций с подстроками в тексте, основанный на использовании метасимволов. В Oktell регулярные выражения можно использовать для того, чтобы найти в тексте отдельно стоящее слово или найти все слова после заданного.
 +
 
 +
Тестировать регулярные выражение можно с помощью сервиса [http://www.regexr.com/ http://www.regexr.com/]
 +
 
 +
Регулярные выражения могут применяться, например, в задаче распознавания '''mailer-daemon''' (электронные письма о неудачной доставке). Например, вы делаете рассылку электронных писем, однако некоторые электронные адреса являются не валидными. При попытке отправки на такой адрес, на почту приходит письмо о неудачной доставке. Часть такого письма показана ниже:
 +
 
 +
Delivery to the following recipient failed permanently:
 +
 +
    oktell@mail.ru
 +
 +
Technical details of permanent failure:
 +
Google tried to deliver your message, but it was rejected by the server for the recipient domain mail.ru by mxs.mail.ru. [94.100.176.20].
 +
 
 +
The error that the other server returned was:
 +
550 spam message rejected. Please visit http://help.mail.ru/notspam-support/id?c=8JqX
 +
A-SgNbLWePr06WQuKoX2oyRiVZYKKcj1vWDyM~ or  report details to abuse@corp.mail.ru.
 +
Error code: 03979AF0B235A0E4FFFA78D642964EA76A5FA8E2592546328F9CA260D04BD65B. ID: 0000000B000054D5230F090F.
 +
 
 +
----- Original message -----
 
   
 
   
 <?xml version="1.0" encoding="utf-16"?>
+
X-Received: by 10.194.94.137 with SMTP id dc9mr4910734wjb.38.1380271480979;
<content Version="80903">
+
        Fri, 27 Sep 2013 01:44:40 -0700 (PDT)
  <call commcount="4" taskcount="0">
+
X-Forwarded-To: oktell@mail.ru
    <property_simple key="datetimeformat" value="dd.MM.yyyy HH:mm:ss" />
+
X-Forwarded-For: oktell@gmail.com oktell@mail.ru
    <property_simple key="direction" value="1" name="cdIncoming" />
+
Delivered-To: oktell@gmail.com
    <property_simple key="lineid" value="99c71464-08a9-4a68-8ad7-56ecce407a26" />
+
Received: by 10.216.42.200 with SMTP id j50csp355274web;
    <property_simple key="linenumber" value="13001" />
+
        Fri, 27 Sep 2013 01:44:38 -0700 (PDT)
    <property_simple key="callerid" value="84951234568" />
+
X-Received: by 10.58.100.144 with SMTP id ey16mr5269098veb.25.1380271477282;
    <property_simple key="calledid" value="84995258525" />
+
        Fri, 27 Sep 2013 01:44:37 -0700 (PDT)
    <property_simple key="idchain" value="cec7eb02-2684-423d-9e6c-e20ff1593548" />
+
Return-Path: <576@oktell.ru>
    <property_cdata key="custominfo"><![CDATA[]]></property_cdata>
+
Received: from mail-ve0-f179.google.com (mail-ve0-f179.google.com [209.85.128.179])
    <property_simple key="timestart" value="21.01.2014 11:31:58" />
+
        by mx.google.com with ESMTPS id om2si1573076vec.37.1969.12.31.16.00.00
    <property_simple key="timestop" value="21.01.2014 11:33:36" />
+
        (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128);
    <property_simple key="totalsec" value="97" />
+
        Fri, 27 Sep 2013 01:44:37 -0700 (PDT)
    <property_simple key="emergency" value="0" />
+
Received-SPF: neutral (google.com: 209.85.128.179 is neither permitted nor denied by best guess record
    <property_simple key="callresult" value="busy" />
+
for domain of 576@oktell.ru) client- ip=209.85.128.179;
    <activity>
+
Authentication-Results: mx.google.com;
      <commutation index="0">
+
        spf=neutral (google.com: 209.85.128.179 is neither permitted nor denied by best guess record for domain
        <property_simple key="idconnection" value="13e4b7cb-81c2-4b1a-8578-7be0ce5cf158" />
+
of 576@oktell.ru)  smtp.mail=576@oktell.ru
        <property_simple key="type" value="2" name="IVR" />
+
Received: by mail-ve0-f179.google.com with SMTP id c14so1802657vea.10
        <property_simple key="custominfo" value="" />
+
        for <oktell@gmail.com>; Fri, 27 Sep 2013 01:44:36 -0700 (PDT)
        <property_simple key="timestart" value="21.01.2014 11:31:58" />
+
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
        <property_simple key="timestop" value="21.01.2014 11:32:00" />
+
        <property_simple key="totalsec" value="1" />
+
        <property_simple key="ivrscriptname" value="Маршр вход 1" />
+
      </commutation>
+
      <commutation index="1">
+
        <property_simple key="idconnection" value="b37040d4-1a78-402f-88ee-2b680f778e6e" />
+
        <property_simple key="type" value="1" name="Abonent" />
+
        <property_simple key="custominfo" value="" />
+
        <property_simple key="timestart" value="21.01.2014 11:32:00" />
+
        <property_simple key="timestop" value="21.01.2014 11:32:24" />
+
        <property_simple key="totalsec" value="23" />
+
        <abonents count="1">
+
          <abonent index="1">
+
            <property_simple key="lineid" value="1822df2e-0002-42ba-ae51-d12009611a13" />
+
            <property_simple key="linenumber" value="16e001" />
+
            <property_simple key="callerid" value="" />
+
            <property_simple key="userid" value="6156bdd9-40cf-4aa2-9b90-aa4e9b7a3a23" />
+
            <property_simple key="username" value="admin" />
+
          </abonent>
+
        </abonents>
+
      </commutation>
+
      <commutation index="2">
+
        <property_simple key="idconnection" value="e6c8c115-dd4c-484d-8f5f-3ebeb67906dd" />
+
        <property_simple key="type" value="1" name="Abonent" />
+
        <property_simple key="custominfo" value="" />
+
        <property_simple key="timestart" value="21.01.2014 11:32:29" />
+
        <property_simple key="timestop" value="21.01.2014 11:33:34" />
+
        <property_simple key="totalsec" value="65" />
+
        <abonents count="1">
+
          <abonent index="1">
+
            <property_simple key="lineid" value="18bcab7a-786e-419b-9d51-9293a3969a0b" />
+
            <property_simple key="linenumber" value="17001" />
+
            <property_simple key="callerid" value="" />
+
            <property_simple key="userid" value="db81f69f-7a2b-4b50-bdb8-480d9f2d4045" />
+
            <property_simple key="username" value="Станислав" />
+
          </abonent>
+
        </abonents>
+
      </commutation>
+
    </activity>
+
  </call>
+
</content>
+
  
=== Регулярные выражения ===
+
Ниже показаны примеры регулярных выражений:
 +
 
 +
* '''\S+''' - все целые слова
 +
 
 +
* '''[A-Z][A-Za-z]+''' - все слова, начинающиеся на прописную букву, за которой идет либо прописная либо строчная буква несколько раз.
 +
 
 +
* '''X\-Forwarded\-For\:\s*(\S+(?:[^\r\n]+\S+)*)''' - находит все электронные почты, после ''X-Forwarded-For:'' до переноса строки.
 +
 
 +
* '''(?:[a-zA-Z0-9][a-zA-Z0-9\-\.]*@)?(?:[a-zA-Z0-9][a-zA-Z0-9\-]*\.)+[a-zA-Z]{2,999}'''  - находит все электронные адресы и электронные почты в тексте.
 +
 
 +
Перед группой рекомендуется ставить знак '''?:''' , чтобы возвратить значение в '''Oktell'''
 +
 
 +
Если запрос возвращает несколько значений, перебор возможен с помощью цикла. Количество найденных значений можно найти с помощью функции "'''Количество элементов'''".
 +
 
 +
 
 +
[[Файл:Парсер-003.png | center | 700 px]]
  
  
  
 
=== Парсер JSON ===
 
=== Парсер JSON ===
 +
 +
'''JSON''' - текстовый формат обмена данными, основанный на '''JavaScript''' и обычно используемый именно с этим языком.
 +
 +
Посмотреть структуру '''JSON'''-документа позволяет сервис [http://www.jsoneditoronline.org/ http://www.jsoneditoronline.org/]
 +
 +
Рассмотрим следующий документ:
 +
 +
{
 +
  "info": {
 +
    "list1": {
 +
      "index": 1,
 +
      "name": "matrix",
 +
      "rows": [
 +
        {
 +
          "id": 1,
 +
          "name": "row1",
 +
          "cols": [
 +
            {
 +
              "id": "1",
 +
              "name": "element11"
 +
            },
 +
            {
 +
              "id": "2",
 +
              "name": "element12"
 +
            }
 +
          ]
 +
        },
 +
        {
 +
          "id": 2,
 +
          "name": "row2",
 +
          "cols": [
 +
            {
 +
              "id": "1",
 +
              "name": "element21"
 +
            },
 +
            {
 +
              "id": "2",
 +
              "name": "element22"
 +
            }
 +
          ]
 +
        }
 +
      ]
 +
    }
 +
  }
 +
}
 +
 +
В документе описана матрица 2x2, которая находится на первом листе в ''info''.
 +
 +
'''Oktell''' имеет собственный синтаксис разбора '''JSON'''-объектов. В принципе синтаксис простейший: доступ к значению идет по имени в кавычках, доступ к вложенным объектам — через /, доступ к элементу массива по индексу. В качестве примера, рассмотрим следующие запросы:
 +
 +
* '''"info"/"list1"/"name"''' - получить значение по имени name у объекта ''list1'' в объекте ''info''. Запрос вернет: '''"matrix"'''.
 +
* '''"info"/"list1"/"rows"/1/"name"''' - получить значение по имени name у второго элемента (отсчет элемент начинается с нуля) в массиве ''rows''. Запрос вернет '''"row2"'''.
 +
* '''"info"/"list1"/"rows"/1/"cols"/0/"name"''' - получить значение по имени ''name'' у первого элемента в массиве ''cols'' у второй строки на первом листе. Запрос вернет '''"element21"'''
 +
 +
'''Техническая документация:''' [[Общие_компоненты_сценариев#json | Парсер JSON]]
 +
 +
 +
[[Файл:Парсер-004.png | center | 700 px]]

Текущая версия на 11:19, 31 марта 2023

Наверх

Компонент "Парсер" предназначен для разбора текстовых структур.

  • Для разбора обычного текста применяются регулярные выражения
  • Для разбора гипертекста или XML-структуры применяется парсер OQuery
  • Для разбора JSON-структура применяется парсер JSON

Входным аргументом для парсера является Документ (структура, подлежащая разбору). Документ может быть задан текстом, через переменную или выражение, с помощью функции. Далее, в зависимости от документа, задается алгоритм поиска и поисковый запрос. При необходимости задаются дополнительные параметры: Функция и Номер элемента. Результат разбора документа ("парсинга") сохраняется в переменную (поле "Результат в переменную").

Если с помощью одного парсера невозможно определить искомое выражение, необходимо использовать последовательность из таких компонентов. Каждый следующий парсер получает на вход результат от предыдущего компонента. Таким образом, возможен сколь угодно глубокий поиск нужной информации.

В этой статье подробно рассматривается применение каждого алгоритма и примеры использования парсера.


Парсер-001.png


Язык OQuery для HTML

Язык OQuery применяется для разбора гипертекста или XML-структуры.

Для тестирования запросов применяется программа OQuery-tester.exe.

Рассмотрим следующую XML-структуру:

<?xml version="1.0" encoding="utf-16"?>
<info>
	<list index="1" name="matrix33"> 
		<row id="1" name="aaa">
			<col id="1" name="r1c1" />
			<col id="2" name="r1c2" />
			<col id="3" name="r1c3" />
		</row>
		<row id="2" name="bbb">
			<col id="1" name="r2c1" />
			<col id="2" name="r2c2" />
			<col id="3" name="r2c3" />
	</row>
		<row id="3" name="ccc">
			<col id="1" name="r3c1" />
			<col id="2" name="r3c2" />
			<col id="3" name="r3c3" />
		</row>
	</list>
	<list index="2" name="matrix22">
		<row id="1" name="ddd">
			<col id="1" name="element11" />
			<col id="2" name="element12" />
		</row>
		<row id="2" name="eee">
			<col id="1" name="element21" />
			<col id="2" name="element22" />
		</row>
	</list>
	<list index="3" name="matrixnull">
        </list>
</info>

XML-структура представляет из себя два листа, на первом листе матрица 3x3, на другом матрица 2x2. Ниже приведены запросы как можно добраться до каждого компонента в представленной структуре.


  • info - запрос отображает все теги <info> и их содержимое.
  • list - запрос отображает все теги <list> и их содержимое. В примере, информация по двум листам.
  • list[index="2"] - запрос отображает все теги <list index="2"> (у которых атрибут index=2) и их содержимое. В примере, вся информация во втором листе.
  • col[id="2"] - запрос отображает все теги <col id="2"> (у которых атрибут id="2"). В примере, все элементы во втором столбце в обеих матрицах.
  • list[index="2"] col[id="2"] - запрос отображает все теги <col id="2">, которые находятся в <list index="2">. В примере, это все элементы во втором столбце, которые находятся на втором листе.
  • col[id="2"][name="element22"] - запрос отображает все теги <col id="2" name="element22" />
  • (col[id="1"]):last:parent - запрос отображает родительский тег (:parent) у последнего тега (:last) <col id="1">.


После того, как вы доберетесь до нужного тега, например <col id="1" name="element21" /> вы можете определить значение каждого атрибута (id, name). Для этого воспользуйтесь свойством компонента "Функция" и выберите "Значения атрибута", а в поле "Атрибут" введите название, например name.

Если запрос возвращает несколько тегов, вы можете перебрать каждый в цикле, воспользовавшись полем "Номер элемента". Количество найденных тегов можно найти с помощью функции "Количество элементов".

Синтаксис языка OQuery также описан в технической документации: Парсер

Пример использования: Служебный_сценарий_обработки_контента


Парсер-002.png

Регулярные выражения

Регулярные выражения - формальный язык поиска и осуществления манипуляций с подстроками в тексте, основанный на использовании метасимволов. В Oktell регулярные выражения можно использовать для того, чтобы найти в тексте отдельно стоящее слово или найти все слова после заданного.

Тестировать регулярные выражение можно с помощью сервиса http://www.regexr.com/

Регулярные выражения могут применяться, например, в задаче распознавания mailer-daemon (электронные письма о неудачной доставке). Например, вы делаете рассылку электронных писем, однако некоторые электронные адреса являются не валидными. При попытке отправки на такой адрес, на почту приходит письмо о неудачной доставке. Часть такого письма показана ниже:

Delivery to the following recipient failed permanently:

    oktell@mail.ru

Technical details of permanent failure:
Google tried to deliver your message, but it was rejected by the server for the recipient domain mail.ru by mxs.mail.ru. [94.100.176.20].
  
The error that the other server returned was:
550 spam message rejected. Please visit http://help.mail.ru/notspam-support/id?c=8JqX
A-SgNbLWePr06WQuKoX2oyRiVZYKKcj1vWDyM~ or   report details to abuse@corp.mail.ru. 
Error code: 03979AF0B235A0E4FFFA78D642964EA76A5FA8E2592546328F9CA260D04BD65B. ID: 0000000B000054D5230F090F.
 
----- Original message -----

X-Received: by 10.194.94.137 with SMTP id dc9mr4910734wjb.38.1380271480979;
        Fri, 27 Sep 2013 01:44:40 -0700 (PDT)
X-Forwarded-To: oktell@mail.ru
X-Forwarded-For: oktell@gmail.com oktell@mail.ru
Delivered-To: oktell@gmail.com
Received: by 10.216.42.200 with SMTP id j50csp355274web;
        Fri, 27 Sep 2013 01:44:38 -0700 (PDT)
X-Received: by 10.58.100.144 with SMTP id ey16mr5269098veb.25.1380271477282;
        Fri, 27 Sep 2013 01:44:37 -0700 (PDT)
Return-Path: <576@oktell.ru>
Received: from mail-ve0-f179.google.com (mail-ve0-f179.google.com [209.85.128.179])
        by mx.google.com with ESMTPS id om2si1573076vec.37.1969.12.31.16.00.00
        (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128);
        Fri, 27 Sep 2013 01:44:37 -0700 (PDT)
Received-SPF: neutral (google.com: 209.85.128.179 is neither permitted nor denied by best guess record 
for domain of 576@oktell.ru) client- ip=209.85.128.179;
Authentication-Results: mx.google.com;
       spf=neutral (google.com: 209.85.128.179 is neither permitted nor denied by best guess record for domain 
of 576@oktell.ru)  smtp.mail=576@oktell.ru
Received: by mail-ve0-f179.google.com with SMTP id c14so1802657vea.10
        for <oktell@gmail.com>; Fri, 27 Sep 2013 01:44:36 -0700 (PDT)
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;

Ниже показаны примеры регулярных выражений:

  • \S+ - все целые слова
  • [A-Z][A-Za-z]+ - все слова, начинающиеся на прописную букву, за которой идет либо прописная либо строчная буква несколько раз.
  • X\-Forwarded\-For\:\s*(\S+(?:[^\r\n]+\S+)*) - находит все электронные почты, после X-Forwarded-For: до переноса строки.
  • (?:[a-zA-Z0-9][a-zA-Z0-9\-\.]*@)?(?:[a-zA-Z0-9][a-zA-Z0-9\-]*\.)+[a-zA-Z]{2,999} - находит все электронные адресы и электронные почты в тексте.

Перед группой рекомендуется ставить знак ?: , чтобы возвратить значение в Oktell

Если запрос возвращает несколько значений, перебор возможен с помощью цикла. Количество найденных значений можно найти с помощью функции "Количество элементов".


Парсер-003.png


Парсер JSON

JSON - текстовый формат обмена данными, основанный на JavaScript и обычно используемый именно с этим языком.

Посмотреть структуру JSON-документа позволяет сервис http://www.jsoneditoronline.org/

Рассмотрим следующий документ:

{
  "info": {
    "list1": {
      "index": 1,
      "name": "matrix",
      "rows": [
        {
          "id": 1,
          "name": "row1",
          "cols": [
            {
              "id": "1",
              "name": "element11"
            },
            {
              "id": "2",
              "name": "element12"
            }
          ]
        },
        {
          "id": 2,
          "name": "row2",
          "cols": [
            {
              "id": "1",
              "name": "element21"
            },
            {
              "id": "2",
              "name": "element22"
            }
          ]
        }
      ]
    }
  }
}

В документе описана матрица 2x2, которая находится на первом листе в info.

Oktell имеет собственный синтаксис разбора JSON-объектов. В принципе синтаксис простейший: доступ к значению идет по имени в кавычках, доступ к вложенным объектам — через /, доступ к элементу массива по индексу. В качестве примера, рассмотрим следующие запросы:

  • "info"/"list1"/"name" - получить значение по имени name у объекта list1 в объекте info. Запрос вернет: "matrix".
  • "info"/"list1"/"rows"/1/"name" - получить значение по имени name у второго элемента (отсчет элемент начинается с нуля) в массиве rows. Запрос вернет "row2".
  • "info"/"list1"/"rows"/1/"cols"/0/"name" - получить значение по имени name у первого элемента в массиве cols у второй строки на первом листе. Запрос вернет "element21"

Техническая документация: Парсер JSON


Парсер-004.png