2013-09-09 2 views
0

Я хочу создать объект JSON от каждого TR от this site.Как создать JSON из разобранной таблицы HTML с помощью Nokogiri?

На данный момент я могу получить всю таблицу и каждый TR, но этого недостаточно ... Вот почему я в замешательстве.

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

{ 
    "chapter":"07", 
    "title":"LIFTING AND SHORING", 
    "description":"This chapter shall...", 
    "section":[ 
    { 
     "number":"00", 
     "title":"GENERAL", 
     "description":"", 
    }, 

    { 
     "number":"10", 
     "title":"JACKING", 
     "description":"Provides information relative...", 
    }, 

    { 
     "number":"20", 
     "title":"SHORING", 
     "description":"Those instructions necessary...", 
    } 
    ] 
} 

Что мне нужно, чтобы получить все это дело сразу, но вот что мне удалось до сих пор:

parsed_html.css("table")[1].css("tr") 

Я использую Nokogiri для разбор.

ответ

4

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

Я написал это, что соответствует хотя бы вашему примеру для главы 07.

Он работает, выбирая (единственную) таблицу со страницы с несколькими строками. Затем он выполняет итерацию по этим строкам, извлекает массив полей, преобразует нерасщепляемые пробелы в обычные пространства и разделяет начальные и конечные пробелы. Все пустые поля отбрасываются, и вся строка игнорируется, если она не содержит данных.

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

Если поле отсутствовало от источника (в описания полея и раздел названия) Я обычно выбираю, чтобы исключить его из промежуточных данных. Однако я по умолчанию поставил эти поля в пустую строку, чтобы соответствовать вашему примеру ожидаемого вывода JSON. (Существует разница между несуществующим элементом хэша и значением nil.)

Надеюсь, это поможет.

require 'open-uri' 
require 'nokogiri' 
require 'json' 

open('http://www.s-techent.com/ATA100.htm') do |f| 

    doc = Nokogiri::HTML(f) 
    table = doc.at_xpath('//table[count(tr) > 1]') 

    chapters = [] 
    chapter = nil 

    table.xpath('tr').each do |tr| 

    td = tr.xpath('td') 
    td = td.map { |td| td.content.gsub("\u00A0", ' ').strip } 
    td = td.select { |txt| not txt.empty? } 
    next if td.empty? 

    if td[0] =~ /^\d+/ 

     chapters << chapter if chapter 

     chapter = { 
      'chapter'  => td[0], 
      'title'  => td[1], 
      'description' => td[2] || '' 
     } 

    elsif td[0] =~ /^-(\d+)/ 

     section = { 
      'number'  => $1, 
      'title'  => td[1] || '', 
      'description' => td[2] || '' 
     } 

     chapter['section'] ||= [] 
     chapter['section'] << section 
    end 

    end 

    chapters << chapter if chapter 

    puts JSON.pretty_generate(chapters) 

end 

(частичный) выход

{ 
    "chapter": "07", 
    "title": "LIFTING AND SHORING", 
    "description": "This chapter shall include the necessary procedures to lift and shore aircraft in any of the conditions to which it may be subjected. Includes lifting and shoring procedures that may be employed during aircraft maintenance and repair.", 
    "section": [ 
    { 
     "number": "00", 
     "title": "GENERAL", 
     "description": "" 
    }, 
    { 
     "number": "10", 
     "title": "JACKING", 
     "description": "Provides information relative to jack points, adapters, tail supports, balance weights, jacks and jacking procedures utilized during aircraft maintenance and repair." 
    }, 
    { 
     "number": "20", 
     "title": "SHORING", 
     "description": "Those instructions necessary to support the aircraft during maintenance and repair. Includes information on shoring materials and equipment, contour dimensions, shoring locations, etc." 
    } 
    ] 
}, 
+0

Что вы здесь сделали ... Я ошеломлен! Теперь я знаю, почему эта задача для меня была такой большой проблемой. Ваш ответ - именно то, что я искал, и проясняет все. Я должен тебе пинту хорошего пива :) – cojoj

1

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

Например

  • Есть два Глава 01s: ВВЕДЕНИЯ и ОПЕРАЦИИ ИНФОРМАЦИЯ

  • номер главы иногда просто числовой, как 05, а иногда и смесь, подобные 72(R)

  • Главы до 23 имеет звание во втором столбце с атрибутом на td элементе colspan="2", но главы после того, что есть пустой второй столбец и заголовок в третьей колонке

  • Существует хаотичное и паразитное использование не -breakable пространства U+00A0, которому String класс не признает пробельным

  • есть пустые строки с серым фоном, которые имеют bgcolor="#CCCCCC", которые могут быть использованы для разделения информации главы. Но опять же мы полагаемся на точность ввода вручную

  • Что-то делать с ОПРЕДЕЛЕНИЕ ГРУППЫ строк в таблице?

Это было бы довольно простым, если программа не для извлечения данных из других подобных страниц, или из (вручную) модифицированной версии одной и той же страницы. В противном случае вы должны поклониться факту, что данные, введенные вручную, не могут быть проанализированы и сдаваться.

+0

Нет, нет ничего, чтобы сделать с GROUP Определение и я думаю, что лучшим решением является разделение глав, используя этот неактивны линии (но не знаю, как...). Мне нужно только извлекать данные с этой страницы specificc, и это один таймер, поскольку я хочу практиковать Ruby и избегать какой-либо ручной работы. Мне нужны эти JSON для приложения iOS. – cojoj