Python使用Unicode参数请求URL

2024-05-13 18:30:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我目前正在尝试使用请求库用python中的日语字符和短语点击google tts url,http://translate.google.com/translate_tts

下面是一个例子:

http://translate.google.com/translate_tts?tl=ja&q=

但是,当我尝试使用python请求库下载端点返回的mp3时,得到的mp3是空的。我已经验证了我可以在使用非unicode字符(通过romanji)的请求中点击这个URL,并且得到了正确的响应。

这是我用来提出请求的代码的一部分

langs = {'japanese': 'ja',
         'english': 'en'}

def get_sound_file_for_text(text, download=False, lang='japanese'):

    r = StringIO()
    glang = langs[lang]
    text = text.replace('*', '')
    text = text.replace('/', '')
    text = text.replace('x', '')
    url = 'http://translate.google.com/translate_tts'
    if download:
        result = requests.get(url, params={'tl': glang, 'q': text})
        r.write(result.content)
        r.seek(0)
        return r
    else:
        return url

另外,如果我在这个片段中打印texturl,则在控制台中正确呈现假名/汉字。

编辑:

如果我尝试对unicode编码并引用它,我仍然得到相同的响应。

# -*- coding: utf-8 -*-

from StringIO import StringIO
import urllib
import requests

__author__ = 'jacob'

langs = {'japanese': 'ja',
         'english': 'en'}

def get_sound_file_for_text(text, download=False, lang='japanese'):

    r = StringIO()
    glang = langs[lang]
    text = text.replace('*', '')
    text = text.replace('/', '')
    text = text.replace('x', '')
    text = urllib.quote(text.encode('utf-8'))
    url = 'http://translate.google.com/translate_tts?tl=%(glang)s&q=%(text)s' % locals()
    print url
    if download:
        result = requests.get(url)
        r.write(result.content)
        r.seek(0)
        return r
    else:
        return url

它返回:

http://translate.google.com/translate_tts?tl=ja&q=%E3%81%B2%E3%81%A8%E3%81%A4

看起来应该有用,但没有

编辑2:

如果尝试使用urllb/urllib2,则会出现403错误。

编辑3:

因此,这个问题/行为似乎仅仅局限于这个端点。如果我尝试以下URL,则使用其他终结点。

http://www.kanjidamage.com/kanji/13-un-%E4%B8%8D

从请求和浏览器中,我得到相同的响应(它们匹配)。如果我在服务器上尝试使用ascii字符,比如这个url。

http://translate.google.com/translate_tts?tl=ja&q=sayonara

我也得到了同样的回应(他们再次匹配)。但如果我尝试将unicode字符发送到这个URL,我会在浏览器上得到一个正确的音频文件,但不是来自发送音频文件但没有声音的请求。

http://translate.google.com/translate_tts?tl=ja&q=%E3%81%B2%E3%81%A8%E3%81%A4

所以,这种行为似乎仅限于Google TTL的URL?


Tags: textcomhttpurlgetgoogle字符replace
3条回答

将用户代理设置为Mozilla/5.0可以解决此问题。

from StringIO import StringIO
import urllib
import requests

__author__ = 'jacob'

langs = {'japanese': 'ja',
         'english': 'en'}

def get_sound_file_for_text(text, download=False, lang='japanese'):

    r = StringIO()
    glang = langs[lang]
    text = text.replace('*', '')
    text = text.replace('/', '')
    text = text.replace('x', '')
    url = 'http://translate.google.com/translate_tts'
    if download:
        result = requests.get(url, params={'tl': glang, 'q': text}, headers={'User-Agent': 'Mozilla/5.0'})
        r.write(result.content)
        r.seek(0)
        return r
    else:
        return url

我以前做过这个小方法来帮助我进行UTF-8编码。我在向CSV打印西里尔文和中日韩文时遇到问题,这就成功了。

def assist(unicode_string):
    utf8 = unicode_string.encode('utf-8')
    read = utf8.decode('string_escape')

    return read   ## UTF-8 encoded string

另外,确保在.py的开头有这两行代码。

#!/usr/bin/python
# -*- coding: utf-8 -*-

第一行只是一个很好的python习惯,它指定在.py上使用哪个编译器(只有在机器上加载了多个python版本时才真正有用)。第二行指定python文件的编码。对此给出了一个稍长的答案here

用户代理可能是问题的一部分,但在本例中不是这样。translate_tts服务拒绝(使用HTTP 403)某些用户代理,例如以Pythoncurlwget开头的任何用户代理,以及可能的其他用户代理。这就是为什么在使用urllib2.urlopen()时会看到HTTP 403响应-它将用户代理设置为Python-urllib/2.7(版本可能会有所不同)。

您发现将用户代理设置为Mozilla/5.0修复了该问题,但这可能会起作用,因为API可能假定基于用户代理的特定编码。

实际应该做的是用ie字段显式指定URL字符编码。您的URL请求应如下所示:

http://translate.google.com/translate_tts?ie=UTF-8&tl=ja&q=%E3%81%B2%E3%81%A8%E3%81%A4

注意ie=UTF-8,它显式地设置URL字符编码。规范确实声明了UTF-8是默认的,但看起来并不完全正确,因此您应该始终在请求中设置ie

API支持汉字、平假名和片假名(可能是其他的?)。这些url都会产生“nihongo”,尽管为平假名输入而产生的音频与其他的略有不同。

import requests

one = u'\u3072\u3068\u3064'
kanji = u'\u65e5\u672c\u8a9e'
hiragana = u'\u306b\u307b\u3093\u3054'
katakana = u'\u30cb\u30db\u30f3\u30b4'
url = 'http://translate.google.com/translate_tts'

for text in one, kanji, hiragana, katakana:
    r = requests.get(url, params={'ie': 'UTF-8', 'tl': 'ja', 'q': text})
    print u"{} -> {}".format(text, r.url)
    open(u'/tmp/{}.mp3'.format(text), 'wb').write(r.content)

相关问题 更多 >