Регулярное выражение для поиска в html

0

Я пытаюсь написать правильное регулярное выражение для поиска значения в html, но есть некоторые проблемы.

Есть кусок html:

<div class="inner">
<div class="title">Processing 3-D Secure Transaction</div>
<form autocomplete="off" name="PAResForm" id="PAResForm" action="https://www.alfaportal.ru/" method="POST">
<input name="MD" type="hidden" value="4326381105C3B67B2823E71FD235FFD2"><input value="eJzVWFmvo0iy/iulnkerm9UYt1xdQtJ2pkQdOVw5AW2qGv+is66Q
qrz9LBZ3mCe7mJzYARdloC1dJ/Lk+nQ7KBxxdgtIEgy/Tp/I93MZ5NtZzfdTnPdj5vfz7tex6I/n
4P8DRkGf4Q==" name="PaRes" type="hidden"> 

Я пытаюсь искать строку

<input name="MD" type="hidden" value="4326381105C3B67B2823E71FD235FFD2">

и получить ценность

Проблема в значении, и имя может заменить друг друга. Например

<input value="4326381105C3B67B2823E71FD235FFD2" type="hidden" name="MD">

Я написал шаблон регулярного выражения:

<input.*name=\"MD\"|value=\"([^<>]*?)\"[^<>]*value=\"([^<>]*?)\"|name=\"MD\".*?>

он работает в некоторых онлайн-сервисах регулярных выражений, но не работает в реальной Java.

Помогите, пожалуйста, изменить его правильно.

Также я написал простой инструмент командной строки для его тестирования. http://pastebin.com/Pzynqrn8

  • 0
    Вы уверены, что вам действительно нужно использовать regxp для ваших задач? может быть, вы можете использовать какой-нибудь инструмент?
  • 1
    Этот ответ может помочь вам решить не использовать регулярные выражения ... stackoverflow.com/questions/1732348/…
Теги:

7 ответов

-1
Лучший ответ

Наконец, я решил это, добавив еще один шаблон. Сначала я ищу строку типа <input... name='MD'.../> по шаблону ".*?(<input[^<>]*name=\\\"MD\\\"[^<>]*>).*?" и после этого я ищу значение в строке результата с шаблоном ".*?value=\\\"(.*?)\\\""

Спасибо всем за помощь

  • 2
    А теперь представьте, что на сайт добавлено несколько трюков html5, и у элемента теперь есть новый атрибут ... <input name='MD' data-js-process-this-value="true" value="4326381105C3B67B2823E71FD235FFD2" type="hidden"/> ... Теперь ваше регулярное выражение может извлечь" true "вместо желаемого значения. Также обратите внимание, что сайт может изменить кавычки с " двойных кавычек ' одинарные кавычки. Ваше регулярное выражение этого не ожидает.
  • 1
    Если вы действительно хотите регулярное выражение, вставьте \s перед именами атрибутов, и поймайте использованные кавычки, а затем сделайте обратную ссылку на них при закрытии. Создайте ежедневную работу, которая проверяет сайт на соответствие вашему регулярному выражению и уведомляет вас, когда сайт был изменен. Потому что это будет в какой-то момент.
2

Существует множество инструментов для разбора HTML. Я думаю, вы не должны игнорировать их. Это обсуждалось здесь.

  • 1
    Совершенно нормально использовать регулярные выражения для анализа известного подмножества HTML. Здесь действительно нет необходимости в полноценном парсере.
  • 1
    Я так и думал некоторое время. Узнал, что это не очень хорошая идея трудным путем. Не анализируйте html, который находится вне вашего контроля, с помощью регулярных выражений, так как незначительные изменения могут легко сделать их недействительными, когда анализ DOM все же удастся сделать.
2

Я не знаю, как это сделать на Java, но я настоятельно рекомендую использовать соответствующие инструменты Document Object Model и т.д.

В PHP я бы сделал это:

$xml = new DomDocument();
$xml->loadXml($yourHTMLHere);
$xpath = new DOMXPath($xml);
$node = $xpath
    ->evaluate('//form[@name="PAResForm"]//input[@name="MD"]')
    ->item(0);
$yourValueIsHere = $node->getAttribute('value');

5 строк, полностью читаемых и не заботятся о порядке атрибутов. Java может сделать то же самое точно, просто найдите подходящие классы.

И не анализируйте нерегулярный язык с помощью выражений. Html не является обычным языком.

2

Я думаю попробовать что-то вроде этого:

<input\s*?(value=['"].*?['"]\s*)|(type=['"].*?["']\s*)|(name=['"].*?['"]\s*)\>
1

Как всегда, всегда, всегда, когда приходится обращаться с HTML: используйте синтаксический анализатор. Regex не справляется с задачей, по техническим причинам, объясненной смертью в известной должности.

Java имеет jSoup, и смущающе легко создать небольшую, простую и удобную часть кода, которая делает именно то, что вам нужно.

Document doc = Jsoup.parse(str);
Element input = doc.select("input[name='MD']").first();

if (input != null) {
    String value = input.attr("value");
    // now do something with it
}

Теперь сравните этот трехстрочный слой со всеми этими волосатыми регулярными выражениями, подумайте о том, насколько они доступны и небезопасны, сколько объяснений они требуют и как вы можете полностью переписать их с нуля, когда HTML изменяется. Подсчитайте, когда вы пытались найти решение для себя и решаете, стоит ли регулярное выражение, когда дело касается HTML.

1

Я бы использовал lookahead в подобном шаблоне:

<input(?=[^>]+?name="MD")[^>]+?value="([A-Z0-9]+)"

Вы в основном говорите, что ищете элемент <input> с name MD. Это выглядит: (?=[^>]+?name="MD")), который не потребляет никаких символов, но гарантирует, что ваш атрибут name присутствует. Затем вы просто сопоставляете значение value в первой группе захвата: ([A-Z0-9]+).

Возможно, было бы полезно написать шаблон в режиме свободного интервала:

<input               # opening input tag
(?=[^>]+?name="MD")  # lookahead looking for the presence of the name attribute
[^>]+?               # anything (whitespace, other attributes) up to ...
value="([A-Z0-9]+)"  # the value attribute and its value

[Обновить] Обратите внимание, что почти всегда лучше использовать правильные синтаксические анализаторы HTML для анализа HTML - что они подходят. В этом случае использование регулярных выражений на мой взгляд прекрасное. Просто имейте в виду следующего парня, который должен будет поддерживать ваш код и принимать ответственное решение.

0

Пока ваш элемент имеет эти атрибуты, это не сложно:

    public static void main(String[] args) {
        Pattern p = Pattern.compile("<input(?:\\s+|name=\"MD\"|type=\"hidden\"|value=\"([^\"]+)\")+");
        Matcher m = p.matcher("<input name=\"MD\" type=\"hidden\" value=\"4326381105C3B67B2823E71FD235FFD2\">");
        if (m.find()) {
            System.out.println(m.group(1));
        }
    }

Ещё вопросы

Сообщество Overcoder
Наверх
Меню