Статьи

Ruby и OpenCalais: преобразование данных в информацию

calais_logo

Несколько недель назад мы увидели, как семантическая веб-служба OpenCalais помогла Коннору, начинающему молодому журналисту, разобраться в своих данных и снизить нагрузку. При этом Коннор просто снял поверхность с огромным аналитическим потенциалом, который предоставляет OpenCalais. На этой неделе мы рассмотрим некоторые из более сложных возможностей, которые предлагает сервис. Держитесь за свои места для части 2: День Обнаружения Данных!

Настройка

Мы снова будем использовать драгоценный камень DoverToCalais , обертку вокруг API OpenCalais с некоторыми хитростями. Вы должны знать тренировку к настоящему времени:

$ gem install dover_to_calais

Вы помните, что в прошлый раз, когда мы использовали DoverToCalais, это было в простом формате XML, и этого было достаточно для удовлетворения наших потребностей в тегировании. DoverToCalais также можно использовать с расширенным форматом JSON Output OpenCalais, который дает нам новый объем данных, в основном, отношения между сущностями.

При обработке данных в расширенном формате JSON DoverToCalais использует Redis для хранения модели данных, которые он обрабатывает. Следуйте инструкциям здесь и получите Redis и работает.

По умолчанию DoverToCalais будет использовать локальный экземпляр Redis 127.0.0.1 на порту 6379 с базой данных № 6 (без пароля). Если что-то из этого окажется неудобным, это можно легко изменить, изменив константу DoverToCalais :: REDIS .

Кроме того, еще раз, не забывайте, что DoverToCalais нуждается в работающей JRE для правильной работы.

Примечание: широкие возможности анализа данных доступны только в версии DoverToCalais v0.2.1, поэтому убедитесь, что у вас установлена ​​последняя версия!

Что нового Pussycat?

Как сказал бы Том Джонс, основное различие в использовании DoverToCalais при использовании расширенного вывода состоит в том, что больше нет необходимости выполнять наш анализ ответа в обратном вызове (метод #to_calais ). Обратный вызов теперь служит только для того, чтобы сообщить нам, когда ответ был обработан. Как только обратный вызов возвращается, мы знаем, что можем найти все наши исходные данные, хорошо смоделированные в Redis, и можем получить к ним доступ независимо от нашего EventMachine цикла создания-> анализа-> обратного вызова .

Единственное другое отличие состоит в том, что нам нужно передать символ : rich в наш метод #analyze_this . DoverToCalais сделает все остальное.

Модель

Нет, не классический трек Kraftwerk, глупый! Это модель данных DoverToCalais, ряд объектов модели Ohm, находящихся в хранилище данных Redis. Эти типы объектов будут созданы после того, как DoverToCalais обработает источник данных.

DoverToCalais :: EntityModel имеет следующие атрибуты

  • name — имя объекта, например, Кларк Кент, Стадион Миллениум и т. д.
  • type — тип объекта, например, Person, Location и т. д.
  • calais_id — уникальный идентификатор, назначенный OpenCalais
  • отношения — совокупность родовых отношений, связанных с сущностью
  • события — набор событий, связанных с объектом

DoverToCalais :: EntityModel :: RelationModel имеет следующие атрибуты

  • субъект — субъект, применяющий действие
  • глагол — действие
  • объект — субъект, получающий действие
  • обнаружение — текст, который отражает сущность отношения
  • calais_id — уникальный идентификатор, назначенный OpenCalais

DoverToCalais :: EntityModel :: EventModel имеет следующие атрибуты

  • calais_id — уникальный идентификатор, назначенный OpenCalais
  • Хэш информации — хэш, созданный на лету, включающий атрибуты и значения события. Поскольку количество атрибутов зависит от типа события (например, у MilitaryAction будут очень разные атрибуты для MovieRelease), информационный хеш — хороший способ динамически инкапсулировать атрибуты события.

Возвращение Коннора

Помните Коннора ? Ну, с тех пор, как он преуспел в своем последнем назначении, его репутация в офисе стала «Мистер анализа данных»! Его коллега Дебби, журналист-расследователь, приходит к нему с проблемой:

«Ходят слухи о том, что в жилищном управлении Олдервуда происходят финансовые нарушения и что каким-то образом мэр замешан в этом. Но у меня нет никаких указаний на это, поэтому не знаю, с чего начать. Черт, я даже не знаю, кто такой мэр Олдервуда! У вас есть данные и навыки, Коннор — вы можете помочь?

«Конечно!» — шутит Коннор и достает своего верного редактора. «Первое, что нужно сделать, это проанализировать данные. Я подозреваю, что нам понадобятся богатые возможности анализа! »

 1  require 'dover_to_calais'
2  require 'em/throttled_queue'
3
4  DoverToCalais::flushdb
5   
6  EM.run do
7    # use Control + C to stop the EM
8    Signal.trap('INT')  { EventMachine.stop }
9    Signal.trap('TERM') { EventMachine.stop }
10  
11   DoverToCalais::API_KEY =  'my-opencalais-api-key'
12   data_dir = '/home/connor/data/Alderwood_News/'
13       
14   total_files = Dir[File.join(data_dir, '**', '*')].count { |file| File.file?(file) }
15   queue = EM::ThrottledQueue.new(2, 1)
16
17   dovers = []
18   Dir.foreach(data_dir) do |filename|
19     next if filename == '.' or filename == '..'
20     dover = DoverToCalais::Dover.new(data_dir + filename) 
21     dovers << dover
22     # push the dover on our throttled queue as well
23     queue.push(dover)
24   end
25
26   count = 0
27        
28   dovers.each do |dover|
29     dover.to_calais do |response|
30       if response.error
31         puts "*** Data source #{dover.data_src} error: #{response}"
32       else
33        count += 1
34        puts "finished #{count}"
35        puts "all done!" if (count >= total_files)
36       
37       end #if
38     end #block
39        
40     # because we told the queue to pop a maximum of two dovers per second
41     # we're not exceeding the OpenCalais limit so we'll get no errors
42     dovers.length.times { queue.pop  { |dover| dover.analyze_this(:rich)} }
43   end #each    
44 end

«Это похоже на то, что вы делали в первый раз», — говорит Дебби. «Довольно», — отвечает Коннор. «Единственное отличие состоит в том, что я получаю общее количество файлов для обработки (строка № 14), а затем увеличиваю счетчик (строка № 33) каждый раз, когда файл анализируется. Когда мой счетчик достигает общего значения, я знаю, что все было обработано, поэтому DoverToCalais создал свою модель данных, и я могу начать анализировать данные. О, и посмотри, как я передаю аргумент для анализа — это тоже! »

«Я вижу, — кивает Дебби, — но что происходит в строке № 4»? «О, это, — говорит Коннор, — это то, что мне не нужно было делать. Просто каждый раз, когда вы что-то анализируете с помощью DoverToCalais, он добавляется в одно и то же хранилище данных. Мне нравится начинать с чистого листа, поэтому я сказал DoverToCalais очистить хранилище данных, вот и все ».

«Теперь давайте посмотрим, что во всех этих данных!»

Дебби детектив данных

Коннор создает новый файл:

 1  require 'dover_to_calais'
2 
3  Ohm.redis = Redis.new(DoverToCalais::REDIS)

«Отныне нет ничего особенного в том, что мы делаем», — говорит Коннор. «Мы просто манипулируем стандартными объектами Arrays, Hashes и Ohm . Во-первых, давайте выясним, кто этот мэр.

 4  all_events = DoverToCalais::EntityModel::EventModel.all.to_a
5  mayors = all_events.select {|v| /[Mm]ayor/.match(v.info_hash['position'].to_s)
6    
7  mayors.each do |event|
8    puts event.info_hash
9  end

«Вау», кричит Дебби, когда код запускается. «Слишком много мэров и слишком много городов! Можем ли мы отфильтровать немного больше? »« Конечно », — отвечает Коннор:

 5  mayors = all_events.select {|v| /[Mm]ayor/.match(v.info_hash['position'].to_s) &&
6                            /[Aa]lderwood/.match(v.info_hash['city'].to_s) && 
7                            /current/.match(v.info_hash['status'].to_s) }
8    
9  mayors.each do |event|
10    puts event.info_hash
11 end

«Это лучше», восклицает Дебби. «Я думаю, мы можем с уверенностью предположить, что Рекс Лютор является мэром Олдервуда. Давайте посмотрим, что мы можем найти на Рексе. Могу ли я водить машину? »С этими словами Дебби хватает клавиатуру и печатает:

 12  a_set = DoverToCalais::EntityModel.find(name: "Rex Luthor")
13  if a_set.size == 1
14    rex = a_set.first
15    rex.relations.each do |r|
16      puts "#{r.subject['name']} -- #{r.verb} -- #{r.object['name']} --    #{r.detection}"
17    end
18  else
19    puts "oh-oh, more than one Rex Luthors!"
20  end

«Посмотри на эту последнюю строчку», — кричит Дебби. «Похоже, мэр подтолкнул этого парня из Гонсалеса к назначению в Жилищное управление». «Вы правы, — говорит Коннор, — но сначала позвольте мне немного улучшить форматирование, это ранит мои глаза». Коннор быстро устанавливает гем tabularize , добавляет require 'tabularize'

 12  a_set = DoverToCalais::EntityModel.find(name: "Rex Luthor")
13   if a_set.size == 1
14    rex = a_set.first
15
16    table = Tabularize.new
17    table << %w[Subject Verb Object Detection]
18    table.separator!
19
20    rex.relations.each do |r|
21         table << ["#{r.subject['name']}", 
22           "#{r.verb}",  
23          "#{r.object['name']}", 
24          "#{r.detection}" ]
25    end
26    puts table
27  else
28    puts "oh-oh, more than one Rex Luthors!"
29  end

«Это выглядит готовым к печати», — говорит Дебби, — «и я также нашла недостающее звено, ведущую, которая связывает мэра с Управлением жилищного строительства. Я уверен, что если я буду использовать те же методы для расследования этого парня, я приду к нему массу информации! Спасибо, Коннор, и я буду покупать тебе ужин сегодня вечером.

Вывод

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