Я пытаюсь сопоставить <input>
«скрытые» поля типа, используя этот шаблон:
/<input type="hidden" name="([^"]*?)" value="([^"]*?)" />/
Это пример данных формы:
<input type="hidden" name="SaveRequired" value="False" /><input type="hidden" name="__VIEWSTATE1" value="1H4sIAAtzrkX7QfL5VEGj6nGi+nP" /><input type="hidden" name="__VIEWSTATE2" value="0351118MK" /><input type="hidden" name="__VIEWSTATE3" value="ZVVV91yjY" /><input type="hidden" name="__VIEWSTATE0" value="3" /><input type="hidden" name="__VIEWSTATE" value="" /><input type="hidden" name="__VIEWSTATE" value="" />
Но я не уверен , что type
, name
, и value
атрибуты будут всегда появляться в том же порядке. Если type
атрибут идет последним, совпадение не удастся, потому что в моем шаблоне он находится в начале.
Вопрос:
Как я могу изменить свой шаблон, чтобы он совпадал независимо от положения атрибутов в <input>
теге?
PS: Кстати, я использую инструмент RegEx Desktop на базе Adobe Air для тестирования регулярных выражений.
Ответы:
Вопреки всем ответам здесь, то, что вы пытаетесь сделать регулярным выражением, является вполне допустимым решением. Это потому, что вы НЕ пытаетесь сопоставить сбалансированные теги - это было бы невозможно с регулярным выражением! Но вы сопоставляете только то, что находится в одном теге, и это совершенно нормально.
Но вот в чем проблема. Вы не можете сделать это только с одним регулярным выражением ... вам нужно выполнить одно совпадение, чтобы захватить
<input>
тег, а затем выполнить дальнейшую обработку. Обратите внимание, что это будет работать только в том случае, если ни одно из значений атрибута не содержит>
символа, поэтому это не идеально, но должно быть достаточным для разумных входов.Вот некоторый (псевдо) код Perl, чтобы показать вам, что я имею в виду:
my $html = readLargeInputFile(); my @input_tags = $html =~ m/ ( <input # Starts with "<input" (?=[^>]*?type="hidden") # Use lookahead to make sure that type="hidden" [^>]+ # Grab the rest of the tag... \/> # ...except for the />, which is grabbed here )/xgm; # Now each member of @input_tags is something like <input type="hidden" name="SaveRequired" value="False" /> foreach my $input_tag (@input_tags) { my $hash_ref = {}; # Now extract each of the fields one at a time. ($hash_ref->{"name"}) = $input_tag =~ /name="([^"]*)"/; ($hash_ref->{"value"}) = $input_tag =~ /value="([^"]*)"/; # Put $hash_ref in a list or something, or otherwise process it }
Основной принцип здесь - не пытайтесь слишком много работать с одним регулярным выражением. Как вы заметили, регулярные выражения обеспечивают определенный порядок. Поэтому вместо этого вам нужно сначала сопоставить КОНТЕКСТ того, что вы пытаетесь извлечь, а затем выполнить повторное сопоставление с данными, которые вы хотите.
РЕДАКТИРОВАТЬ: Тем не менее, я согласен, что в целом использование парсера HTML, вероятно, проще и лучше, и вам действительно следует подумать о переделке кода или пересмотре ваших целей. :-) Но мне пришлось опубликовать этот ответ в качестве противодействия непонятной реакции о том, что анализ любого подмножества HTML невозможен: HTML и XML являются нерегулярными, если рассматривать всю спецификацию, но спецификация тега прилично регулярна , конечно, в пределах возможностей PCRE.
источник
О да, ты можешь использовать регулярные выражения для анализа HTML!
Для задачи, которую вы пытаетесь выполнить, регулярные выражения отлично подходят !
Это является правдой , что большинство людей недооценивают сложность разбор HTML с регулярными выражениями и , следовательно , сделать так плохо.
Но это не какой-то фундаментальный недостаток, связанный с теорией вычислений. Здесь часто повторяют эту глупость , но не верьте им.
Так что, хотя это, безусловно, можно сделать (эта публикация служит доказательством существования этого неопровержимого факта), это не означает, что так должно быть.
Вы должны решить для себя, справитесь ли вы с задачей написать выделенный, специализированный анализатор HTML на основе регулярных выражений. Большинство людей нет.
Но я . ☻
Общие решения для анализа HTML на основе регулярных выражений
Сначала я покажу, как легко разбирать произвольный HTML с помощью регулярных выражений. Полная программа находится в конце этой публикации, но суть парсера:
for (;;) { given ($html) { last when (pos || 0) >= length; printf "\@%d=", (pos || 0); print "doctype " when / \G (?&doctype) $RX_SUBS /xgc; print "cdata " when / \G (?&cdata) $RX_SUBS /xgc; print "xml " when / \G (?&xml) $RX_SUBS /xgc; print "xhook " when / \G (?&xhook) $RX_SUBS /xgc; print "script " when / \G (?&script) $RX_SUBS /xgc; print "style " when / \G (?&style) $RX_SUBS /xgc; print "comment " when / \G (?&comment) $RX_SUBS /xgc; print "tag " when / \G (?&tag) $RX_SUBS /xgc; print "untag " when / \G (?&untag) $RX_SUBS /xgc; print "nasty " when / \G (?&nasty) $RX_SUBS /xgc; print "text " when / \G (?&nontag) $RX_SUBS /xgc; default { die "UNCLASSIFIED: " . substr($_, pos || 0, (length > 65) ? 65 : length); } } }
Видите, как это легко читать?
Как написано, он идентифицирует каждый фрагмент HTML и сообщает, где он нашел этот фрагмент. Вы можете легко изменить его, чтобы делать все, что захотите, с любым заданным типом детали или для более конкретных типов, чем эти.
У меня нет тестовых примеров с ошибками (слева :): Я успешно запустил этот код для более чем 100 000 файлов HTML - каждый из которых я мог быстро и легко достать. Помимо этого, я также запускал его для файлов, специально созданных для взлома наивных парсеров.
Это не наивный парсер.
О, я уверен, что он не идеален, но мне еще не удалось его сломать. Я полагаю, что даже если бы что-то и произошло, исправление было бы легко вписать из-за четкой структуры программы. Даже программы с большим количеством регулярных выражений должны иметь структуру.
Теперь, когда это не так, позвольте мне обратиться к вопросу OP.
Демонстрация решения задачи OP с использованием регулярных выражений
Небольшая
html_input_rx
программа, которую я привожу ниже, дает следующий результат, чтобы вы могли видеть, что синтаксический анализ HTML с помощью регулярных выражений отлично подходит для того, что вы хотите сделать:% html_input_rx Amazon.com-_Online_Shopping_for_Electronics,_Apparel,_Computers,_Books,_DVDs_\&_more.htm input tag #1 at character 9955: class => "searchSelect" id => "twotabsearchtextbox" name => "field-keywords" size => "50" style => "width:100%; background-color: #FFF;" title => "Search for" type => "text" value => "" input tag #2 at character 10335: alt => "Go" src => "http://g-ecx.images-amazon.com/images/G/01/x-locale/common/transparent-pixel._V192234675_.gif" type => "image"
Разобрать теги ввода, не видеть ввод зла
Вот исходный код программы, которая дала результат выше.
#!/usr/bin/env perl # # html_input_rx - pull out all <input> tags from (X)HTML src # via simple regex processing # # Tom Christiansen <tchrist@perl.com> # Sat Nov 20 10:17:31 MST 2010 # ################################################################ use 5.012; use strict; use autodie; use warnings FATAL => "all"; use subs qw{ see_no_evil parse_input_tags input descape dequote load_patterns }; use open ":std", IN => ":bytes", OUT => ":utf8"; use Encode qw< encode decode >; ########################################################### parse_input_tags see_no_evil input ########################################################### until eof(); sub parse_input_tags { my $_ = shift(); our($Input_Tag_Rx, $Pull_Attr_Rx); my $count = 0; while (/$Input_Tag_Rx/pig) { my $input_tag = $+{TAG}; my $place = pos() - length ${^MATCH}; printf "input tag #%d at character %d:\n", ++$count, $place; my %attr = (); while ($input_tag =~ /$Pull_Attr_Rx/g) { my ($name, $value) = @+{ qw< NAME VALUE > }; $value = dequote($value); if (exists $attr{$name}) { printf "Discarding dup attr value '%s' on %s attr\n", $attr{$name} // "<undef>", $name; } $attr{$name} = $value; } for my $name (sort keys %attr) { printf " %10s => ", $name; my $value = descape $attr{$name}; my @Q; given ($value) { @Q = qw[ " " ] when !/'/ && !/"/; @Q = qw[ " " ] when /'/ && !/"/; @Q = qw[ ' ' ] when !/'/ && /"/; @Q = qw[ q( ) ] when /'/ && /"/; default { die "NOTREACHED" } } say $Q[0], $value, $Q[1]; } print "\n"; } } sub dequote { my $_ = $_[0]; s{ (?<quote> ["'] ) (?<BODY> (?s: (?! \k<quote> ) . ) * ) \k<quote> }{$+{BODY}}six; return $_; } sub descape { my $string = $_[0]; for my $_ ($string) { s{ (?<! % ) % ( \p{Hex_Digit} {2} ) }{ chr hex $1; }gsex; s{ & \043 ( [0-9]+ ) (?: ; | (?= [^0-9] ) ) }{ chr $1; }gsex; s{ & \043 x ( \p{ASCII_HexDigit} + ) (?: ; | (?= \P{ASCII_HexDigit} ) ) }{ chr hex $1; }gsex; } return $string; } sub input { our ($RX_SUBS, $Meta_Tag_Rx); my $_ = do { local $/; <> }; my $encoding = "iso-8859-1"; # web default; wish we had the HTTP headers :( while (/$Meta_Tag_Rx/gi) { my $meta = $+{META}; next unless $meta =~ m{ $RX_SUBS (?= http-equiv ) (?&name) (?&equals) (?= (?"e)? content-type ) (?&value) }six; next unless $meta =~ m{ $RX_SUBS (?= content ) (?&name) (?&equals) (?<CONTENT> (?&value) ) }six; next unless $+{CONTENT} =~ m{ $RX_SUBS (?= charset ) (?&name) (?&equals) (?<CHARSET> (?&value) ) }six; if (lc $encoding ne lc $+{CHARSET}) { say "[RESETTING ENCODING $encoding => $+{CHARSET}]"; $encoding = $+{CHARSET}; } } return decode($encoding, $_); } sub see_no_evil { my $_ = shift(); s{ <! DOCTYPE .*? > }{}sx; s{ <! \[ CDATA \[ .*? \]\] > }{}gsx; s{ <script> .*? </script> }{}gsix; s{ <!-- .*? --> }{}gsx; return $_; } sub load_patterns { our $RX_SUBS = qr{ (?(DEFINE) (?<nv_pair> (?&name) (?&equals) (?&value) ) (?<name> \b (?= \pL ) [\w\-] + (?<= \pL ) \b ) (?<equals> (?&might_white) = (?&might_white) ) (?<value> (?"ed_value) | (?&unquoted_value) ) (?<unwhite_chunk> (?: (?! > ) \S ) + ) (?<unquoted_value> [\w\-] * ) (?<might_white> \s * ) (?<quoted_value> (?<quote> ["'] ) (?: (?! \k<quote> ) . ) * \k<quote> ) (?<start_tag> < (?&might_white) ) (?<end_tag> (?&might_white) (?: (?&html_end_tag) | (?&xhtml_end_tag) ) ) (?<html_end_tag> > ) (?<xhtml_end_tag> / > ) ) }six; our $Meta_Tag_Rx = qr{ $RX_SUBS (?<META> (?&start_tag) meta \b (?: (?&might_white) (?&nv_pair) ) + (?&end_tag) ) }six; our $Pull_Attr_Rx = qr{ $RX_SUBS (?<NAME> (?&name) ) (?&equals) (?<VALUE> (?&value) ) }six; our $Input_Tag_Rx = qr{ $RX_SUBS (?<TAG> (?&input_tag) ) (?(DEFINE) (?<input_tag> (?&start_tag) input (?&might_white) (?&attributes) (?&might_white) (?&end_tag) ) (?<attributes> (?: (?&might_white) (?&one_attribute) ) * ) (?<one_attribute> \b (?&legal_attribute) (?&might_white) = (?&might_white) (?: (?"ed_value) | (?&unquoted_value) ) ) (?<legal_attribute> (?: (?&optional_attribute) | (?&standard_attribute) | (?&event_attribute) # for LEGAL parse only, comment out next line | (?&illegal_attribute) ) ) (?<illegal_attribute> (?&name) ) (?<required_attribute> (?#no required attributes) ) (?<optional_attribute> (?&permitted_attribute) | (?&deprecated_attribute) ) # NB: The white space in string literals # below DOES NOT COUNT! It's just # there for legibility. (?<permitted_attribute> accept | alt | bottom | check box | checked | disabled | file | hidden | image | max length | middle | name | password | radio | read only | reset | right | size | src | submit | text | top | type | value ) (?<deprecated_attribute> align ) (?<standard_attribute> access key | class | dir | ltr | id | lang | style | tab index | title | xml:lang ) (?<event_attribute> on blur | on change | on click | on dbl click | on focus | on mouse down | on mouse move | on mouse out | on mouse over | on mouse up | on key down | on key press | on key up | on select ) ) }six; } UNITCHECK { load_patterns(); } END { close(STDOUT) || die "can't close stdout: $!"; }
Вот так! Ничего подобного! :)
Только вы можете судить, подходят ли ваши навыки работы с регулярными выражениями для какой-либо конкретной задачи синтаксического анализа. Уровень навыков у всех разный, и каждое новое задание разное. Для заданий, где у вас есть четко определенный набор входных данных, регулярные выражения, очевидно, являются правильным выбором, потому что собрать некоторые вместе, когда у вас есть ограниченное подмножество HTML, с которым нужно иметь дело, тривиально. Даже новички в регулярных выражениях должны выполнять эти задания с помощью регулярных выражений. Все остальное - излишество.
Однако , как только HTML начинает становиться менее пригвожденным, как только он начинает разветвляться способами, которые вы не можете предсказать, но которые совершенно законны, как только вам придется сопоставить больше разных видов вещей или с более сложными зависимостями, вы в конечном итоге достигнете точки, когда вам придется потрудиться, чтобы реализовать решение, использующее регулярные выражения, чем при использовании класса синтаксического анализа. То, где упадет эта точка безубыточности, снова зависит от вашего собственного уровня комфорта с регулярными выражениями.
Так что я должен делать?
Я не собираюсь говорить вам, что вы должны делать или чего не можете . Я думаю, что это неправильно. Я просто хочу представить вам возможности, приоткройте глаза немного. Вы можете выбирать, что вы хотите делать и как вы хотите это делать. Абсолютов не существует - и никто другой не знает вашу ситуацию так хорошо, как вы сами. Если что-то кажется, что это слишком много работы, что ж, может быть, это так. Знаешь, программирование должно доставлять удовольствие . Если это не так, возможно, вы делаете это неправильно.
На мою
html_input_rx
программу можно смотреть множеством подходящих способов. Одна из них заключается в том, что вы действительно можете анализировать HTML с помощью регулярных выражений. Но другое заключается в том, что это намного, намного, намного сложнее, чем кто-либо думает. Это может легко привести к выводу, что моя программа является свидетельством того, чего вам не следует делать, потому что это действительно слишком сложно.Я не буду с этим не согласен. Конечно, если все, что я делаю в своей программе, не имеет для вас смысла после некоторого изучения, вам не следует пытаться использовать регулярные выражения для такого рода задач. Для определенного HTML регулярные выражения хороши, но для обычного HTML они равносильны безумию. Я все время использую классы синтаксического анализа, особенно если это HTML, который я не создавал сам.
Регулярные выражения оптимальны для небольших задач разбора HTML, пессимальные - для больших
Даже если мою программу рассматривать как иллюстрацию того, почему вы не должны использовать регулярные выражения для синтаксического анализа общего HTML - и это нормально, потому что я вроде как хотел, чтобы это было так - она все равно должна открывать глаза, чтобы больше людей нарушали ужасно распространенные и неприятная, неприятная привычка писать нечитаемые, неструктурированные и неподдерживаемые шаблоны.
Выкройки не обязательно должны быть уродливыми и сложными. Если вы создаете уродливые узоры, это отражается на вас, а не на них.
Феноменально изысканный язык регулярных выражений
Меня попросили указать, что предложенное мной решение вашей проблемы написано на Perl. Вы удивлены? Вы не заметили? Это открытие произвело эффект разорвавшейся бомбы?
Верно, что не все другие инструменты и языки программирования столь же удобны, выразительны и мощны, когда дело касается регулярных выражений, как Perl. Существует большой спектр, некоторые из которых подходят больше, чем другие. В общем, с языками, которые выражают регулярные выражения как часть основного языка, а не как библиотеку, легче работать. Я ничего не сделал с регулярными выражениями, что вы не могли бы сделать, скажем, в PCRE, хотя вы бы структурировали программу иначе, если бы использовали C.
В конце концов, другие языки догонят Perl с точки зрения регулярных выражений. Я говорю это потому, что когда начинался Perl, ни у кого не было ничего похожего на регулярные выражения Perl. Говорите что угодно, но именно здесь Perl явно победил: все копировали регулярные выражения Perl, хотя и на разных этапах их разработки. Perl был пионером почти (не совсем всего, но почти) всего, на что вы привыкли полагаться в современных шаблонах сегодня, независимо от того, какой инструмент или язык вы используете. Таким образом , в конце концов , другие будут догонять.
Но они догонят только то, на чем был Perl когда-то в прошлом, как и сейчас. Все идет вперед. В регулярных выражениях, если ничто иное, куда ведет Perl, следуют другие. Где будет Perl, когда все, наконец, поймут, где Perl находится сейчас? Понятия не имею, но знаю, что мы тоже переедем. Возможно, мы будем ближе к стилю создания шаблонов Perl .
Если вам нравятся такие вещи, но вы хотели бы использовать их в Perl₅, вас может заинтересовать замечательный модуль Regexp :: Grammars Дэмиана Конвея . Это совершенно потрясающе, и то, что я сделал здесь, в своей программе, кажется таким же примитивным, как и мое, что создает шаблоны, которые люди собирают вместе, без пробелов или буквенных идентификаторов. Проверить это!
Простой HTML Chunker
Вот полный исходный код парсера, который я показал в самом начале этой публикации.
Я не предлагаю вам использовать это вместо тщательно протестированного класса синтаксического анализа. Но я устал от людей, которые притворяются, будто никто не может анализировать HTML с помощью регулярных выражений только потому, что они не могут. Вы явно можете, и эта программа является доказательством этого утверждения.
Конечно, это не легко, но это это возможно!
И попытки сделать это - ужасная трата времени, потому что существуют хорошие классы синтаксического анализа, которые вы должны использовать для этой задачи. Правильный ответ людям, пытающимся разобрать произвольный HTML, заключается не в том, что это невозможно. Это легкий и лукавый ответ. Правильный и честный ответ состоит в том, что они не должны пытаться это сделать, потому что слишком сложно разобраться с нуля; они не должны ломать себе спину, пытаясь заново изобрести колесо, которое отлично работает.
С другой стороны, HTML, который попадает в предсказуемое подмножество , очень легко анализировать с помощью регулярных выражений. Неудивительно, что люди пытаются их использовать, потому что для небольших задач, возможно, игрушечных, нет ничего проще. Вот почему так важно различать две задачи - конкретную и общую - поскольку они не обязательно требуют одного и того же подхода.
Я надеюсь, что в будущем здесь будет более справедливое и честное решение вопросов об HTML и регулярных выражениях.
Вот мой лексер HTML. Он не пытается выполнить проверочный синтаксический анализ; он просто определяет лексические элементы. Вы могли бы думать об этом больше как о чанкере HTML, чем о парсере HTML. Он не очень прощает сломанный HTML, хотя делает некоторые очень небольшие поправки в этом направлении.
Даже если вы никогда не разбираете полный HTML самостоятельно (а зачем вам это нужно? Это решенная проблема!), В этой программе есть много интересных битов регулярных выражений, на которых, я думаю, многие люди могут многому научиться. Наслаждайтесь!
#!/usr/bin/env perl # # chunk_HTML - a regex-based HTML chunker # # Tom Christiansen <tchrist@perl.com # Sun Nov 21 19:16:02 MST 2010 ######################################## use 5.012; use strict; use autodie; use warnings qw< FATAL all >; use open qw< IN :bytes OUT :utf8 :std >; MAIN: { $| = 1; lex_html(my $page = slurpy()); exit(); } ######################################################################## sub lex_html { our $RX_SUBS; ############### my $html = shift(); # Am I... # for (;;) { # forgiven? :)# given ($html) { ############### last when (pos || 0) >= length; printf "\@%d=", (pos || 0); print "doctype " when / \G (?&doctype) $RX_SUBS /xgc; print "cdata " when / \G (?&cdata) $RX_SUBS /xgc; print "xml " when / \G (?&xml) $RX_SUBS /xgc; print "xhook " when / \G (?&xhook) $RX_SUBS /xgc; print "script " when / \G (?&script) $RX_SUBS /xgc; print "style " when / \G (?&style) $RX_SUBS /xgc; print "comment " when / \G (?&comment) $RX_SUBS /xgc; print "tag " when / \G (?&tag) $RX_SUBS /xgc; print "untag " when / \G (?&untag) $RX_SUBS /xgc; print "nasty " when / \G (?&nasty) $RX_SUBS /xgc; print "text " when / \G (?&nontag) $RX_SUBS /xgc; default { die "UNCLASSIFIED: " . substr($_, pos || 0, (length > 65) ? 65 : length); } } } say "."; } ##################### # Return correctly decoded contents of next complete # file slurped in from the <ARGV> stream. # sub slurpy { our ($RX_SUBS, $Meta_Tag_Rx); my $_ = do { local $/; <ARGV> }; # read all input return unless length; use Encode qw< decode >; my $bom = ""; given ($_) { $bom = "UTF-32LE" when / ^ \xFf \xFe \0 \0 /x; # LE $bom = "UTF-32BE" when / ^ \0 \0 \xFe \xFf /x; # BE $bom = "UTF-16LE" when / ^ \xFf \xFe /x; # le $bom = "UTF-16BE" when / ^ \xFe \xFf /x; # be $bom = "UTF-8" when / ^ \xEF \xBB \xBF /x; # st00pid } if ($bom) { say "[BOM $bom]"; s/^...// if $bom eq "UTF-8"; # st00pid # Must use UTF-(16|32) w/o -[BL]E to strip BOM. $bom =~ s/-[LB]E//; return decode($bom, $_); # if BOM found, don't fall through to look # for embedded encoding spec } # Latin1 is web default if not otherwise specified. # No way to do this correctly if it was overridden # in the HTTP header, since we assume stream contains # HTML only, not also the HTTP header. my $encoding = "iso-8859-1"; while (/ (?&xml) $RX_SUBS /pgx) { my $xml = ${^MATCH}; next unless $xml =~ m{ $RX_SUBS (?= encoding ) (?&name) (?&equals) (?"e) ? (?<ENCODING> (?&value) ) }sx; if (lc $encoding ne lc $+{ENCODING}) { say "[XML ENCODING $encoding => $+{ENCODING}]"; $encoding = $+{ENCODING}; } } while (/$Meta_Tag_Rx/gi) { my $meta = $+{META}; next unless $meta =~ m{ $RX_SUBS (?= http-equiv ) (?&name) (?&equals) (?= (?"e)? content-type ) (?&value) }six; next unless $meta =~ m{ $RX_SUBS (?= content ) (?&name) (?&equals) (?<CONTENT> (?&value) ) }six; next unless $+{CONTENT} =~ m{ $RX_SUBS (?= charset ) (?&name) (?&equals) (?<CHARSET> (?&value) ) }six; if (lc $encoding ne lc $+{CHARSET}) { say "[HTTP-EQUIV ENCODING $encoding => $+{CHARSET}]"; $encoding = $+{CHARSET}; } } return decode($encoding, $_); } ######################################################################## # Make sure to this function is called # as soon as source unit has been compiled. UNITCHECK { load_rxsubs() } # useful regex subroutines for HTML parsing sub load_rxsubs { our $RX_SUBS = qr{ (?(DEFINE) (?<WS> \s * ) (?<any_nv_pair> (?&name) (?&equals) (?&value) ) (?<name> \b (?= \pL ) [\w:\-] + \b ) (?<equals> (?&WS) = (?&WS) ) (?<value> (?"ed_value) | (?&unquoted_value) ) (?<unwhite_chunk> (?: (?! > ) \S ) + ) (?<unquoted_value> [\w:\-] * ) (?<any_quote> ["'] ) (?<quoted_value> (?<quote> (?&any_quote) ) (?: (?! \k<quote> ) . ) * \k<quote> ) (?<start_tag> < (?&WS) ) (?<html_end_tag> > ) (?<xhtml_end_tag> / > ) (?<end_tag> (?&WS) (?: (?&html_end_tag) | (?&xhtml_end_tag) ) ) (?<tag> (?&start_tag) (?&name) (?: (?&WS) (?&any_nv_pair) ) * (?&end_tag) ) (?<untag> </ (?&name) > ) # starts like a tag, but has screwed up quotes inside it (?<nasty> (?&start_tag) (?&name) .*? (?&end_tag) ) (?<nontag> [^<] + ) (?<string> (?"ed_value) ) (?<word> (?&name) ) (?<doctype> <!DOCTYPE # please don't feed me nonHTML ### (?&WS) HTML [^>]* > ) (?<cdata> <!\[CDATA\[ .*? \]\] > ) (?<script> (?= <script ) (?&tag) .*? </script> ) (?<style> (?= <style ) (?&tag) .*? </style> ) (?<comment> <!-- .*? --> ) (?<xml> < \? xml (?: (?&WS) (?&any_nv_pair) ) * (?&WS) \? > ) (?<xhook> < \? .*? \? > ) ) }six; our $Meta_Tag_Rx = qr{ $RX_SUBS (?<META> (?&start_tag) meta \b (?: (?&WS) (?&any_nv_pair) ) + (?&end_tag) ) }six; } # nobody *ever* remembers to do this! END { close STDOUT }
источник
//input[@type="hidden"]
. Или, если вы не хотите использовать xpath, просто получите все входные данные и отфильтруйте, какие из них скрытыgetAttribute
.Я предпочитаю №2.
<?php $d = new DOMDocument(); $d->loadHTML( ' <p>fsdjl</p> <form><div>fdsjl</div></form> <input type="hidden" name="blah" value="hide yo kids"> <input type="text" name="blah" value="hide yo kids"> <input type="hidden" name="blah" value="hide yo wife"> '); $x = new DOMXpath($d); $inputs = $x->evaluate('//input[@type="hidden"]'); foreach ( $inputs as $input ) { echo $input->getAttribute('value'), '<br>'; }
Результат:
hide yo kids<br>hide yo wife<br>
источник
В духе лексического решения Тома Кристиансена вот ссылка на, казалось бы, забытую статью Роберта Кэмерона 1998 года, REX: поверхностный анализ XML с регулярными выражениями.
http://www.cs.sfu.ca/~cameron/REX.html
Если вам нравится читать о регулярных выражениях, статья Кэмерона очень интересна. Его текст краткий, тщательный и очень подробный. Он не просто показывает вам, как построить регулярное выражение REX, но также предлагает подход к созданию любого сложного регулярного выражения из более мелких частей.
Я использовал регулярное выражение REX в течение 10 лет, чтобы решить проблему, о которой спрашивал начальный плакат (как мне сопоставить этот конкретный тег, но не какой-либо другой очень похожий тег?). Я считаю разработанное им регулярное выражение полностью надежным.
REX особенно полезен, когда вы сосредотачиваетесь на лексических деталях документа - например, при преобразовании одного типа текстового документа (например, обычного текста, XML, SGML, HTML) в другой, где документ может быть недействительным, хорошо сформирован или даже поддается синтаксическому анализу для большей части преобразования. Это позволяет вам нацеливать участки разметки в любом месте документа, не нарушая остальную часть документа.
источник
Хотя мне нравится содержание остальных ответов, они не ответили на вопрос прямо или правильно. Даже ответ Platinum был чрезмерно сложным и к тому же менее эффективным. Поэтому я был вынужден поставить это.
Я большой сторонник Regex при правильном использовании. Но из-за стигмы (и производительности) я всегда заявляю, что правильно сформированный XML или HTML должен использовать XML Parser. И даже лучшая производительность была бы при синтаксическом анализе строк, хотя есть грань между удобочитаемостью, если это становится слишком неуправляемым. Однако вопрос не в этом. Вопрос в том, как сопоставить тег ввода скрытого типа. Ответ:
<input[^>]*type="hidden"[^>]*>
В зависимости от вашего вкуса, единственный вариант регулярного выражения, который вам нужно включить, - это параметр ignorecase.
источник
<input type='hidden' name='Oh, <really>?' value='Try a real HTML parser instead.'>
>
в поле имени почти нет, действительно возможно, что там будет>
в дескрипторе действия. Например: встроенный вызов javascript для свойства OnClick. При этом у меня есть синтаксический анализатор XML для них, но также есть Regex для тех, где предоставленный мне документ слишком запутан для обработки синтаксическими анализаторами XML, но Regex может. Кроме того, вопрос был не в этом. Вы никогда не столкнетесь с подобными ситуациями со скрытым вводом данных, и мой ответ - лучший.Ya, <really>!
./>
это XML-изм; он не требуется ни в одной версии HTML, за исключением XHTML (который никогда не пользовался особой популярностью и был почти заменен HTML5). И вы правы в том, что существует много беспорядочного не совсем корректного HTML, но хороший синтаксический анализатор HTML ( не XML) должен уметь справиться с большей его частью; если нет, скорее всего, и браузеры тоже.вы можете попробовать это:
<[A-Za-z ="/_0-9+]*>
и для более точного результата вы можете попробовать следующее:
<[ ]*input[ ]+type="hidden"[ ]*name=[A-Za-z ="_0-9+]*[ ]*[/]*>
вы можете проверить свой шаблон регулярного выражения здесь http://regexpal.com/
для этого хороши вот такие узоры:
<input type="hidden" name="SaveRequired" value="False" /><input type="hidden" name="__VIEWSTATE1" value="1H4sIAAtzrkX7QfL5VEGj6nGi+nP" /><input type="hidden" name="__VIEWSTATE2" value="0351118MK" /><input type="hidden" name="__VIEWSTATE3" value="ZVVV91yjY" />
и для случайного порядка
type
,name
иvalue
вы можете использовать это:<[ ]*input[ ]*[A-Za-z ="_0-9+/]*>
или
<[ ]*input[ ]*[A-Za-z ="_0-9+/]*[ ]*[/]>
на этом :
<input name="SaveRequired" type="hidden" value="False" /><input type="hidden" name="__VIEWSTATE1" value="1H4sIAAtzrkX7QfL5VEGj6nGi+nP" /><input type="hidden" name="__VIEWSTATE2" value="0351118MK" /><input name="__VIEWSTATE3" type="hidden" value="ZVVV91yjY" />
`
кстати, я думаю, вам нужно что-то вроде этого:
<[ ]*input(([ ]*type="hidden"[ ]*name=[A-Za-z0-9_+"]*[ ]*value=[A-Za-z0-9_+"]*[ ]*)+)[ ]*/>|<[ ]*input(([ ]*type="hidden"[ ]*value=[A-Za-z0-9_+"]*[ ]*name=[A-Za-z0-9_+"]*[ ]*)+)[ ]*/>|<[ ]*input(([ ]*name=[A-Za-z0-9_+"]*[ ]*type="hidden"[ ]*value=[A-Za-z0-9_+"]*[ ]*)+)[ ]*/>|<[ ]*input(([ ]*value=[A-Za-z0-9_+"]*[ ]*type="hidden"[ ]*name=[A-Za-z0-9_+"]*[ ]*)+)[ ]*/>|<[ ]*input(([ ]*name=[A-Za-z0-9_+"]*[ ]*value=[A-Za-z0-9_+"]*[ ]*type="hidden"[ ]*)+)[ ]*/>|<[ ]*input(([ ]*value=[A-Za-z0-9_+"]*[ ]*name=[A-Za-z0-9_+"]*[ ]*type="hidden"[ ]*)+)[ ]*/>
это не хорошо, но работает в любом случае.
проверьте это на: http://regexpal.com/
источник
Я хотел бы использовать
**DOMDocument**
для извлечения html-кода.$dom = new DOMDocument(); $dom ->loadHTML($input); $x = new DOMXpath($dom ); $results = $x->evaluate('//input[@type="hidden"]'); foreach ( $results as $item) { print_r( $item->getAttribute('value') ); }
Кстати, вы можете протестировать его здесь - regex101.com. Показывает результат в реальном времени. Некоторые правила о Regexp: http://www.eclipse.org/tptp/home/downloads/installguide/gla_42/ref/rregexp.html Reader .
источник
предположим, что ваш html-контент хранится в строке html, тогда для получения каждого ввода, содержащего скрытый тип, вы можете использовать регулярное выражение
var regex = /(<input.*?type\s?=\s?["']hidden["'].*?>)/g; html.match(regex);
приведенное выше регулярное выражение find,
<input
за которым следует любое количество символов, пока оно не получит,type="hidden"
или введите = 'hidden', за которым следует любое количество символов, пока оно не получит>
/ g указывает регулярному выражению найти каждую подстроку, соответствующую заданному шаблону.
источник