@antoart
Web developer

Как пропарсить HTML теги, а также скобки и подобное?

Добрый день!

Как можно пропарсить HTML теги, принимая в расчет, что к каждому открытому тегу соответствует закрытый?

Это была задача.
Дан HTML файл, необходимо в этом файле найти все строки соответствующие заданному тегу.
Строчки в теге могут содержать вложенные теги.
Например, искомый тег
на входе
<span xml:lang="en" lang="en">Текст текст <b><span>Имя Фамилия</span></b></span>


на выходе
<span xml:lang="en" lang="en">Текст текст <b><span>Имя Фамилия</span></b></span>
<span>Имя Фамилия</span>


Я понимаю, что есть раззличные парсеры и библиотеки, но хотелось бы самому понять как это работает. Какие есть алгоритмы и как работают.

У меня есть мое решение. Оно рабочее, но чувствую, что можно сделать лучше и аккуратней.

public static void main(String[] args) throws Exception {

        String tagName = args[0]; // входящий тэг
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String filename = reader.readLine();
        reader.close();
        StringBuilder sb = new StringBuilder();

        //считал из файла все строки и перевел в одну строку
        BufferedReader br = new BufferedReader(new FileReader(filename));
        String data = br.readLine();
        while (data != null) {
            sb.append(data);
            data = br.readLine();
        }
        br.close();
        String fileData = sb.toString(); // итоговая строка для поиска в ней

        int n = fileData.indexOf(tagName);
        int flag = 0;
        ArrayList<Integer> forIndex = new ArrayList<>();
        while (n != -1) { //если нет тегов, то indexOf return -1
            String tag = fileData.substring(n-1, n + tagName.length());
            if (("<" + tagName).equals(tag)) { //если нашли открывающий тэг
                flag++;
                forIndex.add(n - 1);
            }
            else if (("/" + tagName).equals(tag)) { //если нашли закрывающий тэг
                flag--;
                forIndex.add(n + tagName.length() + 1);
            }
            if (flag == 0) { // когда закрыли открытый тэг
                while (forIndex.size() > 0) { //из списка индексов собрали индексы "по краям и вглубь"
                    int start = forIndex.remove(0);
                    int end = forIndex.remove(forIndex.size() - 1);
                    System.out.println(fileData.substring(start, end));
                }
            }
            n = fileData.indexOf(tagName, n + tagName.length());
        }
    }


Прошу вашей помощи в данном вопросе.
P.S. мне думается, что данные методики можно применять и при парсинге различных скобок, других тегов (XML) и подобном. Полезные знания могли бы получиться.
  • Вопрос задан
  • 415 просмотров
Пригласить эксперта
Ответы на вопрос 3
@balamut108
Py
Попробуйте воспользоваться средством, которое специально разрабатывалось для этой задачи: wiki.python.su/%D0%94%D0%BE%D0%BA%D1%83%D0%BC%D0%B...

Это не Java, но Python будет в разы проще.
Ответ написан
@mik222
xml/html давно парсится чем только не лень, в Go он вообще, в stdlib.
самое известное для питона: lxml.de
Beautiful soup не советую, он старый и забытый.
Если хочется чистенько и самому, гуглите packrat парсеры и ABNF мета грамматику.
Симпатишно и быстро тут: https://github.com/Engelberg/instaparse
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы