Rails 0mPG::Error: ERROR: невалидна последователност от байтове за UTF8 кодиране: 0xeda0bc

Получавам грешка, докато се опитвам да пиша на туитове в моята psql база данни.

Търсих в интернет високо и ниско (може би не достатъчно добре) за отговора, но без резултат. Разгледах отговорите тук - но предложението беше да преобразувам низа в UTF8 (въпреки че заглавките на отговора твърдят, че вече е UTF-8).

Направих го с този код:

# get the data from twitter
response = RestClient.get "http://search.twitter.com/search.json?rpp=100&since_id=238726971826253824&q=love"

# find the data encoding using CharDet
data = CharDet.detect(response.body)
encoding = data['encoding']

# create a new instance of Iconv with UTF-8 and then convert response.body
ic = Iconv.new('UTF-8//IGNORE', encoding)
converted_response = ic.iconv(response.body + '  ')[0..-2]

# take the data and convert it to JSON
response_json = ActiveSupport::JSON.decode(converted_response)


След това анализираме response_json и създаваме туитове отвътре навън база данни. Въпреки това, когато го правим, получаваме тази грешка по-долу.

  [4;36;1mSQL (0.1ms)[0m   [0;1mBEGIN[0m
  [4;35;1mSQL (0.0ms)[0m   [0mPG::Error: ERROR: invalid byte sequence for encoding "UTF8": 0xeda0bc
: INSERT INTO "tweets" ("from_user_id", "approved", "from_user", "has_profanity",    "twitter_search_id", "twitter_id", "posted_at", "updated_at", "iso_language_code", "profile_image_url", "text", "created_at", "archived", "geo", "to_user_id", "to_user", "metadata", "source", "event_id") VALUES(573857675, NULL, 'nataliekiro', NULL, 618, 238825898718162944, '2012-08-24 02:31:46.000000', '2012-08-24 02:32:05.166492', 'en', 'http://a0.twimg.com/profile_images/2341785780/image_normal.jpg', 'Happy Birthday @daughternumber1 🎂 Love You 😘', '2012-08-24 02:32:05.166492', 'f', NULL, 0, NULL, 
'--- !map:HashWithIndifferentAccess 
result_type: recent

Продължих и тествах класа на response_json (връща Hash), въпреки че в края на тази грешка се казва HashWithIndifferentAccess.

Някой друг да има подобни проблеми и да знае решение?

Благодаря!


person watts    schedule 24.08.2012    source източник
comment
Пускам го локално на MacOSX и работи на Heroku. Проблемът е и в двата края.   -  person watts    schedule 24.08.2012
comment
Можете ли да покажете оригиналната, неподправена форма на текста?   -  person Craig Ringer    schedule 25.08.2012
comment
Като цяло тази обработка на кодове изглежда изключително съмнителна. Откриването на набор от знаци в най-добрия случай е съмнително и е лоша основа за използване за автоматично преобразуване. Второ, ActiveSupport::JSON.decode() не преобразува ли от json в Ruby структури от данни? Вашият коментар и име на променлива са малко объркващи.   -  person Craig Ringer    schedule 25.08.2012
comment
Що се отнася до заглавките на отговора, в които се твърди, че е UTF-8: това предполага, че хората, внедрили API, имат наполовина представа за текстовите кодировки и че клиентът, който е изпратил туита, също е направил. Необходим е само един човек, който заглушава ISO-8859-1 (latin-1) байтове в предполагаем UTF-8 низ.   -  person Craig Ringer    schedule 25.08.2012
comment
@CraigRinger Вие сте напълно прав за декларирането на UTF-8! Може да казват, че това е специфично кодиране, без първо да го дезинфекцират.   -  person watts    schedule 26.08.2012
comment
Прав си също така, че коментарът ми и имената на променливите са объркващи - предполагам, че това идва от липсата ми на опит с Ruby/Rails в момента. (Съжалявам!)   -  person watts    schedule 26.08.2012
comment
ЧОВЕК, свикнах с използването на shift+return за нови редове - съжалявам за толкова много малки коментари!   -  person watts    schedule 26.08.2012
comment
уф Още един знак, че Twitter е успешен въпреки доста дълбокото количество лош дизайн. Срамно е, че текстовите кодировки не се обработват правилно в новите услуги.   -  person Craig Ringer    schedule 26.08.2012


Отговори (1)


Намерих решение, което работи! Не съм сигурен дали това беше най-добрият пример, тъй като съм нов в Rails/Ruby - но изглежда поне за момента работи!

Както можете да видите в моя пример по-горе, опитвах се да преобразувам целия response.body в UTF-8. Това се оказа неуспешно.

При разглеждане на данните, които се извличат, единствената част, която може да има различни от UTF-8 обекти, ще бъде текстът на състоянието на туита. Twitter не позволява знаци, различни от a-z,-,_ в показваните им имена. И тъй като съхранявам само екранни имена, текстове на състоянието и идентификатори на туитове, това оставя текста на състоянието. Гледайки някои от статусите, изтеглени от Twitter - някои потребители използваха емотикони и други подобни в своите туитове.

Решението за мен беше да преобразувам отделния текст на състоянието в UTF-8, след което да го пренасоча в рамките на хеша.

def parse_response!
tweets_json = response_json['results'].reverse rescue []
tweets << tweets_json.collect do |tweet_json|

  # trying to fix encoding issue!
  data = CharDet.detect(tweet_json['text'])
  encoding = data['encoding']
  ic = Iconv.new('UTF-8//IGNORE', encoding)
  converted_response = ic.iconv(tweet_json['text'] + '  ')[0..-2]
  # after converting, put back into value
  tweet_json['text'] = converted_response

  # ... etc

Говорете за учебен процес!

Благодаря на @CraigRinger за вашата помощ!

person watts    schedule 26.08.2012