2010-07-17 7 views
4

Использование Nokogiri, мне нужно, чтобы разобрать блок заданного:Regex синтаксического анализа с использованием Nokogiri

<div class="some_class"> 
    12 AB/4+ CD 
    <br/> 
    2,600 Dollars 
    <br/> 
</div> 

Мне нужно получить значения по ab, cd и dollars, если они существуют.

ab = p.css(".some_class").text[....some regex....] 
cd = p.css(".some_class").text[....some regex....] 
dollars = p.css(".some_class").text[....some regex....] 

Это правильно? Если да, может ли кто-нибудь помочь мне с регулярным выражением проанализировать значения ab, cd и dollars?

ответ

6

Чтобы получить лучший ответ, вам нужно будет уточнить, в каком формате берутся значения AB, CD и Dollar, но вот решение, основанное на приведенном примере. Он использует регулярное выражение группировки (), чтобы захватить информацию, которую мы заинтересованы в (см. Нижняя часть ответа для более подробной информации)

text = p.css(".some_class").text 

# one or more digits followed by a space followed by AB, capture the digits 
ab = text.match(/(\d+) AB/).captures[0] # => "12" 

# one of more non digits followed by a literal + followed by CD 
cd = text.match(/(\d+\+) CD/).captures[0] # => "4+" 

# digits or commas followed by "Dollars" 
dollars = text.match(/([\d,]+) Dollars/).captures[0] # => "2,600" 

Обратите внимание, что если нет совпадения, то String#match возвращается nil так, если значение может не существует, вам понадобится проверка, например

if match = text.match(/([\d,]+) Dollars/) 
    dollars = match.captures[0] 
end 

Дополнительное объяснение захватами

Чтобы соответствовать сумме АВ нам нужен образец /\d+ AB/, чтобы определить правильную часть текста. Тем не менее, нас действительно интересует только числовая часть, поэтому мы окружаем ее скобками, чтобы мы могли ее извлечь. например

irb(main):027:0> match = text.match(/(\d+) AB/) 
=> #<MatchData:0x2ca3440>   # the match method returns MatchData if there is a match, nil if not 
irb(main):028:0> match.to_s   # match.to_s gives us the entire text that matched the pattern 
=> "12 AB" 
irb(main):029:0> match.captures  
=> ["12"] 
# match.captures gives us an array of the parts of the pattern that were enclosed in() 
# in our example there is just 1 but there could be multiple 
irb(main):030:0> match.captures[0] 
=> "12"        # the first capture - the bit we want 

Посмотрите на документацию для MatchData, в частности, метод captures для более подробной информации.

+0

Спасибо! для меня это нормально. Так что все работает нормально. –

+0

Примечание: если нет совпадения, то это не то, что ваши переменные, например. '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ' – mikej

+0

Ах. Хорошо я понял. Итак, какой метод захвата? Потому что теперь он отлично работает без привязок для меня. –

0

Это более старая тема, но я просто наткнулся на нее. Вот как я могу найти значения и удобный способ хранения значений:

require "ap" 
require "nokogiri" 

xml = <<EOT 
<div class="some_class"> 
    12 AB/4+ CD 
    <br/> 
    2,600 Dollars 
    <br/> 
</div> 
EOT 

doc = Nokogiri::XML(xml) 

some_class = doc.at('.some_class').text 

values = some_class 
    .scan(/([\d+]+) ([a-z,]+)/i) 
    .each_with_object({}){ |(v,c), h| h[c] = v.to_i } 

values # => {"AB"=>12, "CD"=>4, "Dollars"=>600} 
+0

есть ли способ для nokogiri просто вернуть данные, если он соответствует определенному шаблону регулярного выражения, а не возвращать все, а затем позже применить к нему логику? esp, при синтаксическом анализе большого файла xml, возможно, что nokogiri возвращает только то, что мы хотим, быстрее? Или будет ли позже его фильтровать быстрее? Благодарю. –

+0

XPath2 поддерживает регулярное выражение, тогда как старший XPath1 этого не сделал. CSS-код Nokogiri предоставляет несколько расширений типа jQuery, которые не позволяют регулярное выражение, но могут помочь. Быстрее разрешить библиотеке libXML2 поднимать/искать, чем возвращать каждый узел в Nokogiri, а затем просеивать их, но вы можете доказать это, используя тесты. –

Смежные вопросы