我正在尝试使用 feedparser 解析 RSS 提要,并使用 SQLAlchemy 将其插入到 mySQL 表中。我实际上能够正常运行,但今天提要的描述中有一个带有省略号字符的项目,我收到以下错误:
UnicodeEncodeError: 'latin-1' codec can't encode character u'\u2026' in position 35: ordinal not in range(256)
如果我将 convert_unicode=True 选项添加到引擎,我可以让插入通过,但省略号不会显示,它只是奇怪的字符。这似乎是有道理的,因为据我所知,latin-1 中没有水平省略号。即使我将编码设置为 utf-8,它似乎也没有什么不同。如果我使用 phpmyadmin 进行插入并包含省略号,则可以正常使用。
我想我只是不了解字符编码或如何让 SQLAlchemy 使用我指定的编码。有谁知道如何让文本进入没有奇怪的字符?
更新
我想我已经解决了这个问题,但我不确定为什么它很重要......
代码如下:
import sys
import feedparser
import sqlalchemy
from sqlalchemy import create_engine, MetaData, Table
COMMON_CHANNEL_PROPERTIES = [
('Channel title:','title', None),
('Channel description:', 'description', 100),
('Channel URL:', 'link', None),
]
COMMON_ITEM_PROPERTIES = [
('Item title:', 'title', None),
('Item description:', 'description', 100),
('Item URL:', 'link', None),
]
INDENT = u' '*4
def feedinfo(url, output=sys.stdout):
feed_data = feedparser.parse(url)
channel, items = feed_data.feed, feed_data.entries
#adding charset=utf8 here is what fixed the problem
db = create_engine('mysql://user:pass@localhost/db?charset=utf8')
metadata = MetaData(db)
rssItems = Table('rss_items', metadata,autoload=True)
i = rssItems.insert();
for label, prop, trunc in COMMON_CHANNEL_PROPERTIES:
value = channel[prop]
if trunc:
value = value[:trunc] + u'...'
print >> output, label, value
print >> output
print >> output, "Feed items:"
for item in items:
i.execute({'title':item['title'], 'description': item['description'][:100]})
for label, prop, trunc in COMMON_ITEM_PROPERTIES:
value = item[prop]
if trunc:
value = value[:trunc] + u'...'
print >> output, INDENT, label, value
print >> output, INDENT, u'---'
return
if __name__=="__main__":
url = sys.argv[1]
feedinfo(url)
这是在不使用字符集选项的情况下运行代码的输出/回溯:
Channel title: [H]ardOCP News/Article Feed
Channel description: News/Article Feed for [H]ardOCP...
Channel URL: http://www.hardocp.com
Feed items:
Item title: Windows 8 UI is Dropping the 'Start' Button
Item description: After 15 years of occupying a place of honor on the desktop, the "Start" button will disappear from ...
Item URL: http://www.hardocp.com/news/2012/02/05/windows_8_ui_dropping_lsquostartrsquo_button/
---
Item title: Which Crashes More? Apple Apps or Android Apps
Item description: A new study of smartphone apps between Android and Apple conducted over a two month period came up w...
Item URL: http://www.hardocp.com/news/2012/02/05/which_crashes_more63_apple_apps_or_android/
---
Traceback (most recent call last):
File "parse.py", line 47, in <module>
feedinfo(url)
File "parse.py", line 36, in feedinfo
i.execute({'title':item['title'], 'description': item['description'][:100]})
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/sql/expression.py", line 2758, in execute
return e._execute_clauseelement(self, multiparams, params)
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 2304, in _execute_clauseelement
return connection._execute_clauseelement(elem, multiparams, params)
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1538, in _execute_clauseelement
compiled_sql, distilled_params
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1639, in _execute_context
context)
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/default.py", line 330, in do_execute
cursor.execute(statement, parameters)
File "build/bdist.linux-i686/egg/MySQLdb/cursors.py", line 159, in execute
File "build/bdist.linux-i686/egg/MySQLdb/connections.py", line 264, in literal
File "build/bdist.linux-i686/egg/MySQLdb/connections.py", line 202, in unicode_literal
UnicodeEncodeError: 'latin-1' codec can't encode character u'\u2026' in position 35: ordinal not in range(256)
所以看起来像将字符集添加到 mysql 连接字符串就可以了。我想它默认为latin-1?我曾尝试将 content_engine 上的编码标志设置为 utf8,但什么也没做。任何人都知道当表和字段设置为 utf8 unicode 时为什么会使用 latin-1?我还尝试在发送之前使用 .encode('cp1252') 对 item['description] 进行编码,即使没有将 charset 选项添加到连接字符串,它也能正常工作。那不应该与 latin-1 一起使用,但显然它确实有效?我有解决方案,但希望得到答案:)
最佳答案
错误信息
UnicodeEncodeError: 'latin-1' codec can't encode character u'\u2026'
in position 35: ordinal not in range(256)
似乎表明某些 Python 语言代码正在尝试将字符 \u2026 转换为 Latin-1 (ISO8859-1) 字符串,但它失败了。毫不奇怪,那个字符是 U+2026 HORIZONTAL ELLIPSIS ,在 ISO8859-1 中没有单个等效字符。
您通过在 SQLAlchemy 连接调用中添加查询 ?charset=utf8 解决了问题:
import sqlalchemy
from sqlalchemy import create_engine, MetaData, Table
db = create_engine('mysql://user:pass@localhost/db?charset=utf8')
该部分Database Urls的 SQLAlchemy 文档告诉我们,以 mysql 开头的 URL 表示使用 mysql-python 驱动程序的 MySQL 方言。
以下部分,Custom DBAPI connect() arguments , 告诉我们查询参数被传递给底层 DBAPI。
那么,mysql-python 是什么意思?参数 {charset: 'utf8'} 的驱动程序?栏目Functions and attributes他们的文档中提到了 charset 属性“......如果存在,如果它们不相等,则连接字符集将更改为此字符集。”
要找出连接字符集的含义,我们求助于 10.1.4. Connection Character Sets and Collations MySQL 5.6 引用手册。长话短说,MySQL 可以将传入查询解释为不同于数据库字符集的编码,也不同于返回查询结果的编码。
由于您报告的错误消息看起来像 Python 而不是 SQL 错误消息,我推测 SQLAlchemy 或 mysql-python 中的某些内容正在尝试将查询转换为 latin-1 的默认连接编码 在发送之前。这就是触发错误的原因。但是,connect() 调用中的查询字符串 ?charset=utf8 会更改连接编码,并且 U+2026 HORIZONTAL ELLIPSIS 能够打通。
更新:您还问,“如果我删除 charset 选项,然后使用 .encode('cp1252') 对描述进行编码,它将顺利通过。省略号如何获得通过 cp1252 但不是 unicode?”
encoding cp1252 has字节值 \x85 处的水平省略号字符。因此,可以将包含 U+2026 HORIZONTAL ELLIPSIS 的 Unicode 字符串编码为 cp1252 而不会出错。
还要记住,在 Python 中,Unicode 字符串和字节字符串是两种不同的数据类型。推测 MySQLdb 可能具有通过 SQL 连接仅发送字节字符串的策略是合理的。因此,它会将作为 Unicode 字符串接收的查询编码为字节字符串,但会将作为字节字符串接收的查询单独留下。 (这是推测,我没有看源码。)
在您发布的回溯中,最后两行(最接近错误发生的位置)显示方法名称 literal,然后是 unicode_literal。这倾向于支持 MySQLdb 将它作为 Unicode 字符串接收的查询编码为字节字符串的理论。
当您自己编码查询字符串时,您绕过了 MySQLdb 中以不同方式执行此编码的部分。但是请注意,如果您对查询字符串进行编码与 MySQL 连接字符集所要求的不同,那么您将遇到编码不匹配,并且您的文本可能会被错误地存储。
关于python - 如何让 SQLAlchemy 正确地将 unicode 省略号插入到 mySQL 表中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9155264/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
在我的Rails(2.3,Ruby1.8.7)应用程序中,我需要将字符串截断到一定长度。该字符串是unicode,在控制台中运行测试时,例如'א'.length,我意识到返回了双倍长度。我想要一个与编码无关的长度,以便对unicode字符串或latin1编码字符串进行相同的截断。我已经了解了Ruby的大部分unicode资料,但仍然有些一头雾水。应该如何解决这个问题? 最佳答案 Rails有一个返回多字节字符的mb_chars方法。试试unicode_string.mb_chars.slice(0,50)
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为