【问题标题】:Python url string matchPython url 字符串匹配
【发布时间】:2013-03-13 08:26:08
【问题描述】:

我的问题如下。我有一长串 URL,例如:

www.foo.com/davidbobmike1joe
www.foo.com/mikejoe2bobkarl
www.foo.com/joemikebob
www.foo.com/bobjoe

我需要将该列表中的所有条目(URL)相互比较,提取这些 URL 的子域中的关键字(在本例中:david、joe、bob、mike、karl)并按频率对它们进行排序。我一直在阅读有关 nltk 等几个库的信息。然而,这里的问题是没有空格来独立标记每个单词。有关如何完成工作的任何建议?

【问题讨论】:

  • 为什么不用空格,然后用BASE64转换呢?
  • 没有分隔符或关键字,几乎不可能分隔单词,你不能让机器随意猜测你想如何分割文本:/你需要某种上下文。
  • 你是对的。但是我认为这种情况有所不同,因为我可以将每个 URL 相互比较并确定哪些字符集更频繁地重复以提取这些关键字
  • 您仍然会遇到同样的问题:您使用多少个字母来确定一个单词? 3? 4? 10?您会尝试将字母数量增加一并遍历所有网址吗?您将匹配“mi”、“mik”、“mike”等,它们都是有效的匹配项。等等。我坚持认为,如果没有某种背景,这将很难实现。
  • 这似乎在今天很流行.... - 最后一个相关帖子:stackoverflow.com/questions/15364975/…

标签: python string-matching url-parsing


【解决方案1】:

限制

如果您拒绝使用字典,您的算法将需要大量计算。除此之外,不可能将只出现一次的关键字(例如:“karl”)与糟糕的序列(例如:“e2bo”)区分开来。我的解决方案将尽最大努力,并且仅当您的 URL 列表包含多次关键字时才有效。

基本思想

我假设一个单词是至少 3 个字符的频繁出现的字符序列。这可以防止字母“o”成为最流行的单词。

基本思路如下。

  • 计算所有 n 个字母序列并选择出现多次的那个。
  • 剪切属于较大序列一部分的所有序列。
  • 按受欢迎程度对它们进行排序,您就有了一个接近解决问题的解决方案。 (留给读者作为练习)

在代码中

import operator

sentences = ["davidbobmike1joe" , "mikejoe2bobkarl", "joemikebob", "bobjoe", "bobbyisawesome", "david", "bobbyjoe"];
dict = {}

def countWords(n):
    """Count all possible character sequences/words of length n occuring in all given sentences"""
    for sentence in sentences:
        countWordsSentence(sentence, n);

def countWordsSentence(sentence, n):
    """Count all possible character sequence/words of length n occuring in a sentence"""
    for i in range(0,len(sentence)-n+1):
        word = sentence[i:i+n]
        if word not in dict:
            dict[word] = 1;
        else:
            dict[word] = dict[word] +1;

def cropDictionary():
    """Removes all words that occur only once."""
    for key in dict.keys():
        if(dict[key]==1):
            dict.pop(key);

def removePartials(word):
    """Removes all the partial occurences of a given word from the dictionary."""
    for i in range(3,len(word)):
        for j in range(0,len(word)-i+1):
            for key in dict.keys():
               if key==word[j:j+i] and dict[key]==dict[word]:
                   dict.pop(key);

def removeAllPartials():
    """Removes all partial words in the dictionary"""
    for word in dict.keys():
        removePartials(word);

for i in range(3,max(map(lambda x: len(x), sentences))):
    countWords(i);
    cropDictionary();
    removeAllPartials();

print dict;

输出

>>> print dict;
{'mike': 3, 'bobby': 2, 'david': 2, 'joe': 5, 'bob': 6}

对读者的一些挑战

  • 在打印之前按值对字典进行排序。 (Sort a Python dictionary by value)
  • 在此示例中,“bob”出现了 6 次,其中 2 次是“bobby”的部分单词。确定这是否有问题并在必要时进行修复。
  • 考虑大小写。

【讨论】:

  • 建议:(1) 不要命名变量dict (2) 使用collections.defaultdict(int) 而不是dict() (3) 用分号代替。我将尝试代码并稍后 +1。有人必须这样做。
  • 这正是我想要的。非常感谢。我将尝试代码并提供更新
【解决方案2】:

概述

您可以使用此代码提取名称,并传入 [david、bob 等] 的列表:

Is there an easy way generate a probable list of words from an unspaced sentence in python?

然后使用collections.Counter 获取频率。

代码

from Bio import trie
import string
from collections import Counter


def get_trie(words):
    tr = trie.trie()
    for word in words:
        tr[word] = len(word)
    return tr

def get_trie_word(tr, s):
    for end in reversed(range(len(s))):
        word = s[:end + 1]
        if tr.has_key(word): 
            return word, s[end + 1: ]
    return None, s

def get_trie_words(s):
    names = ['david', 'bob', 'karl', 'joe', 'mike']
    tr = get_trie(names)
    while s:
        word, s = get_trie_word(tr, s)
        yield word

def main(urls):
    d = Counter()
    for url in urls:
        url = "".join(a for a in url if a in string.lowercase)
        for word in get_trie_words(url):
            d[word] += 1
    return d

if __name__ == '__main__':
    urls = [
        "davidbobmike1joe",
        "mikejoe2bobkarl",
        "joemikebob",
        "bobjoe",
    ]
    print main(urls)

结果

Counter({'bob': 4, 'joe': 4, 'mike': 3, 'karl': 1, 'david': 1})

【讨论】:

  • 嗨,问题是有大量的 URL,不可能创建一个先验关键字列表来匹配这些术语。
  • 哦,要是不用字典就更好了
  • 那么我不明白:您使用的任何库都会有某种方法来找出关键字,而字典似乎最有希望。如果排除字典(如我在这里使用的:stackoverflow.com/questions/15364975/…),您如何想象会生成关键字?
  • 你可以使用facebook名单,因为它很大,所以可以作为torrent使用。
猜你喜欢
  • 2011-03-22
  • 1970-01-01
  • 2016-06-09
  • 1970-01-01
  • 1970-01-01
  • 2020-05-26
  • 2021-08-25
  • 2020-11-13
  • 1970-01-01
相关资源
最近更新 更多