我正在寻找一种简单的方法来检测一段简短的文本摘录,几句话,是否是英语。在我看来,这个问题比尝试检测任意语言要容易得多。有没有什么软件可以做到这一点?我正在用 python 编写,并且更喜欢 python 库,但其他东西也可以。我试过谷歌,但后来意识到 TOS 不允许自动查询。
5 回答
编辑:这在这种情况下不起作用,因为 OP 正在批量处理违反 Google 服务条款的文本。
使用谷歌翻译语言检测 API。文档中的 Python 示例:
url = ('https://ajax.googleapis.com/ajax/services/language/detect?' +
'v=1.0&q=Hola,%20mi%20amigo!&key=INSERT-YOUR-KEY&userip=INSERT-USER-IP')
request = urllib2.Request(url, None, {'Referer': /* Enter the URL of your site here */})
response = urllib2.urlopen(request)
results = simplejson.load(response)
if results['responseData']['language'] == 'en':
print 'English detected'
虽然不如谷歌自己的好,但我使用 Apache Nutch LanguageIdentifier 获得了很好的结果,它带有自己的预训练 ngram 模型。我在多种语言的大型(50GB pdf,主要是文本)真实世界数据语料库中取得了相当不错的结果。
它是用 Java 编写的,但如果你想用 Python 重新实现它,我相信你可以从中重新读取 ngram 配置文件。
Google Translate API v2 允许自动查询,但它需要使用您可以在Google API 控制台上免费获得的 API 密钥。
要检测文本是否为英语,您可以使用我对Pythondetect_language_v2()
问题的回答中的函数(使用该 API) - 我可以检测 unicode 字符串语言代码吗?:
if all(lang == 'en' for lang in detect_language_v2(['some text', 'more text'])):
# all text fragments are in English
我最近为此写了一个解决方案。我的解决方案不是万无一失的,我认为它对于大量文本在计算上是不可行的,但在我看来,它适用于小句子。
假设您有两个文本字符串:
- “让我们先说谢谢”
- “UNGHSYINDJFHAKJSNFNDKUAJUD”
然后目标是确定 1. 可能是英语,而 2. 不是。直观地说,我的大脑决定这一点的方式是寻找句子中英语单词的单词边界(LET、ME、BEGIN 等)。但这在计算上并不简单,因为存在重叠的单词(BE、GIN、BEGIN、SAY、SAYING、THANK、THANKS 等)。
我的方法执行以下操作:
{ known English words }
取和的交点{ all substrings of the text of all lengths }
。- 构造一个顶点图,其位置是句子中单词的起始索引,有向边指向单词结尾后字母的起始位置。例如,
(0)
将是L
,所以“LET”可以表示为(0) -> (3)
,其中(3)
是M
“LET ME”。 n
找到0 到 0 之间len(text)
存在从索引 0 到索引 的简单有向路径的最大整数n
。- 将该数字除以
n
文本的长度,粗略了解文本中有多少百分比是连续的英文单词。
请注意,我的代码假定单词之间没有空格。如果您已经有空格,那么我的方法很愚蠢,因为我的解决方案的核心是弄清楚空格应该在哪里。(如果您正在阅读本文并且有空格,那么您可能正在尝试解决更复杂的问题。)。此外,要使我的代码正常工作,您需要一个英文单词表文件。我从这里得到了一个,但是你可以使用任何这样的文件,我想通过这种方式,这种技术也可以扩展到其他语言。
这是代码:
from collections import defaultdict
# This function tests what percent of the string seems to me to be maybe
# English-language
# We use an English words list from here:
# https://github.com/first20hours/google-10000-english
def englishness(maybeplaintext):
maybeplaintext = maybeplaintext.lower()
f = open('words.txt', 'r')
words = f.read()
f.close()
words = words.lower().split("\n")
letters = [c for c in maybeplaintext]
# Now let's iterate over letters and look for some English!
wordGraph = defaultdict(list)
lt = len(maybeplaintext)
for start in range(0, lt):
st = lt - start
if st > 1:
for length in range(2, st):
end = start + length
possibleWord = maybeplaintext[start:end]
if possibleWord in words:
if not start in wordGraph:
wordGraph[start] = []
wordGraph[start].append(end)
# Ok, now we have a big graph of words.
# What is the shortest path from the first letter to the last letter,
# moving exclusively through the English language?
# Does any such path exist?
englishness = 0
values = set([a for sublist in list(wordGraph.values()) for a in sublist])
numberVertices = len(set(wordGraph.keys()).union(values))
for i in range(2, lt):
if isReachable(numberVertices, wordGraph, i):
englishness = i
return englishness/lt
# Here I use my modified version of the technique from:
# https://www.geeksforgeeks.org/
# find-if-there-is-a-path-between-two-vertices-in-a-given-graph/
def isReachable(numberVertices, wordGraph, end):
visited = [0]
queue = [0]
while queue:
n = queue.pop(0)
if n == end or n > end:
return True
for i in wordGraph[n]:
if not i in visited:
queue.append(i)
visited.append(i)
return False
这是I/O
我给出的初始示例:
In [5]: englishness('LETMEBEGINBYSAYINGTHANKS')
Out[5]: 0.9583333333333334
In [6]: englishness('UNGHSYINDJFHAKJSNFNDKUAJUD')
Out[6]: 0.07692307692307693
所以大致来说,我 96% 确定那LETMEBEGINBYSAYINGTHANKS
是英语,8% 确定那UNGHSYINDJFHAKJSNFNDKUAJUD
是英语。这听起来是对的!
要将其扩展到更大的文本,我的建议是对随机短子字符串进行二次抽样并检查它们的“英语”。希望这可以帮助!