Использование регулярных выражений для анализа HTML вызывает проблемы, за исключением самых тривиальных, контролируемых обстоятельств. Синтаксический анализатор является более надежным и, в конечном счете, обычно намного проще в обслуживании.
HTML-код недействителен, поскольку теги <block>
не завершены. Это приводит к неоднозначному синтаксическому анализу с использованием Nokogiri, но мы можем сыграть на нем небольшую хитрость, чтобы исправить ситуацию, и затем иметь возможность правильно ее проанализировать:
html =<<EOT
<block color="green">
This is the text I need and
it may also <p> have other </p>
tags in it, and all sorts of
things...
<block color="blue">
This is the text I need and
it may also <p> have other </p>
tags in it, and all sorts of
things...
<block color="green">
This is the text I need and
it may also <p> have other </p>
tags in it, and all sorts of
things...
<block color="green">
This is the text I need and
it may also <p> have other </p>
tags in it, and all sorts of
things...
EOT
require 'nokogiri'
require 'pp'
doc = Nokogiri::HTML(html.gsub('<block', '</block><block'))
pp doc.search('block').map { |n| n.text }
>> ["\n This is the text I need and\n it may also have other \n tags in it, and all sorts of \n things...\n",
>> "\n This is the text I need and\n it may also have other \n tags in it, and all sorts of \n things...\n",
>> "\n This is the text I need and\n it may also have other \n tags in it, and all sorts of \n things... \n",
>> "\n This is the text I need and\n it may also have other \n tags in it, and all sorts of \n things...\n"]
Путем поиска и замены закрывающих </block>
можно вставить перед всеми <block>
тегами. Это приводит к тому, что первое вхождение ошибочно, но все остальные достаточно близки, чтобы исправление Нокогири HTML было разумным. Вот как выглядит HTML после исправления:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body>
<block color="green">
This is the text I need and
it may also <p> have other </p>
tags in it, and all sorts of
things...
</block><block color="blue">
This is the text I need and
it may also <p> have other </p>
tags in it, and all sorts of
things...
</block><block color="green">
This is the text I need and
it may also <p> have other </p>
tags in it, and all sorts of
things...
</block><block color="green">
This is the text I need and
it may also <p> have other </p>
tags in it, and all sorts of
things...
</block>
</body></html>
В этот момент Нокогири может разобраться в документе и найти отдельные блоки. Я использую аксессор CSS, поэтому, если вам нужна лучшая детализация, вы можете настроить CSS или переключиться на XPath.