как разобрать строку, только если одно из ее полей выделено жирным шрифтом? Нокогири и Руби

поэтому у меня есть этот код, который собирает всю необходимую мне информацию о продукте:

  # get main page
  page = agent.get "http://www.site.com.mx/tienda/index.php"

  search_form = page.forms.first

  search_result = agent.submit search_form

  doc = Nokogiri::HTML(search_result.body)

  rows = doc.css("table.articulos tr")

        i = 0
        details = rows.collect do |row|
          detail = {}
          [
            [:sku, 'td[3]/text()'],
            [:desc, 'td[4]/text()'],
            [:qty, 'td[5]/text()'],
            [:qty2, 'td[5]/p/b/text()'],
            [:price, 'td[6]/text()']
          ].collect do |name, xpath|
            detail[name] = row.at_xpath(xpath).to_s.strip
          end
          i = i + 1
          detail
        end

Мне нужно собрать SKU как в моем коде (в переменной), если существует только qty2.


person ingalcala    schedule 22.06.2011    source источник
comment
Как вы извлекаете свои строки?   -  person Mark Thomas    schedule 22.06.2011
comment
Похоже, вы пытаетесь разобрать html. Вы смотрели нокогири?   -  person Candide    schedule 22.06.2011
comment
Хм, он использует Nokogiri, смотрите заголовок вопроса, теги и метод at_xpath().   -  person Mark Thomas    schedule 22.06.2011
comment
Да, я использую Nokogiri, и это файл RUBY.   -  person ingalcala    schedule 22.06.2011
comment
Похоже, вы используете Mechanize для доступа к сайту. Если это так, Mechanize использует Nokogiri для внутреннего использования, поэтому вы можете запросить у него документ Nokogiri, а не анализировать тело или просто сообщить об этом search. См. раздел очистки данных в нижней части страницы Начало работы с Mechanize.   -  person the Tin Man    schedule 22.06.2011
comment
@the Tin Man: я прочитал документацию на сайте Mechanize и Nokogiri, там говорится, что вы можете использовать страницу chanize в качестве объекта nokogiri. Теперь, если я использую поиск, это даст мне искомое поле и проанализирует его, мне нужно другое поле в той же строке, будет ли это работать?   -  person ingalcala    schedule 22.06.2011
comment
Ваш HTML неверный формат: у вас есть </a><a...> за пределами td блоков. Nokogiri проанализирует его, однако перепишет DOM, чтобы он был правильным. Это может изменить необходимые методы доступа, потому что правильная разметка может не соответствовать тому, что показывает ваш образец.   -  person the Tin Man    schedule 23.06.2011


Ответы (2)


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

rows = doc.xpath('//table[@class="articulos"]/tr[td[5]/p/b]')

Обновление 2

Вот пример, показывающий, что это работает.

require 'nokogiri'

html = <<__html__
<html>
<table class="articulos">
<tr>
  <td>1</td>
  <td>2</td>
  <td>sku1</td>
  <td>4</td>
  <td>5</td>
  <td>6</td>
</tr>
<tr>
  <td>2-1</td>
  <td>2-2</td>
  <td>sku2</td>
  <td>2-4</td>
  <td><p><b>2-5</b></p></td>
  <td>2-6</td>
</tr>
</table>
</html>
__html__

doc = Nokogiri::HTML(html)
doc.xpath('//table[@class="articulos"]/tr[td[5]/p/b]').each do |row|
  puts row.at_xpath('td[3]/text()')
end

Выход:

sku2
person Mark Thomas    schedule 22.06.2011
comment
rows = doc.xpath('//table[@class=articulos]/tr[not(td[5])]') не будет мешать жирному шрифту, если он находится в той же логике выбора? - person ingalcala; 22.06.2011
comment
Никаких помех, потому что селектор специально ищет p с b внутри, которая должна существовать, прежде чем она совпадет и будет исключена. - person Mark Thomas; 22.06.2011
comment
да, но мне нужен жирный шрифт, и если я использую not(td[5]) , жирный шрифт находится на том же пути, что и в td[5]. Я только что сделал это, и он не собирает никаких данных. потому что он говорит просто собирать, если td [5] отсутствует: S .. есть идеи? - person ingalcala; 22.06.2011
comment
Я думаю, это будет что-то вроде: если присутствует xpath td[5]/p/b/text(), собрать xpath td[3]/text() ?? Любая идея, как настроить это? - person ingalcala; 22.06.2011
comment
@ingalcala, я обновил свой ответ. Я удалил not(), и теперь он дает вам строки выделенные жирным шрифтом, а не жирным шрифтом. - person Mark Thomas; 22.06.2011
comment
Я получаю: undefined метод `each' для nil:NilClass (NoMethodError) , я думаю, это потому, что другие строки существуют, но у них нет этого условия. так что мне нужно определить объект? - person ingalcala; 22.06.2011
comment
@ingalcala, наличие несовпадающих строк не повлияет на это. Скорее всего, XPath не соответствует вашему XML. Можете ли вы предоставить образец фрагмента XML (например, полный элемент таблицы)? - person Mark Thomas; 22.06.2011
comment
@Марк Томас, я обновил кое-какую информацию. Я забыл сказать, что использую Mechanize. ИДК, если это имеет значение вообще. xpath для жирного шрифта: /x:html/x:body/x:a/x:center/x:table[2]/x:tbody/x:tr/x:td[2]/x:center[3]/ x:table/x:tbody/x:tr[3]/x:td[5]/x:p/x:b xpath для нежирного шрифта: /x:html/x:body/x:a/x:center /x:таблица[2]/x:tbody/x:tr/x:td[2]/x:center[3]/x:table/x:tbody/x:tr[6]/x:td[5 ] - person ingalcala; 23.06.2011
comment
@ingalcala, мое последнее обновление показывает, как это делается, на полном примере. Вы можете приспособиться к своим конкретным потребностям XPath. - person Mark Thomas; 23.06.2011

Если я правильно понял ваш вопрос:

rows.collect{...}.reject{|detail| detail[:qty2].empty?}

or

rows.inject([]){ |details, row| ... ; detail[:qty2].empty? ? details : details.push(detail) }
person Victor Moroz    schedule 22.06.2011
comment
Извините, если я звучу немного глупо, спрашивая об этом. Но я добавляю свой код в ваши точки? или как это будет работать? Благодарю. - person ingalcala; 22.06.2011
comment
пожалуйста, помогите мне понять синтаксис как моего кода, так и вашей рекомендации - person ingalcala; 22.06.2011