Python: кодек 'ascii' не может закодировать символ u '\\ u2026' - PullRequest
2 голосов
/ 06 февраля 2011

Я пытаюсь использовать API Bing в Python со следующим кодом:

#!/usr/bin/python
from bingapi import bingapi  
import re
import json
import urllib
import cgi
import cgitb
from HTMLParser import HTMLParser

class MLStripper(HTMLParser):
    def __init__(self):
            self.reset()
            self.fed = []
    def handle_data(self, d):
            self.fed.append(d)
    def get_data(self):
            return ''.join(self.fed)

def strip_tags(html):
    s = MLStripper()
    s.feed(html)
    return s.get_data()

def strip_tags2(data):
    p = re.compile(r'<[^<]*?>')
    q = re.compile(r'[&;!@#$%^*()]*')
    data = p.sub('', data)
    return q.sub('', data)

def getUrl(item):
    return item['Url']

def getContent(item):
    return item['Description']

def getTitle(item):
    return item['Title']

def getInfo(qry, siteStr):
    qryStr = qry + "+" + siteStr
    #qryStr = u"%s" % qryStr.encode('UTF-8')
    query = urllib.urlencode({'q' : qryStr})
    url = 'http://api.bing.net/json.aspx?Appid=<myappid>&Version=2.2&Market=en-US&Query=%s&Sources=web&Web.Count=10&JsonType=raw' % (query)
    search_results = urllib.urlopen(url)
    j = json.loads(search_results.read())
    results = j['SearchResponse']['Web']['Results']
    return results

def updateRecent(qry):
    f = open("recent.txt", "r")
    lines = f.readlines()
    f.close()
    lines = lines[1:]

    if len(qry) > 50: #truncate if string too long
            qry = (qry[:50] + '...')
    qry = strip_tags2(qry) #strip out the html if injection try

    lines.append("\n%s" % qry)
    f = open("recent.txt", "w")
    f.writelines(lines)
    f.close()

if __name__ == '__main__':
    form = cgi.FieldStorage()
    qry = form["qry"].value
    qry = r'%s' % qry

    updateRecent(qry)

    siteStr = "(site:answers.yahoo.com OR site:chacha.com OR site:blurtit.com OR site:answers.com OR site:question.com OR site:answerbag.com OR site:stackexchange.com)"

    print "Content-type: text/html"
    print

    header = open("header.html", "r")
    contents = header.readlines()
    header.close()
    for item in contents:
            print item

    print """
    <div id="results">
    <center><h1>Results:</h1></center>
    """
    for item in getInfo(siteStr, qry):
            print "<h3>%s</h3>" % getTitle(item)
            print "<br />"
            print "%s" % getUrl(item)
            print "<br />"
            print "<p style=\"color:gray\">%s</p>" % getContent(item)
            print "<br />"
    print "</div>"

    footer = open("footer.html", "r")
    contents = footer.readlines()
    footer.close()
    for thing in contents:
            print thing

Я печатаю несколько результатов, а затем выдает следующую ошибку:

UnicodeEncodeError: 'ascii' codec can't encode character u'\\u2026' in position 72:    ordinal not in range(128)

Может кто-нибудь объяснить, почему это происходит?Это явно связано с тем, как URL кодируется, но что именно не так?Заранее спасибо!

Ответы [ 2 ]

3 голосов
/ 06 февраля 2011

Этот конкретный символ Unicode - "ГОРИЗОНТАЛЬНЫЙ ЭЛЛИПСИС".Одна или несколько ваших функций getXXXXX () возвращают строки Unicode, одна из которых содержит не-ASCII символ.Я предлагаю объявить кодировку вашего вывода, например:

Content-Type: text/html; charset=utf-8

и явно кодировать ваш вывод в этой кодировке.

2 голосов
/ 06 февраля 2011

Нам нужно знать номер строки, в которой было сгенерировано исключение, оно будет в обратной трассировке. В любом случае, проблема в том, что вы читаете юникод из файлов / URL-адресов и затем неявно преобразуете их в US-ASCII, возможно, в одну из операций конкатенации. Вы должны поставить перед всеми константными строками префикс u, чтобы указать, что они являются строками Юникода, как в

u"\n%s" % qry
...