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

몇 가지 기본 광동어, 북경어, 일본 스피커와 이야기 한 후 그것을 할 수있는 올바른 것은 어렵지만, 내 현재의 알고리즘은 여전히 ​​인터넷 게시물의 맥락에서 그들에게 의미가 보인다.

의미는 "공간 분할 및 끝에 ... 추가"처리에 사용됩니다.

그래서 나는 그것을 이해하지 못하는 사람들로부터 불만을 얻을 때까지 게으르며 붙어 있습니다.

내 원래의 구현에 단 하나의 변화 (2 개 문자를 저장하고 ... &#x2026 대신 three dots ...의 유니 코드 문자를 사용)은 모든 언어에서 불필요한 때문에 마지막 단어에 공간을 강제하지하는 것입니다

+0

HTML : '& hellip;', 명명 된 엔티티입니다 (수평 줄임표). – ephemient

7

중국어는 일반적으로 단어 사이에 공백이 없으며 기호는 문맥에 따라 다른 의미를 가질 수 있습니다. 단어 경계에서 텍스트를 분리하려면 텍스트를 이해해야합니다. 다른 말로하면, 당신이하려는 것은 일반적으로 쉽지 않습니다.

+0

중국어 문자열을 부분 문자열로 해석하는 것이 맞습니까? ''[: 120]''처럼하면 여전히 읽을 수 있습니까? –

+4

단어의 의미가 완전히 바뀔 수 있습니다. 처음 세 글자에서 "도움"을 나누어 상상해보십시오. –

+0

좋습니다. 고맙습니다. "..."은 다른 언어에서 같은 것을 의미합니까, 아니면 다른 "타원"문자가 있습니까 –

5

중국어로 단어를 세분화하고 자연 언어를 처리하는 고급 작업의 경우 완벽한 솔루션이 아니라면 NLTK을 좋은 출발점으로 생각하십시오. 풍부한 파이썬 기반 툴킷으로 특히 NL 처리 기술을 배우기에 좋습니다 이러한 문제 중 일부에 대한 실행 가능한 솔루션을 제공하기에 충분하지는 않습니다.

+3

"드물게"== 대개 가끔은 뭔가 다른 것입니까? –

+0

@Laurence는 일반적인 NL 작업의 최첨단에 달려 있으며 코드가 필요한 생산 강화 및 성능 조정 방법에 따라 달라집니다. 테라 바이트의 텍스트를 처리하거나 대기 시간이 짧은 응답을 필요로하는 경우, 확장 성이 뛰어난 대형 병렬 클러스터에 배포해야하므로 NLTK는 시제품을 스케치 할 수 있으며 요구 사항에 적합한 솔루션을 제공하지는 않습니다. 더 적은 양과보다 많은 시간을 허용하는 작업, 특히 세분화와 같은 잘 알려진 것들이 "일반적으로"적용됩니다 - 그러나 모든 종류의 중간 요구와 특수한 문제가 있습니다! - –

+2

저는 단어 분리 발견을위한 NLP 솔루션을 배우고 싶지 않습니다. 누군가 이미이 작업을 수행했으며 미리 박스에 담긴 단어 분리 스플리터를 원합니다. –

0

이렇게하면 re-module에 단어 분리 결정이 적용되지 않지만 충분히 잘 작동 할 수 있습니다.

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 자이 아닌 문자열로 끝납니다.'len (shorten (s * 2, "... end "))' –

+0

그것은 마지막 \ b \ W에서 깨지기 때문에 예상대로 작동한다는 것을 의미합니다. 그러나, 나는 이것이 실제로 그 텍스트의 단어 분리인지 알기 위해 중국어를 모른다. 한도보다 더 짧게 깨는 방법에 대한 다른 예제는'shorten ("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

UTF-8에서 줄임표는 3 바이트를 필요로하므로 거기에 저장되지 않습니다. –

+2

"bytes"대신 "characters"라는 단어를 사용했습니다. :) –

+1

Adam 의미 : UTF-8에서 U + 2026은 3 바이트를 사용하고 3 개의 점은 각각 1 바이트를 사용하므로 저장할 때 저장하지 않습니다. 내 메모 : 개념적으로 줄임표 문자를 사용하는 것이 좋습니다. –

2

푸시 알림을위한 PyAPNS 솔루션을 사용해 보았고 나에게 맞는 것을 공유하고 싶었습니다. 내가 가진 문제는 UTF-8로 256 바이트를 잘라내면 알림이 삭제된다는 것입니다. 통지가 "unicode_escape"로 인코딩되어 작동하는지 확인해야했습니다. 결과가 JSON으로 보내지며 원시 UTF-8로 보내지지 않기 때문에 이것이라고 가정합니다.

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

는 기본적으로 CJK에 (공백 한국어 제외), 제대로 세그먼트 단어 사전 룩 - 업이 필요합니다 어쨌든 여기에 나를 위해 일한 기능입니다. 단어의 정확한 정의에 따라 단어의 변형 된 모든 변종 (예 : '행세'대 '행 했음')이 사전에 표시되지 않으므로 일본어가 그보다 어려울 수 있습니다. 가치가 있는지 여부는 애플리케이션에 따라 다릅니다.