Извлечение отдельных существующих слов в доменные имена - PullRequest
1 голос
/ 30 ноября 2010

Я ищу рубиновый драгоценный камень (желательно), который разрезал бы доменные имена на их слова.

whatwomenwant.com => 3 words, "what", "women", "want".

Если он может игнорировать такие вещи, как числа и тарабарщины, тогда прекрасно.

Ответы [ 3 ]

3 голосов
/ 30 ноября 2010

Вам понадобится список слов , например, составленный Project Gutenberg или доступный в источнике для ispell & c.Затем вы можете использовать следующий код для разложения домена на слова:

WORD_LIST = [
  'experts',
  'expert',
  'exchange',
  'sex',
  'change',
]

def words_that_phrase_begins_with(phrase)
  WORD_LIST.find_all do |word|
    phrase.start_with?(word)
  end
end

def phrase_to_words(phrase, words = [], word_list = [])
  if phrase.empty?
    word_list << words
  else
    words_that_phrase_begins_with(phrase).each do |word|
      remainder = phrase[word.size..-1]
      phrase_to_words(remainder, words + [word], word_list)
    end
  end
  word_list
end

p phrase_to_words('expertsexchange')
# => [["experts", "exchange"], ["expert", "sex", "change"]]

Если задана фраза с нераспознанными словами, она возвращает пустой массив:

p phrase_to_words('expertsfoo')
# => []

Если список слов длинный, это будет медленно.Вы можете сделать этот алгоритм быстрее, предварительно обработав список слов в дереве.Сама предварительная обработка займет время, поэтому, стоит ли оно того, зависит от того, сколько доменов вы хотите протестировать.

Вот некоторый код для преобразования списка слов в дерево:

def add_word_to_tree(tree, word)
  first_letter = word[0..0].to_sym
  remainder = word[1..-1]
  tree[first_letter] ||= {}
  if remainder.empty?
    tree[first_letter][:word] = true
  else
    add_word_to_tree(tree[first_letter], remainder)
  end
end

def make_word_tree
  root = {}
  WORD_LIST.each do |word|
    add_word_to_tree(root, word)
  end
  root
end

def word_tree
  @word_tree ||= make_word_tree
end

Это создает дерево, которое выглядит следующим образом:

{: c => {: h => {: a => {: n => {: g => {: e => {: word =>true}}}}}},: s => {: e => {: x => {: word => true}}},: e => {: x => {: c => {: h => {: a => {: n => {: g => {: e => {: word => true}}}}}},: p => {: e => {: r => {:t => {: word => true,: s => {: word => true}}}}}}}}

Похоже на Лисп, не так ли?Каждый узел в дереве является хешем.Каждый ключ хеша является либо буквой, значение которой является другим узлом, либо символом: слово со значением true.Узлы с: word - это слова.

Изменение words_that_phrase_begins_with для использования новой древовидной структуры сделает его быстрее:

def words_that_phrase_begins_with(phrase)
  node = word_tree
  words = []
  phrase.each_char.with_index do |c, i|
    node = node[c.to_sym]
    break if node.nil?
    words << phrase[0..i] if node[:word]
  end
  words
end
1 голос
/ 01 декабря 2010

Обновление


Я работал с этой проблемой и придумал следующий код. Пожалуйста, рефакторинг, если я делаю что-то не так: -)

Benchmark:


Продолжительность: 11 сек.
f-файл: 13.000 строк доменных имен
w-файл: 2000 слов (для проверки)

Код:


f           = File.open('resource/domainlist.txt', 'r')
lines       = f.readlines
w           = File.open('resource/commonwords.txt', 'r')
words       = w.readlines

results  = {}

lines.each do |line|
  # Start with words from 2 letters on, so ignoring 1 letter words like 'a'
  word_size = 2
  # Only get the .com domains
  if line =~ /^.*,[a-z]+\.com.*$/i then
    # Strip the .com off the domain
    line.gsub!(/^.*,([a-z]+)\.com.*$/i, '\\1')
    # If the domain name is between 3 and 12 characters
    if line.size > 3 and line.size < 15 then
      # For the length of the string run ...
      line.size.times do |n|
        # Set the counter
        i = 0
        # As long as we're within the length of the string
        while i <= line.size - word_size do
          # Get the word in proper DRY fashion
          word = line[i,word_size]
          # Check the word against our list
          if words.include?(word) 
            results[line] = [] unless results[line]
            # Add all the found words to the hash
            results[line] << word
          end
          i += 1
        end
        word_size += 1
      end
    end
  end
end
p results
1 голос
/ 30 ноября 2010

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

Если у вас есть несколько вариантов деления букв (как в expertsexchange ) в sepp2k, у вас может быть два совета:

  1. Ваш словарь отсортирован по ... например, популярности слова . Таким образом, разделение с наиболее популярными словами будет более ценным.
  2. Вы можете перейти на главную страницу сайта с доменом, который вы аназилинге, и просто прочитать контент, выполнив поиск по вашим словам. Я не думаю, что вы найдете sex на странице для некоторых экспертов. Но ... хм ... эксперты могут быть такими разными.)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...