Я получаю твиты из Twitter, используя библиотеку Tweepy (Python) и Kafka. Текст закодирован в UTF-8, как показано в этой строке:
self.producer.send('my-topic', data.encode('UTF-8'))
Где «данные» — это строка. Затем эти данные сохраняются в базе данных Oracle NoSQL в формате ключ-значение. По этой причине сам твит кодируется. Я делаю это с помощью Java:
Value myValue = Value.createValue(msg.value().getBytes("UTF-8"));
Наконец, твиты извлекаются Formatter, разработанным на Java. Чтобы сохранить его в реляционной схеме, я должен проанализировать твит, чтобы получить его как строку.
String data = new String(value.toByteArray(),StandardCharsets.UTF_8);
Как видите, я поддерживаю кодировку UTF-8 на всех этапах. Однако когда я вижу текст твита в своей базе данных, он всегда обрезается. Например:
RT @briIIohead: the hardest pill i had to swallow this year was learning that no matter how good you could be to somebody, no matter how mu?
Обратите внимание, как он заканчивается на '?' символ, и он был четко вырезан. Ну, это происходит с каждым длинным твитом. Я имею в виду, что если текст длиной около 30 символов, то он отображается нормально, однако все, что длиннее 100 или около того, обрезается.
Сначала я подумал, что это может быть мое определение таблицы, но поле «Текст» объявлено как VARCHAR2(400 CHAR)
, что является максимальным количеством символов, которое может иметь твит в социальной сети.
Любые идеи о том, как я могу определить, что сокращает текст и ставит '?' символ в конце?
Как выглядят «данные»:
{"created_at":"Tue May 28 09:23:36 +0000 2019","id":1133302792129351681,"id_str":"1133302792129351681","text":"RT @AppleEDU: Learn, create, and do more with iPad in your classroom. Get the free Everyone Can Create curriculum and bring projects to lif\u2026","source":"\u003ca href=\"http://twitter.com/download/iphone\" rel=\"nofollow\"\u003eTwitter for iPhone\u003c/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":1060510851889750022,"id_str":"1060510851889750022","name":"Rem.0112","screen_name":"0112Rem","location":"Mawson Lakes, Adelaide","url":null,"description":null,"translator_type":"none","protected":false,"verified":false,"followers_count":739,"friends_count":1853,"listed_count":10,"favourites_count":33406,"statuses_count":36936,"created_at":"Thu Nov 08 12:34:25 +0000 2018","utc_offset":null,"time_zone":null,"geo_enabled":true,"lang":null,"contributors_enabled":false,"is_translator":false,"profile_background_color":"F5F8FA","profile_background_image_url":"","profile_background_image_url_https":"","profile_background_tile":false,"profile_link_color":"1DA1F2","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"profile_image_url":"http://pbs.twimg.com/profile_images/1093157842163355649/6oAdJTCs_normal.jpg","profile_image_url_https":"https://pbs.twimg.com/profile_images/1093157842163355649/6oAdJTCs_normal.jpg","profile_banner_url":"https://pbs.twimg.com/profile_banners/1060510851889750022/1546155144","default_profile":true,"default_profile_image":false,"following":null,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"retweeted_status":{"created_at":"Thu May 23 15:15:16 +0000 2019","id":1131579354964725760,"id_str":"1131579354964725760","text":"Learn, create, and do more with iPad in your classroom. Get the free Everyone Can Create curriculum and bring proje\u2026 https://t.co/aeeSPTXtFx","source":"\u003ca href=\"https://ads-api.twitter.com\" rel=\"nofollow\"\u003eTwitter Ads Composer\u003c/a\u003e","truncated":true,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"user":{"id":468741166,"id_str":"468741166","name":"Apple Education","screen_name":"AppleEDU","location":"Cupertino, CA","url":null,"description":"Spark new ideas, create more aha moments, and teach in ways you\u2019ve always imagined. Follow @AppleEDU for tips, updates, and inspiration.","translator_type":"none","protected":false,"verified":true,"followers_count":728781,"friends_count":273,"listed_count":2594,"favourites_count":13189,"statuses_count":2766,"created_at":"Thu Jan 19 21:26:14 +0000 2012","utc_offset":null,"time_zone":null,"geo_enabled":false,"lang":null,"contributors_enabled":false,"is_translator":false,"profile_background_color":"F0F0F0","profile_background_image_url":"http://abs.twimg.com/images/themes/theme1/bg.png","profile_background_image_url_https":"https://abs.twimg.com/images/themes/theme1/bg.png","profile_background_tile":false,"profile_link_color":"0088CC","profile_sidebar_border_color":"C0DEED","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":false,"profile_image_url":"http://pbs.twimg.com/profile_images/892429342046691328/2SOlm_09_normal.jpg","profile_image_url_https":"https://pbs.twimg.com/profile_images/892429342046691328/2SOlm_09_normal.jpg","profile_banner_url":"https://pbs.twimg.com/profile_banners/468741166/1530123538","default_profile":false,"default_profile_image":false,"following":null,"follow_request_sent":null,"notifications":null},"geo":null,"coordinates":null,"place":null,"contributors":null,"is_quote_status":false,"extended_tweet":{"full_text":"Learn, create, and do more with iPad in your classroom. Get the free Everyone Can Create curriculum and bring projects to life through music, drawing, video and photography.","display_text_range":[0,173],"entities":{"hashtags":[],"urls":[],"user_mentions":[],"symbols":[]}},"quote_count":0,"reply_count":3,"retweet_count":3,"favorite_count":58,"entities":{"hashtags":[],"urls":[{"url":"https://t.co/aeeSPTXtFx","expanded_url":"https://twitter.com/i/web/status/1131579354964725760","display_url":"twitter.com/i/web/status/1\u2026","indices":[117,140]}],"user_mentions":[],"symbols":[]},"favorited":false,"retweeted":false,"scopes":{"followers":false},"filter_level":"low","lang":"en"},"is_quote_status":false,"quote_count":0,"reply_count":0,"retweet_count":0,"favorite_count":0,"entities":{"hashtags":[],"urls":[],"user_mentions":[{"screen_name":"AppleEDU","name":"Apple Education","id":468741166,"id_str":"468741166","indices":[3,12]}],"symbols":[]},"favorited":false,"retweeted":false,"filter_level":"low","lang":"en","timestamp_ms":"1559035416048"}
Я также должен упомянуть, что весь этот фрагмент закодирован. Затем декодируется и, наконец, анализируется для внесения в базу данных. Все поля корректно декодируются и анализируются, кроме «текста», который вырезается.
@Lino, конечно, я отредактирую вопрос
Я помню, как твиттер увеличил свой лимит до 280 символов. Может ли быть так, что используемая вами версия библиотеки не адаптировала свои внутренние ограничения? Например. они все еще ожидают не более 140 символов
Согласно документации официальный, твит имеет не более «140» символов (это широкое определение); но в последнее время они изменили его на 280
.
В том же документе говорится:
Twitter counts the length of a Tweet using the Normalization Form C (NFC) version of the text.
Поэтому они сначала нормализуют текст (позволю вам разобраться, как это делается в java). А потом говорят:
Twitter also counts the number of codepoints in the text rather than UTF-8 bytes.
Таким образом:
String test = "RT @briIIohead: the hardest pill i had to swallow this year was learning that no matter how good you could be to somebody, no matter how mu";
System.out.println(test.codePoints().count()); // 139
Кажется, что первоначальный твит состоял из 280 «символов», и ваша библиотека, которую вы используете, не знает об этом, поэтому она использует только предыдущие 140. Поскольку при этом происходит некоторое разбиение на фрагменты, кажется, что разбиение на фрагменты также неверно, оно удаляет некоторые «частичные» байты в конце. Когда вы пытаетесь напечатать их - java не знает, что на самом деле означают эти (в конце) байты (из-за некоторого неправильного фрагментирования) и просто говорит ?
(что является стратегией по умолчанию, что показывать, когда он просто что-то не понимает) .
@Лино круто! Я только предположил, что библиотека сломана, вы это подтвердили! Спасибо
Добро пожаловать, не стесняйтесь добавлять эту ссылку в свой ответ, чтобы усилить свое утверждение :)
Как выглядит
data
? Какой это тип? Можно как-то отладить, если весь текст вообще доступен? Например. вы как-то обрезаете текст или вообще получаете сразу целиком?