2021年4月11日 星期日

Python Error - UnicodeDecodeError: 'cp950' codec can't decode

讀檔時 UnicodeDecodeError: 'cp950' codec can't decode

老實說這非常常見,即使你的檔案是用 UTF-8 編寫,而且用 Python3 ( 絕大部分 default 是 utf-8 ),仍會報這個錯。所以要避免程式能在不同平台都能正常使用,讀檔時最好都加上 encoding="utf-8"
    with open("somefile.py", encoding="utf-8") as f:
        f.read()
參考資料 :
1.stackoverflow

2021年4月7日 星期三

Python - BeautifulSoup 基本應用 (2)

Navigating the tree - Going down

  • child Tag
    前一篇呼叫 Tag 底下的 subTag 是用像 class 的方式 (Tag.subTag),沒完整說明的是這個 subTag 可呼叫到的範圍並不只侷限 children Tag,而是整個 Tag 底下第一個遇到的 Tag.name == subTag。
        """ html
        <b class="boldest" id="bold man">
            <u>Extremely bold</u>
        </b>
        <p>Just a paragraph</p>
        """
        soup = BeautifulSoup(html, 'html.parser')
        print(soup.u)  # <u>Extremely bold</u>
  • find_all()
    依循前面的 subTag 找法,find_all 則會找出所有的 Tag (Tag.name == subTag)。
        soup.find_all('a')
        # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
        #  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
        #  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
  • .contents
    Tag.contents 回傳包含所有 child string 的 list。
        print(soup.contents)  # [<d class="car"><u>Extremely bold.</u></d>, <p>123</p>]
  • .children
    Tag.children 回傳包含所有 child Tag object 的 list。
        for child in soup.children:
            print(child.name)
        # b
        # p
  • .descendants
    回傳一個不只包含 Tag 底下一層的 subTag,而是整個 tree 上所有 object。底下的結果之所以會有 None,是因為 NavigableString 也是 child 的包含範圍 ( .contents 跟 .children 也一樣 ),而 NavigableString object 沒有 .name。
        for child in soup.descendants:
            print(child.name)
        # b
        # u
        # None
        # p
        # None
  • .string
    回傳底下唯一一個的 NavigableString 。如果 Tag 只有一個 child 而且還是 NavigableString 則回傳。如果 Tag 只有一個 child 且 child 也只有一個 NavigableString child 也是回傳。如果有兩個以上的 NavigableString 則要呼叫 .strings,.string 會回傳 None。
        print(soup.u.string) # Extremely bold
        print(soup.b.string) # Extremely bold
        print(soup.string)   # None
  • .strings & .stripped_strings
    strings 會回傳所有 NavigableString。但這種情況下仍會紀錄到一些換行或字串前後的空格,所以可以用 stripped_strings 回傳乾淨的 NavigableString list。(如果整個字串都是空格或換行,則這個 NavigableString 會被無視)
        for sstr in soup.strings:
            print(repr(sstr))
        # 'Extremely bold'
        # 'Just a paragraph' 

Navigating the tree - Going Up

  • .parent & .parents
    基本上就是往上一層的 Tag (Soup 的 parent 為 None)。
        link = soup.a
        link
        # <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>
        for parent in link.parents:
            print(parent.name)
        # p
        # body
        # html
        # [document]

Navigating the tree - Going sideways

  • .next_sibling &.previous_sibling
    往前找跟往後找,但是要注意的是他沒那方便幫你找到下一個或上一個的 Tag object,絕大部分都是 NavigableString,例如換行 (\n) 之類的。
        tag1 = soup.b
        tag2 = soup.p
        print(tag1.next_sibling)     # <p>123</p>
        print(tag2.previous_sibling) # <b class="boldest" id="bold man"><u>Extremely bold</u></b>
參考資料 :
1.Beautiful Soup 4.9.0 documentation

2021年3月31日 星期三

Python - BeautifulSoup 基本應用 (1)

BeautifulSoup

紀錄下 Python 網頁爬蟲大部分會用到的 BeautifulSoup。BeautifulSoup 本質上就是 parser,知道這點後其 function 和 parameter 的使用就能得心應手。
  • Install
    這裡紀錄使用 pip 安裝
        pip install beautifulsoup4
        pip install lxml # 非必要
  • Import
    第一行的 import 就可以包含 99%,第二行則是此篇會用的 import,多了 2 個說明用的 object。
        from bs4 import BeautifulSoup
        from bs4 import BeautifulSoup, NavigableString, Comment
  • Load html
    此篇會用第一行來 make soup
        soup = BeautifulSoup("<html>a web page</html>", features="html.parser")
        soup = BeautifulSoup("<html>a web page</html>", features="lxml") # 如果你有安裝的話

Tag object

Tag object 對應到的就是 XML 跟 HTML 裡的 Tag。
這裡可以從 soup object 下 2 個 Tag 開始,一個是 b 一個是 p。
    """ html
    <b class="boldest" id="bold man">
        <u>Extremely bold</u>
    </b>
    <p>Just a paragraph</p>
    """
    soup = BeautifulSoup(html, 'html.parser')
    print(type(soup))   # <class 'bs4.BeautifulSoup'>
    print(soup.b)       # <b class="boldest" id="bold man"><u>Extremely bold</u></b>
    print(soup.p)       # <p>Just a paragraph</p>

    # Tag 有兩個基礎參數 name 跟 attrs
    tag = soup.b
    print(type(tag))    # <class 'bs4.element.Tag'>
    print(tag.name)     # b
    print(tag.attrs)    # {'class': ['boldest'], 'id': 'bold man'}

    # name 跟 attrs 都可以直接修改
    tag.name = "d"
    tag.attrs = {'class': ['boldest', 'cutest'], 'id': 'pui pui'}
    print(str(tag))     # <d class="boldest cutest" id="pui pui"><u>Extremely bold</u></d>
Tag 的 child Tag 可以像 class 的 element 一樣直接呼叫 (上面的 soup.b 和 soup.p 也是一種呼叫 child Tag)
    print(str(tag.u))   # <u>Extremely bold</u>
    print(tag['class']) # ['boldest', 'cutest']
    print(tag['id'])    # pui pui
Tag 的 attr 也可以修改和刪除
tag['class'] = ['car']
del tag['id']
print(str(tag))     # <d class="boldest cutest"><u>Extremely bold</u></d>
P.S. HTML 裡的 class 是可以允許多參數的,所以上述的例子裡 class 是 string list,而非 string

NavigableString object

NavigableString 就等於 Tag 裡的 string,可以使用 replace_with 做修改。
    tag.u.string.replace_with("No longer bold.")
    print(type(tag.u.string)) # <class 'bs4.element.NavigableString'>
    print(str(tag.u.string))  # No longer bold.

BeautifulSoup object

其實一開始就有示範了,可以把他想像成沒有 name 和 attributes 的 Tag。但有時候你在 load 真正的 html 檔,他的 name 可能會是 "[document]"。
    print(str(soup))
    # <d class="car"><u>No longer bold.</u></d><p>123</p>
    print(soup.prettify())
    # <d class="car">
    #  <u>
    #   No longer bold.
    #  </u>
    # </d>
    # <p>
    #  123
    # </p>
參考資料 :
1.Beautiful Soup 4.9.0 documentation

2021年3月26日 星期五

Python - sys, os.path 常見的 module 應用

Common python module - sys

  • sys parameter
    一些常見系統參數
        import sys
        print(sys.platform) # linux
  • sys.argv
    像 c/c++ 的 argv 一樣,可以吃從 command line 傳入的參數。
        # test.py 123 456 789
        print (argv)    # ['test.py', '123', '456', '789']
        print (argv[1]) # 123
  • sys.path
    import 時的 search list,可以也透過改變(增加, 刪除, 更改順序) list 來在想要的位置 import。除了 built-in 的 lodule,其他額外安裝的 module 都可以用這個順序做調整。以下例子就等於會先去找 tool/ 底下的 module,找不到才會找 local/lib/python3.X/site-packages 或 local/lib/python3.X/dist-packages
        print (sys.path)            # [......]
        sys.path.insert(0, "tool/") # ['tool/',......] 
        import markdown             # 已安裝 markdown,但 import 的卻是 tool 底下的
        print(markdown.__file__)    # tool/markdown.py

Common python module - os

  • os.function
    一些常用的 os.function
        import os
        os.system(command)  # 執行 command , command 為系統指令的字串。
        os.getcwd()         # 取得目前所在路徑。
        os.rename(src, dst) # 將 src 改名為 dst 。
        os.mkdir(path)      # 建立 path 路徑,如果已存在就會發起例外。
        os.remove(path)     # 移除 path ,如果 path 是目錄就會發起例外。
        os.rmdir(path)      # 刪除 path 目錄。
  • os.path (1)
    檢查檔案目錄。
        import os
        os.path.isfile(path)            # 判斷 path 檔案是否存在。
        os.path.isdir(path)             # 判斷 path 路徑是否存在。
  • os.path (2)
    os.path 路徑處理。
        import os
        path = "/home/JunYe/123.txt"
        os.path.dirname(path)  # 回傳 path 的目錄路徑。
        os.path.basename(path) # 回傳 path 的檔案名稱。
        os.path.split(path)    # 分割路徑為 (head, tail) ,其中 head 為目錄, tail 為檔案名稱。
        os.path.splitext(path) # 分割路徑為 (root, ext) ,其中 root 為目錄包括檔名, ext 為副檔名。
        print(os.path.dirname(path))  # /home/JunYe
        print(os.path.basename(path)) # 123.txt
        print(os.path.split(path))    # ('/home/JunYe', '123.txt')
        print(os.path.splitext(path)) # ('/home/JunYe/123', '.txt')
參考資料 :
1.sys — 你所不知道的 Python 標準函式庫用法 01
2.Python 速查手冊 - 12.5 基本檔案與目錄處理 os 與 os.path

2021年3月21日 星期日

英文 Mail - 催促

 英文催促信件範本

    記錄下一些常用句型。井字號後之內容純屬虛構,如有雷同...你 Bad!!
# 跟他打招呼
Hello, JunYe. 

# 靠夭他
Do you have any updates about the project that we discussed in the last weekly meeting ?

# 假裝很關心 + 會幫忙
If you have any further queries, please do not hesitate to contact me.

# 假惺惺提醒要加快腳步
You can consider checking your schedule to make sure progress of the project is hitting the target.

# 給截止時間
We would be grateful if the job can be finished by 30th June.

# 輕輕施加壓力的結尾
Your early reply will be much highly appeciated.
參考資料 :

2021年2月19日 星期五

讀書心得 - C++ Primer (5th Edition) - Chapter 2 (4) - 常用詞彙

 常用詞彙

  • bind
    Associating a name with a given entity so that uses of the name are uses of the underlying entity. For example, a reference is a name that is bound to an object.
  • compound type
    A type that is defined in terms of another type.
  • const
    Type qualifier used to define objects that may not be changed. const objects must be initialized, because there is no way to give them a value after they are defined.
  • declaration
    Asserts the existence of a variable, function, or type defined elsewhere. Names may not be used until they are defined or declared.
  • definition
    Allocates storage for a variable of a specified type and optionally initializes the variable. Names may not be used until they are defined or declared.
  • const pointer
    Pointer that is const.
  • pointer to const
    Pointer that can hold the address of a const object. A pointer to const may not be used to change the value of the object to which it points.
  • reference to const
    A reference that may not change the value of the object to which it refers. A reference to const may be bound to a const object, a nonconst object, or the result of an expression.
  • const reference
    因為 reference 本身不是 object 所以不能用 const 修飾,所以口語上跟 reference to const 同義。
  • undefined
    Usage for which the language does not specify a meaning. Knowingly or unknowingly relying on undefined behavior is a great source of hard-to-track runtime errors, security problems, and portability problems.(例如給 unsigned char 賦值 256)
  • word
    The natural unit of integer computation on a given machine. Usually a word is large enough to hold an address. On a 32-bit machine a word is typically 4 bytes.

2021年2月18日 星期四

Programmer Interview - stack v.s. heap

 stack v.s. heap

  • 與 threads 的互動
    在一個 multi-threaded 的程式中,每個 thread 都各自擁有一個 stack,但共享一個 heap。
  • object 可以儲存在 heap,而非 stack
    在 c++ 可以使用 new,來將 object 實體儲存在 heap。
        void foo () {
            // myClass, myPointer 儲存在 stack
            // myPointer 所指向的 tempClass object 則儲存在 heap
            // function 結束 myClass, myPointer 則會與 stack 一起 remove
            // 而 myPointer 所指向的 tempClass 不會,所以下 delete
            tempClass myClass;
            tempClass *myPointer = new tempClass();
            delete myPointer;
        }
  • Java 或 .NET 可以透過 garbage collection 來作到 delete myPointer; 的效果。
  • stack 跟 heap 的大小
    stack 大小是固定的,有某些語言可以增加其大小。若 stack 不夠則會造成 stackoverflow (ex 無限遞迴)。heap 大小則是靠 OS 給的。
參考資料 :

Popular Posts