2009-11-15 21 views
10

मुझे एक स्ट्रिंग लेने की आवश्यकता है, और इसे 140 वर्णों तक छोटा करें।पायथन: शब्द सीमाओं पर यूनिकोड स्ट्रिंग को विभाजित करें

वर्तमान में मैं कर रहा हूँ:

if len(tweet) > 140: 
    tweet = re.sub(r"\s+", " ", tweet) #normalize space 
    footer = "… " + utils.shorten_urls(post['url']) 
    avail = 140 - len(footer) 
    words = tweet.split() 
    result = "" 
    for word in words: 
     word += " " 
     if len(word) > avail: 
      break 
     result += word 
     avail -= len(word) 
    tweet = (result + footer).strip() 
    assert len(tweet) <= 140 

तो यह अंग्रेजी के लिए महान काम करता है, और तार की तरह अंग्रेजी है, लेकिन क्योंकि tweet.split() सिर्फ एक सरणी देता है एक चीनी स्ट्रिंग के लिए विफल रहता है:

>>> s = u"简讯:新華社報道,美國總統奧巴馬乘坐的「空軍一號」專機晚上10時42分進入上海空域,預計約30分鐘後抵達浦東國際機場,開展他上任後首次訪華之旅。" 
>>> s 
u'\u7b80\u8baf\uff1a\u65b0\u83ef\u793e\u5831\u9053\uff0c\u7f8e\u570b\u7e3d\u7d71\u5967\u5df4\u99ac\u4e58\u5750\u7684\u300c\u7a7a\u8ecd\u4e00\u865f\u300d\u5c08\u6a5f\u665a\u4e0a10\u664242\u5206\u9032\u5165\u4e0a\u6d77\u7a7a\u57df\uff0c\u9810\u8a08\u7d0430\u5206\u9418\u5f8c\u62b5\u9054\u6d66\u6771\u570b\u969b\u6a5f\u5834\uff0c\u958b\u5c55\u4ed6\u4e0a\u4efb\u5f8c\u9996\u6b21\u8a2a\u83ef\u4e4b\u65c5\u3002' 
>>> s.split() 
[u'\u7b80\u8baf\uff1a\u65b0\u83ef\u793e\u5831\u9053\uff0c\u7f8e\u570b\u7e3d\u7d71\u5967\u5df4\u99ac\u4e58\u5750\u7684\u300c\u7a7a\u8ecd\u4e00\u865f\u300d\u5c08\u6a5f\u665a\u4e0a10\u664242\u5206\u9032\u5165\u4e0a\u6d77\u7a7a\u57df\uff0c\u9810\u8a08\u7d0430\u5206\u9418\u5f8c\u62b5\u9054\u6d66\u6771\u570b\u969b\u6a5f\u5834\uff0c\u958b\u5c55\u4ed6\u4e0a\u4efb\u5f8c\u9996\u6b21\u8a2a\u83ef\u4e4b\u65c5\u3002'] 

कैसे करना चाहिए मैं ऐसा करता हूं इसलिए यह I18N को संभालता है? क्या यह सभी भाषाओं में समझ में आता है?

यदि मायने रखता है तो मैं पाइथन 2.5.4 पर हूं।

+0

दिलचस्प प्रश्न के लिए +1 –

उत्तर

1

कुछ देशी कैंटोनीज़, मंदारिन, और जापानी वक्ताओं के साथ बात करने के बाद ऐसा लगता है कि ऐसा करने के लिए सही बात कठिन है, लेकिन मेरे वर्तमान एल्गोरिथ्म अभी भी इंटरनेट पदों के संदर्भ में उन्हें समझ में आता है।

मतलब, उनका उपयोग "अंतरिक्ष पर विभाजित और अंत में ... अंत में" उपचार के लिए किया जाता है।

तो मैं आलसी होने जा रहा हूं और इसके साथ रहना चाहता हूं, जब तक कि मुझे उन लोगों की शिकायतें न मिलें जो इसे समझ में नहीं आतीं।

अपने मूल कार्यान्वयन के लिए केवल परिवर्तन अंतिम शब्द पर एक अंतरिक्ष के लिए मजबूर करने के लिए नहीं है, क्योंकि यह किसी भी भाषा में अनावश्यक है (और यूनिकोड चरित्र ... &#x2026 बजाय ... three dots का उपयोग 2 पात्रों को बचाने के लिए) होगा

+0

यह एचटीएमएल में एक नामित इकाई है: '& hellip;', क्षैतिज ellipsis। – ephemient

7

चीनी में आमतौर पर शब्दों के बीच सफेद जगह नहीं होती है, और प्रतीकों के संदर्भ के आधार पर अलग-अलग अर्थ हो सकते हैं। शब्द सीमा पर इसे विभाजित करने के लिए आपको पाठ को समझना होगा। दूसरे शब्दों में, आप जो करने की कोशिश कर रहे हैं वह सामान्य रूप से आसान नहीं है।

+0

क्या यह चीनी स्ट्रिंग को प्रतिस्थापित करने के लिए समझ में आता है? जैसे कि मैं करता हूं [: 120] 'क्या वह अभी भी पठनीय होगा? –

+4

आप आधा शब्द समाप्त कर सकते हैं जो पूरी तरह से अर्थ बदल सकता है। पहले तीन अक्षरों में विभाजन "सहायता" की कल्पना करो। –

+0

ठीक है, धन्यवाद। क्या "..." का मतलब अन्य भाषाओं में एक ही बात है, या क्या कोई वैकल्पिक "अंडाकार" चरित्र –

5

चीनी में शब्द विभाजन के लिए, और प्राकृतिक भाषा प्रसंस्करण में अन्य उन्नत कार्यों के लिए, NLTK पर एक अच्छा प्रारंभिक बिंदु के रूप में एक अच्छा प्रारंभिक बिंदु के रूप में विचार करें - यह एक समृद्ध पायथन आधारित टूलकिट है, विशेष रूप से एनएल प्रसंस्करण तकनीकों के बारे में सीखने के लिए अच्छा है (और इन समस्याओं में से कुछ के लिए व्यवहार्य समाधान प्रदान करने के लिए पर्याप्त रूप से पर्याप्त नहीं है)।

+3

"शायद ही कभी नहीं" == आमतौर पर, कभी-कभी, कुछ और? –

+0

@ लॉरेंस, इस बात पर निर्भर करता है कि आपके सामान्य एनएल कार्यों में कितना खून बह रहा है, और कैसे उत्पादन-कठोर और प्रदर्शन-ट्यून किए गए हैं, आपको अपने कोड की आवश्यकता है। यदि आप टेक्स्ट के टेराबाइट से निपट रहे हैं या कम विलंबता प्रतिक्रिया की आवश्यकता है, तो आपको एक बड़े, उच्च स्केलेबल समानांतर क्लस्टर पर तैनाती करनी होगी, एनएलटीके आपको प्रोटोटाइप को स्केच करने देगी, न कि आपकी आवश्यकताओं के लिए व्यवहार्य समाधान प्रदान करेगी; कम मात्रा और अधिक समय-सहनशील कार्यों के लिए, esp। सेगमेंटेशन जैसे प्रसिद्ध लोग, "आमतौर पर" लागू होते हैं - लेकिन सभी प्रकार की इंटरमीडिएट जरूरतों और विशेष समस्या quirks हैं! -) –

+2

मैं वास्तव में शब्द ब्रेक डिस्कवरी के लिए एक एनएलपी समाधान को प्रशिक्षित नहीं करना चाहता हूं। मुझे यकीन है कि किसी ने पहले से ही ऐसा किया है, और बस एक प्री-बॉक्सेड वर्डबैक स्प्लिटर चाहिए। –

0

यह फिर से मॉड्यूल के लिए शब्द-ब्रेकिंग निर्णय को पेंट करता है, लेकिन यह आपके लिए पर्याप्त काम कर सकता है।

import re 

def shorten(tweet, footer="", limit=140): 
    """Break tweet into two pieces at roughly the last word break 
    before limit. 
    """ 
    lower_break_limit = limit/2 
    # limit under which to assume breaking didn't work as expected 

    limit -= len(footer) 

    tweet = re.sub(r"\s+", " ", tweet.strip()) 
    m = re.match(r"^(.{,%d})\b(?:\W|$)" % limit, tweet, re.UNICODE) 
    if not m or m.end(1) < lower_break_limit: 
     # no suitable word break found 
     # cutting at an arbitrary location, 
     # or if len(tweet) < lower_break_limit, this will be true and 
     # returning this still gives the desired result 
     return tweet[:limit] + footer 
    return m.group(1) + footer 
+0

धन्यवाद। यदि कोई शब्द सीमा नहीं है तो मैंने एक चेक जोड़ा। अंग्रेजी तारों के लिए यह बहुत अच्छा काम कर रहा है, लेकिन मेरे चीनी उदाहरण के लिए (इसे लंबे समय तक बनाने के लिए इसे डबल करें) मैं एक स्ट्रिंग के साथ समाप्त होता हूं जो कि 137 वर्ण लंबा है, 140 नहीं। 'लेन (छोटा (एस * 2, "... अंत "))' –

+0

इसका मतलब है कि यह अपेक्षित काम कर रहा है, क्योंकि यह अंतिम \ b \ W पर टूट जाता है। हालांकि, मुझे यह नहीं पता कि चीनी वास्तव में उस पाठ में एक शब्द तोड़ है या नहीं। 'छोटा करें (" abcde "* 3," ", 13) 'एक और उदाहरण के लिए प्रयास करें कि यह सीमा से कम कैसे टूटता है। –

3

re.U flag यूनिकोड चरित्र गुण डेटाबेस के अनुसार \s का इलाज करेगा।

>>> x = u'\u7b80\u8baf\uff1a\u65b0\u83ef\u793e\u5831\u9053\uff0c\u7f8e\u570b\u7e3d\u7d71\u5967\u5df4\u99ac\u4e58\u5750\u7684\u300c\u7a7a\u8ecd\u4e00\u865f\u300d\u5c08\u6a5f\u665a\u4e0a10\u664242\u5206\u9032\u5165\u4e0a\u6d77\u7a7a\u57df\uff0c\u9810\u8a08\u7d0430\u5206\u9418\u5f8c\u62b5\u9054\u6d66\u6771\u570b\u969b\u6a5f\u5834\uff0c\u958b\u5c55\u4ed6\u4e0a\u4efb\u5f8c\u9996\u6b21\u8a2a\u83ef\u4e4b\u65c5\u3002' 
>>> re.compile(r'\s+', re.U).split(x) 
[u'\u7b80\u8baf\uff1a\u65b0\u83ef\u793e\u5831\u9053\uff0c\u7f8e\u570b\u7e3d\u7d71\u5967\u5df4\u99ac\u4e58\u5750\u7684\u300c\u7a7a\u8ecd\u4e00\u865f\u300d\u5c08\u6a5f\u665a\u4e0a10\u664242\u5206\u9032\u5165\u4e0a\u6d77\u7a7a\u57df\uff0c\u9810\u8a08\u7d0430\u5206\u9418\u5f8c\u62b5\u9054\u6d66\u6771\u570b\u969b\u6a5f\u5834\uff0c\u958b\u5c55\u4ed6\u4e0a\u4efb\u5f8c\u9996\u6b21\u8a2a\u83ef\u4e4b\u65c5\u3002'] 
+0

दाएं, लेकिन अंग्रेजी में "व्हाइटस्पेस" का अर्थ शब्द सेपरेटर्स है, जहां चीनी में कोई शब्द विभाजक नहीं है, केवल वाक्य सेपरेटर्स के रूप में सफेद जगह है। –

-1

दो सहेजें अक्षर और तीन बिंदुओं के बजाय एक elipsis (, 0x2026) का उपयोग करें:

दिया स्ट्रिंग, हालांकि, जाहिरा तौर पर किसी भी सफेद स्थान पात्रों अजगर का यूनिकोड डेटाबेस के अनुसार शामिल नहीं है!

+1

यूटीएफ -8 में इलिप्सिस में 3 बाइट्स लेते हैं इसलिए वहां सहेजने के लिए बहुत कुछ नहीं :) –

+2

मैंने उद्देश्य पर "बाइट्स" के बजाय "अक्षर" शब्द का उपयोग किया। :) –

+1

एडम का मतलब था: आप दो यूनिकोड वर्णों को सहेजते हैं, लेकिन यूटीएफ -8 में, यू +2026 में 3 बाइट्स लेते हैं, और तीन बिंदु प्रत्येक बाइट लेते हैं, इसलिए जब आप इसे स्टोर करते हैं तो कोई बचत नहीं होती है। मेरा नोट: संकल्पनात्मक रूप से एक इलिप्सिस चरित्र का उपयोग करना बेहतर है। –

2

मैंने पुश नोटिफिकेशन के लिए पीएएपीएनएस के साथ समाधान की कोशिश की और सिर्फ मेरे लिए काम करने के लिए साझा करना चाहता था। मेरे पास यह मुद्दा था कि यूटीएफ -8 में 256 बाइट्स पर छेड़छाड़ के परिणामस्वरूप सूचना छोड़ दी जाएगी। मुझे यह सुनिश्चित करना था कि अधिसूचना को इसे काम करने के लिए "यूनिकोड_स्केप" के रूप में एन्कोड किया गया था। मुझे लगता है कि ऐसा इसलिए है क्योंकि परिणाम जेएसओएन के रूप में भेजा जाता है और कच्चे यूटीएफ -8 नहीं।

def unicode_truncate(s, length, encoding='unicode_escape'): 
    encoded = s.encode(encoding)[:length] 
    return encoded.decode(encoding, 'ignore') 
1

असल में, CJK में (रिक्तियों के साथ कोरियाई छोड़कर), आप खंड शब्द ठीक से करने के लिए शब्दकोश लुक-अप की जरूरत है: वैसे भी यहाँ समारोह है कि मेरे लिए काम किया है। "शब्द" की आपकी सटीक परिभाषा के आधार पर, जापानी उस से अधिक कठिन हो सकता है, क्योंकि किसी शब्द के सभी इन्फलेक्टेड वेरिएंट नहीं हैं (यानी "行 こ う" बनाम "行 っ た") शब्दकोश में दिखाई देंगे। चाहे यह प्रयास के लायक है, आपके आवेदन पर निर्भर करता है।

संबंधित मुद्दे