Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

取得 big5-uao 編碼的文章/信件內容 #11

Closed
eight04 opened this issue Jun 10, 2018 · 14 comments
Closed

取得 big5-uao 編碼的文章/信件內容 #11

eight04 opened this issue Jun 10, 2018 · 14 comments

Comments

@eight04
Copy link

eight04 commented Jun 10, 2018

在 utf-8 模式下,雙色字無法被正確上色。希望能新增一個選項,用來取得 big5 編碼下的原始資料。類似︰

bot = PTT.Library(user, password, raw=True)
content = bot.getMail(index).content
assert isinstance(content, bytes) # content 是 bytes
cleaned_content = clean_screen(content) # 移除 esc code
text = cleaned_content.decode("big5-uao") # 純文字
@Truth1987 Truth1987 self-assigned this Jun 10, 2018
@eight04
Copy link
Author

eight04 commented Jun 11, 2018

UAO encoder/decoder:
https://github.com/eight04/pyUAO

@Truth1987
Copy link

Truth1987 commented Jun 12, 2018

!
謝謝你的專案!!!昨天我已經修好了,如果有問題我再引用你的 repo。
請參考

from PTTLibrary import Big5uao
encode("Big5uao")

感恩

@eight04
Copy link
Author

eight04 commented Jun 12, 2018

Big5uao.py 有幾個問題︰

  1. 每當 PTTLibrary.Big5uao 被 import,該編碼就會自動被註冊進 codecs (L67):

    codecs.register(getregentry) 	
  2. getregentry 沒有檢查 codec_name 直接回傳 CodecInfo (L56):

    def getregentry(codec_name):
      return codecs.CodecInfo(
        name='big5ext',
        encode=Codec().encode,
        decode=Codec().decode,
        incrementalencoder=IncrementalEncoder,
        incrementaldecoder=IncrementalDecoder,
        streamreader=StreamReader,
        streamwriter=StreamWriter,
      )

    導致以下的程式碼也正常運作︰

    >>> from PTTLibrary import Big5uao
    >>> a = "我不是大五碼"
    >>> a.encode("Big5uao")
    b'\xa7\xda\xa4\xa3\xacO\xa4j\xa4\xad\xbdX'
    >>> a.encode("NotBig5uao")
    b'\xa7\xda\xa4\xa3\xacO\xa4j\xa4\xad\xbdX'
    >>>
  3. 承上,任意非系統內建的 codec name 都被覆蓋成 Big5uao,導致其它自訂編碼無法使用。

  4. 沒有使用 errors 參數,編碼錯誤被 ignore (L18):

    encdoe_str.extend(unichar.encode('big5hkscs', 'ignore'))

另外,uao 使用的字碼表去除了 "\uFFFD",所以無法編碼的字元會丟出例外而非被替換成替代字元︰

>>> import uao
>>> uao.register_uao()
>>> "나는".encode("big5-uao")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "d:\dev\pyuao\uao\__init__.py", line 15, in encode
    result = b"".join(self._encode(input, errors))
  File "d:\dev\pyuao\uao\__init__.py", line 33, in _encode
    c_replaced, next_i = lookup_error(errors)(err)
UnicodeEncodeError: 'big5-uao' codec can't encode character '\ub098' in position
 0: illegal multibyte sequence

Big5uao.py:

>>> from PTTLibrary import Big5uao
>>> "나는".encode("Big5uao")
b'\xff\xfd\xff\xfd'

@Truth1987
Copy link

好,我改用 uao 專案試試看。

謝謝你的幫助。

@Truth1987
Copy link

Truth1987 commented Jun 13, 2018

我思考了一下,是不是 MailInformation 裡面多一個欄位放 RAW 資料就好了?
拿出來再自己轉換就好?

@eight04

@eight04
Copy link
Author

eight04 commented Jun 13, 2018

不是。因為 PTTLibrary 登入時使用 bbsu 作為使用者登入 SSH,整個連線都使用 utf-8 編碼。也因此原始資料已經在 big5-uao -> utf8 的過程中被破壞過一次。必須使用 bbs 作為使用者登入 SSH,連線才會使用 big5-uao 編碼。

下面是擷圖比較 bbs 和 bbsu 的畫面 (pietty)︰

bbs
image

bbsu
image

可以看到 LOGO 的 "P", "1", "8" 都有顏色錯誤的情況,這是由於雙色字無法用 utf-8 編碼。這在普通文章中沒什麼問題,因為很少用到上色甚至雙色字;但對於 ANSI Art 卻是致命的(參考 asciiart 板)。

後來我有實作了一個非常簡易的 PTTBot(沒有 threading、沒有自動重連線、很多情況都沒測試、只會進信箱和擷取文章),使用 big5-uao 連線︰
https://github.com/eight04/ptt-mail-backup/blob/master/ptt_mail_backup/ptt_bot.py

@Truth1987
Copy link

我使用 PTTChrome

2018-06-13 21-50-59

看起來顯示雙色沒有問題,我看了一下 PTTChrome 的程式碼,裡面也有 UTF8 與 Big5uao 的轉換。

詳見
https://github.com/robertabcd/PttChrome/tree/dev/src/conv

見此討論,問題似乎沒有很簡單,
https://www.ptt.cc/bbs/Linux/M.1408507973.A.686.html

另外我也看了 pcman 專案,

pcman-bbs/pcman-windows#14

歷史這麼悠久的專案在 2017 年,依舊有類似的問題存在。

所以總結兩條路可以選,

  1. 完備純 Python 的 UTF8 to Big5uao
  2. 裝上純 telnet 版本的連線核心,這個我之前就做過詳見 PTTLibrary 0.5 或更早的版本

我不太建議走不安全的選項二,另外 UTF-8 屬於 Unicode 的一種變型,可以把任何編碼轉換至 UTF-8,
詳見

https://zh.wikipedia.org/wiki/UTF-8

我會繼續看有沒有方案一的候選,感謝您的回報。
每一個 issue 都讓 PTTLibrary 更強壯。

@eight04
Copy link
Author

eight04 commented Jun 13, 2018

裝上純 telnet 版本的連線核心

這項的原因是?如果是為了連線時能取得以 big5-uao 編碼的資料,ssh 也可以做到。只要做以下修改︰

diff --git a/PTTLibrary/PTT.py b/PTTLibrary/PTT.py
index 22a0457..d7fd041 100644
--- a/PTTLibrary/PTT.py
+++ b/PTTLibrary/PTT.py
@@ -414,7 +414,7 @@ class Library(object):
                 # self.__ConnectList[ConnectIndex].load_system_host_keys()
                 # self.__ConnectList[ConnectIndex].set_missing_host_key_policy(paramiko.WarningPolicy())
                 self.__ConnectList[ConnectIndex].set_missing_host_key_policy(paramiko.AutoAddPolicy())
-                self.__ConnectList[ConnectIndex].connect('ptt.cc', username = 'bbsu', password = '', pkey = self.__SSHKey)
+                self.__ConnectList[ConnectIndex].connect('ptt.cc', username = 'bbs', password = '', pkey = self.__SSHKey)
                 
                 self.__ConnectList[ConnectIndex].channel = self.__ConnectList[ConnectIndex].invoke_shell(width = self.width, height = self.height)
             except paramiko.AuthenticationException:

@holishing
Copy link

簡單來說就 ssh bbs@ptt.cc 這個帳號連進去編碼就是 big5+UAO 了..
跟你要採用或捨棄 telnet / ssh / websocket 完全無關 , 更不必搞 UTF8 to Big5+UAO 這多餘的東西..

@Truth1987
Copy link

喔! 原來是這樣,好 我在想一下架構怎麼調整比較好。

謝謝各位啦。

@Truth1987
Copy link

@eight04 你改成 bbs 執行登入功能可以成功嗎?

@eight04
Copy link
Author

eight04 commented Jun 14, 2018

不行。有幾個問題︰

  1. 目前一收到資料就以 utf-8 decode︰
    https://github.com/Truth0906/PTTLibrary/blob/121049d8f6de3ee0408a58c7bf5e891d53bc4269/PTTLibrary/PTT.py#L379-L380
    使用 big5-uao 時必須先去除 ANSI escape code -> 才能進行 decode。

  2. 承上,如果要去除色碼,必須找一個方法,用來儲存包含色碼的原始資料。

ptt-mail-backup 使用的方法,是把資料丟給 pyte,pyte 會解析色碼並把字元包含顏色畫到 80x24 大小的 buffer 上。然後 ptt-mail-backup 再從 buffer 中取出字元內容,進行 decode。

P.S. 目前 pyte 不支援閃爍字,所以原始資料中有閃爍的 ANSI escape code (\x1b[5m),畫到 buffer 上沒有效果。不知道是否有其它的替代品。

@Truth1987
Copy link

已經成功取得原始資料,使用 big5 寫入檔案後,可使用 big5 正確顯示,此問題結束後推上 pypi。

@eight04
Copy link
Author

eight04 commented Jun 18, 2018

我測試了 master,可以正常抓取資料 🎉
https://github.com/eight04/ptt-mail-backup/tree/dev-ptt-library

其它和 ANSI 文章相關的問題,我開了新的 issue。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants