Я пытаюсь использовать Hpricot, чтобы получить значение в диапазоне с именем класса, которое я не знаю. Я знаю, что это следует шаблону "foo_ [несколько цифр] _bar".

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

doc = Hpricot(open("http://scrape.example.com/search?q=#{ticker_symbol}"))
elements = doc.search("//span[@class='pr']").inner_html
string = ""
elements.each do |attr|
  if(attr =~ /foo_\d+_bar/)
    string = attr
  end
end
# get rid of the span tags, just get the value
string.sub!(/<\/span>/, "")
string.sub!(/<span.+>/, "")

return string

Похоже, должен быть лучший способ сделать это. Я бы хотел сделать что-то вроде:

elements = doc.search("//span[@class='" + /foo_\d+_bar/ + "']").inner_html

Но это не работает. Есть ли способ поиска с помощью регулярного выражения?

0
AaronM 29 Дек 2009 в 07:33

3 ответа

Лучший ответ

Это должно делать:

doc.search("span[@class^='foo'][@class$='bar']")
2
Nakul 30 Дек 2009 в 14:34
Это похоже на то, что я хочу. Я попробую и посмотрю, как это пойдет.
 – 
AaronM
3 Янв 2010 в 01:11
Сработало отлично! Это именно то, что я хотел.
 – 
AaronM
4 Янв 2010 в 02:31

Это должно делать:

doc.search("span[@class^='foo'][@class$='bar']")

В дополнение к этому мы можем привести еще несколько примеров того, как работают некоторые другие похожие выражения:

Для документа, подобного следующему:

Для каждого запроса мы получаем следующий результат:

doc.search("//meta[@content='abcxy def ghi jklmn']")
=> #<Hpricot::Elements[{emptyelem <meta content="abcxy def ghi jklmn">}]>

Этого мы и ожидали.

doc.search("//meta[@content='def']")
=> #<Hpricot::Elements[]>

Как видите, = ищет точное совпадение.

doc.search("//meta[@content~='def']")
=> #<Hpricot::Elements[{emptyelem <meta content="abcxy def ghi jklmn">}]>

С помощью ~ мы можем выполнить сопоставление подстроки; но не совсем то, чего вы ожидали.

Например, см. Следующее.

doc.search("//meta[@content~=' def ']")
=> #<Hpricot::Elements[]>

Кажется, что пробелы обрабатываются особым образом.

С помощью звезды мы можем решить эту проблему. Теперь мы выполняем истинное сопоставление подстрок.

doc.search("//meta[@content*=' def ']")
=> #<Hpricot::Elements[{emptyelem <meta content="abcxy def ghi jklmn">}]>

Мы также можем выполнить сопоставление начала и конца строки следующим образом:

doc.search("//meta[@content^='def']")
=> #<Hpricot::Elements[]>

doc.search("//meta[@content^='ab']")
=> #<Hpricot::Elements[{emptyelem <meta content="abcxy def ghi jklmn">}]>

doc.search("//meta[@content$='mn']")
=> #<Hpricot::Elements[{emptyelem <meta content="abcxy def ghi jklmn">}]>

Учтите, что для этих пробелов не проблема.

doc.search("//meta[@content$=' jklmn']")
=> #<Hpricot::Elements[{emptyelem <meta content="abcxy def ghi jklmn">}]>
3
CEGRD 26 Май 2011 в 14:11

Можно изменить входящий html перед синтаксическим анализом.

html = open("http://scrape.example.com/search?q=#{ticker_symbol}").string
html.gsub!(/class="(foo_\d+_bar)"/){ |s| "class=\"foo_bar #{$1}\"" }
doc = Hpricot(html)

После этого вы можете идентифицировать элементы с помощью класса foo_bar. Это далеко не изящно или универсально, но может оказаться более эффективным.

0
anshul 29 Дек 2009 в 12:05
Спасибо за предложение. Это сработало бы, если бы оно не вернуло строку. Я бы предпочел вернуть объект HPricot Element.
 – 
AaronM
4 Янв 2010 в 02:33