Извлечение информации из вики-страниц с учётом их структуры
представляется непростой задачей. Зачастую язык вики-разметки (WML) не
имеет формального описания. Часто WML развивается путем добавления новых
фич без стадии перепроектирования с большим грузом обратной
совместимости. В итоге обычно описание WML сводится к набору примеров из
документации и в "окончательном виде" язык определен в коде парсера
вики-движка. При этом внутри вики движка разбор проводится не на основе
грамматических правил, как это делается, для большинства языков
программирования и языков разметки, таких, как XML, а на основе поиска
по шаблону. Найденные шаблоны превращаются в кусочки HTML-разметки,
которые в итоге формируют вики-страницу в браузере пользователя. Это
делает структурированный разбор вики-страниц трудной задачей. Тем
не менее для разбора вики-страниц существуют готовые решения, и к
счастью обычно не требуется прибегать к велосипедостроению. Об эдном из
решений - парсере Sweble.org я и хочу рассказать в этом посте.
Некоторое время назад я делал "химичесикй поиск" по википедии, сервис, который позволяет искать статьи о химических веществах как по тексту, так и по структурной формуле. Для этого я скачивал дамп википедии, извлекал статьи про химические вещества и индексировал их с помощью поискового движка Lucene. Первая (и на данный момент единственная) версия поиска не делала какой-то особой обработки страниц, требовалось просто извлечь текст самой статьи, отделив его от разметки. Перед этим название статьи и структурная формула вещества извлекалась с помощью регулярного выражения perl-скриптом. Немного поискав в инетрнете, я нашёл несколько парсеров вики-разметки, при этом как-то случайно само собой получилось, что быстрее всего пошли дела с парсером Sweble.org. Теоретическую вводную в работу парсера Sweble.org можно получить в статье авторов (pdf).
Как и многие другие парсеры Sweble.org строит дерево разбора страницы. Это дерево в терминах Sweble.org называется WOM, или "Wiki Object Model". Парсер написан на Java и работать с ним проще всего из Java. Документация почти отсутствует, но имеются примеры, которые сильно помогают.
Итак, как же работать с разобранным деревом? Разобранная вики-статья представляется в виде дерева, узлы которого -- объекты реализующие интерфейс WtNode. Эти объекты принадлежат унаследованным интерфейсам и классам WtNodeList (интерфейс), WtUnorderedList, WtOrderedList, WtListItem, EngPage, EngProcessedPage, WtText, WtWhitespace, WtBold, WtXmlCharRef, WtXmlEntityRef, WtUrl, WtExternalLink, WtInternalLink, WtSection, WtParagraph, WtHorizontalRule, WtXmlElement и другим.
Обход дерева реализуется в соответствии с шаблоном проектирования посетитель (Visitor).
Для анлиза дерева разбора я написал небольшую утилитку, которая разбирает вики-статью с помощью Sweble.org и выводит дерево в текстовом формате. Например, для статьи Manzanate
{{Orphan|date=April 2011}}
{{chembox
| verifiedrevid = 425210668
| Name =Ethyl 2-methylpentanoate
| Reference =
| ImageFile = Manzanate.png
| ImageSize = 200px
| ImageName =
| IUPACName = Ethyl 2-methylpentanoate
| OtherNames = Ethyl α-methylvalerate; Melon valerate
| Section1 = {{Chembox Identifiers
| CASNo_Ref = {{cascite|correct|??}}
| CASNo = 39255-32-8
| SMILES = CCCC(C)C(=O)OCC
}}
| Section2 = {{Chembox Properties
| Formula = C8H16O2
| MolarMass = 144.21 g/mol
| Density =
| MeltingPt =
| BoilingPt =
}}
}}
'''Manzanate''' is a [[flavor]] ingredient which has a fruity apple smell and with aspects of cider and sweet pineapple.[http://www.thegoodscentscompany.com/data/rw1006801.html Melon valerate]
==References==
{{reflist}}
[[Category:Carboxylate esters]]
{{ester-stub}}
будет сгенерирован примерно такой вывод
[WtListItem]
[WtParagraph]
[WtTemplate]
[WtNodeList]
[WtText] Orphan
[WtNodeList]
[WtTemplateArgument]
[WtNodeList]
[WtText] date
[WtNodeList]
[WtText] April 2011
[WtText]
[WtParagraph]
[WtTemplate]
[WtNodeList]
[WtText] chembox
[WtNodeList]
[WtTemplateArgument]
[WtNodeList]
[WtText] verifiedrevid
[WtNodeList]
[WtText] 425210668
[WtTemplateArgument]
[WtNodeList]
[WtText] Name
[WtNodeList]
[WtText] Ethyl 2-methylpentanoate
...поскипано
[WtParagraph]
[WtBold]
[WtText] Manzanate
[WtText] is a
[WtInternalLink]
[WtText] flavor
[WtText] ingredient which has a fruity apple smell and with aspects of cider and sweet pineapple.
[WtTagExtension]
[WtText]
[WtSection]
--heading--
[WtText] References
--body--
[WtText]
[WtParagraph]
[WtTemplate]
[WtNodeList]
[WtText] reflist
[WtNodeList]
[WtText]
[WtParagraph]
[WtInternalLink]
[WtText]
[WtParagraph]
[WtText]
[WtTemplate]
[WtNodeList]
[WtText] ester-stub
[WtNodeList]
[WtText]
На первом этапе мне нужно было просто очистить статью от вики-разметки, оставивь только текст. Эта задача решена в примерах, поставляемых вместе с парсером Sweble.
Общий подход таков: сначала строим WOM-дерево как-то так:
Напомню, что класс EngProcessedPage реализует интерфейс WtNode и, как видно из примера, представлят собой корневой узел WOM-дерева. Для того, чтобы обойти дерево произведя какие-либо полезные действия нужно создать класс, унаследованный от de.fau.cs.osr.ptk.common.AstVisitor и переопределить методы before, after и семейство методов visit В случае очистки от разметки можно взять из примеров проекта уже готовый класс org.sweble.wikitext.example.TextConverter.
Эту магию я планирую применить для извлечения и индексирования различных свойств химических веществ. Статьи, которые индексирует мой "химический поисковик" содержат специальный infobox (chembox, drugbox или ionbox, см. пример выше). В настоящий момент из этого инфобокса с помощью регулярного выражение извлекается только лишь структурная формула в формате SMILES. Использование парсера Sweble.org облегчит эту задачу и позволит единообразно извлечь множество других свойств вещества.
Некоторое время назад я делал "химичесикй поиск" по википедии, сервис, который позволяет искать статьи о химических веществах как по тексту, так и по структурной формуле. Для этого я скачивал дамп википедии, извлекал статьи про химические вещества и индексировал их с помощью поискового движка Lucene. Первая (и на данный момент единственная) версия поиска не делала какой-то особой обработки страниц, требовалось просто извлечь текст самой статьи, отделив его от разметки. Перед этим название статьи и структурная формула вещества извлекалась с помощью регулярного выражения perl-скриптом. Немного поискав в инетрнете, я нашёл несколько парсеров вики-разметки, при этом как-то случайно само собой получилось, что быстрее всего пошли дела с парсером Sweble.org. Теоретическую вводную в работу парсера Sweble.org можно получить в статье авторов (pdf).
Как и многие другие парсеры Sweble.org строит дерево разбора страницы. Это дерево в терминах Sweble.org называется WOM, или "Wiki Object Model". Парсер написан на Java и работать с ним проще всего из Java. Документация почти отсутствует, но имеются примеры, которые сильно помогают.
Итак, как же работать с разобранным деревом? Разобранная вики-статья представляется в виде дерева, узлы которого -- объекты реализующие интерфейс WtNode. Эти объекты принадлежат унаследованным интерфейсам и классам WtNodeList (интерфейс), WtUnorderedList, WtOrderedList, WtListItem, EngPage, EngProcessedPage, WtText, WtWhitespace, WtBold, WtXmlCharRef, WtXmlEntityRef, WtUrl, WtExternalLink, WtInternalLink, WtSection, WtParagraph, WtHorizontalRule, WtXmlElement и другим.
Обход дерева реализуется в соответствии с шаблоном проектирования посетитель (Visitor).
Для анлиза дерева разбора я написал небольшую утилитку, которая разбирает вики-статью с помощью Sweble.org и выводит дерево в текстовом формате. Например, для статьи Manzanate
{{Orphan|date=April 2011}}
{{chembox
| verifiedrevid = 425210668
| Name =Ethyl 2-methylpentanoate
| Reference =
| ImageFile = Manzanate.png
| ImageSize = 200px
| ImageName =
| IUPACName = Ethyl 2-methylpentanoate
| OtherNames = Ethyl α-methylvalerate; Melon valerate
| Section1 = {{Chembox Identifiers
| CASNo_Ref = {{cascite|correct|??}}
| CASNo = 39255-32-8
| SMILES = CCCC(C)C(=O)OCC
}}
| Section2 = {{Chembox Properties
| Formula = C8H16O2
| MolarMass = 144.21 g/mol
| Density =
| MeltingPt =
| BoilingPt =
}}
}}
'''Manzanate''' is a [[flavor]] ingredient which has a fruity apple smell and with aspects of cider and sweet pineapple.[http://www.thegoodscentscompany.com/data/rw1006801.html Melon valerate]
==References==
{{reflist}}
[[Category:Carboxylate esters]]
{{ester-stub}}
будет сгенерирован примерно такой вывод
[WtListItem]
[WtParagraph]
[WtTemplate]
[WtNodeList]
[WtText] Orphan
[WtNodeList]
[WtTemplateArgument]
[WtNodeList]
[WtText] date
[WtNodeList]
[WtText] April 2011
[WtText]
[WtParagraph]
[WtTemplate]
[WtNodeList]
[WtText] chembox
[WtNodeList]
[WtTemplateArgument]
[WtNodeList]
[WtText] verifiedrevid
[WtNodeList]
[WtText] 425210668
[WtTemplateArgument]
[WtNodeList]
[WtText] Name
[WtNodeList]
[WtText] Ethyl 2-methylpentanoate
...поскипано
[WtParagraph]
[WtBold]
[WtText] Manzanate
[WtText] is a
[WtInternalLink]
[WtText] flavor
[WtText] ingredient which has a fruity apple smell and with aspects of cider and sweet pineapple.
[WtTagExtension]
[WtText]
[WtSection]
--heading--
[WtText] References
--body--
[WtText]
[WtParagraph]
[WtTemplate]
[WtNodeList]
[WtText] reflist
[WtNodeList]
[WtText]
[WtParagraph]
[WtInternalLink]
[WtText]
[WtParagraph]
[WtText]
[WtTemplate]
[WtNodeList]
[WtText] ester-stub
[WtNodeList]
[WtText]
На первом этапе мне нужно было просто очистить статью от вики-разметки, оставивь только текст. Эта задача решена в примерах, поставляемых вместе с парсером Sweble.
Общий подход таков: сначала строим WOM-дерево как-то так:
import org.sweble.wikitext.engine.EngineException; import org.sweble.wikitext.engine.PageId; import org.sweble.wikitext.engine.PageTitle; import org.sweble.wikitext.engine.WtEngineImpl; import org.sweble.wikitext.engine.config.WikiConfig; import org.sweble.wikitext.engine.nodes.EngProcessedPage; ... //Установим простую конфигурацию по-умолчанию WikiConfig config = DefaultConfigEnWp.generate(); //Тайтл меня особо не волнует. Сгенерируем что-нибудь на основе пути к данным в файловой системе PageTitle pageTitle = PageTitle.make(config, pathStr); PageId pageId = new PageId(pageTitle, -1); //Скомипилируем (читай, распарсим) страницу. EngProcessedPage cp = engine.postprocess(pageId, wikitext, null);
Напомню, что класс EngProcessedPage реализует интерфейс WtNode и, как видно из примера, представлят собой корневой узел WOM-дерева. Для того, чтобы обойти дерево произведя какие-либо полезные действия нужно создать класс, унаследованный от de.fau.cs.osr.ptk.common.AstVisitor и переопределить методы before, after и семейство методов visit В случае очистки от разметки можно взять из примеров проекта уже готовый класс org.sweble.wikitext.example.TextConverter.
Эту магию я планирую применить для извлечения и индексирования различных свойств химических веществ. Статьи, которые индексирует мой "химический поисковик" содержат специальный infobox (chembox, drugbox или ionbox, см. пример выше). В настоящий момент из этого инфобокса с помощью регулярного выражение извлекается только лишь структурная формула в формате SMILES. Использование парсера Sweble.org облегчит эту задачу и позволит единообразно извлечь множество других свойств вещества.
Комментариев нет:
Отправить комментарий