Regex - Найти содержимое div по id с помощью вложенных div - PullRequest
8 голосов
/ 13 ноября 2008

Прежде чем кто-либо спросит, я не делаю никаких скраппингов.

Я пытаюсь разобрать строку html, чтобы найти div с определенным идентификатором. Я не могу на всю жизнь заставить это работать. Следующее выражение сработало в одном случае, но не в другом. Я не уверен, имеет ли это отношение к дополнительным элементам в HTML или нет.

<div\s*?id=(\""|&quot;|&#34;)content(\""|&quot;|&#34;).*?>\s*?(?>(?! <div\s*?> | </div> ) | <div\s*?>(?<DEPTH>) | </div>(?<-DEPTH>) | .?)*(?(DEPTH)(?!))</div>

Он правильно находит первый div с правильным идентификатором, но затем закрывается в первом закрывающем div, а не в соответствующем div.

<div id="firstdiv">begining content<div id="content">some other stuff
    <div id="otherdiv">other stuff here</div>
    more stuff
    </div>
</div>

Это должно вернуть

<div id="content">some other stuff
   <div id="otherdiv">other stuff here</div>
   more stuff
</div>

, но по какой-то причине это не так. Возвращаем:

   <div id="content">some other stuff
      <div id="otherdiv">other stuff here</div>

У кого-нибудь есть более простое выражение, чтобы справиться с этим?

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

Ответы [ 4 ]

5 голосов
/ 13 ноября 2008

В .NET вы можете сделать это:

(?<text>
(<div\s*?id=(\"|&quot;|&\#34;)content(\"|&quot;|&\#34;).*?>)

  (?>
      .*?</div>
    |
      .*?<div (?>depth)
    |
      .*?</div> (?>-depth)
  )*)
  (?(depth)(?!))
.*?</div>

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

using System;
using System.Text.RegularExpressions;

namespace Temp
{
    class Program
    {
        static void Main()
        {
            string s = @"
<div id=""firstdiv"">begining content<div id=""content"">some other stuff
  <div id=""otherdiv"">other stuff here</div>
  more stuff
  </div>
</div>";
            Regex r = new Regex(@"(?<text>(<div\s*?id=(\""|&quot;|&\#34;)"
                + @"content(\""|&quot;|&\#34;).*?>)(?>.*?</div>|.*?<div "
                + @"(?>depth)|.*?</div> (?>-depth))*)(?(depth)(?!)).*?</div>",
                RegexOptions.Singleline);
            Console.WriteLine("HTML:\n");
            Console.WriteLine(s);
            Match m = r.Match(s);
            if (m.Success)
            {
                Console.WriteLine("\nCaptured text:\n");
                Console.WriteLine(m.Groups[4]);

            }
            Console.ReadLine();
        }
    }
}
5 голосов
/ 13 ноября 2008

Вы запрашиваете регулярное выражение, которое может отслеживать количество тегов DIV, вложенных в тег DIV? Боюсь, что это невозможно с регулярными выражениями.

Вы можете использовать регулярное выражение для получения индекса первого тега DIV, а затем циклически перебирать символы в строке, начиная с этого индекса и вести подсчет количества открытых тегов div. Когда вы сталкиваетесь с близким тегом div и счетчик равен нулю, у вас есть начальный и конечный индексы в строке, которая содержит нужную подстроку.

2 голосов
/ 13 ноября 2008

Кибис говорит правду. Такого рода вещи относятся к контекстно-свободным языкам, которые являются более мощными, чем обычные языки (виды вещей, охватываемые регулярными выражениями). В это вовлечено много теорий информатики, но позвольте себе сказать, что на любом языке, заслуживающем его внимания, будет библиотека для такого рода написанных вещей, которые вы, вероятно, должны использовать.

0 голосов
/ 13 ноября 2008

Какой язык программирования? Если это .Net, и вы уверены, что html правильно сформирован, вы можете загрузить его в объект XmlDocument или XDocument и выполнить запрос xpath.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...