2019年2月4日 星期一

BeautifulSoup 中 find_all contents children descendants select 的使用時機

初學者常看到的網路上文件或程式碼通常是這樣取得一個節點

tr.td.ul.li.table.tbody.tr

但是有一行很不起眼的註解出現在文件中:

Using a tag name as an attribute will give you only the first tag by that name:

所以如果你要存取的是同層級的第二個 tr 或 td 呢? 嘿嘿嘿…



當然還有另一個問題,就是子節點中根本就沒有這個型態,那就默默的回你一個null...(炸)

所以初學者的文件說實在不應該提到這些縮寫,這都是了解 dom 以後配合情境才能用的。

簡單來說,初學者應該只用 find_all ,配合 recursive=false 參數就等於 contents ,均可迭代;

只要迭代子節點就用 children ,迭代整個子樹就用 descendants ;除了 find_all 均應檢查節點型別以免發生意外 ;

直接以 tag 名稱存取 a.b 的語意就是 a.find_all('b')[0] ,你就要保證它剛好就只有一個,或是你要的就是第一個 b。

bs4 還有很多坑的,例如:

soup.p['class'] 和 soup.p.get('class') 相比,後者不會發出例外,但 soup.p.get('class', [])更佳,因為檢查 'xxx' in soup.p.get('class', []) 的程式碼也不會發出例外,但語意一致。(class 預設傳回的是陣列)

a['b'] 就是 a.get('b') ,但前者的寫法在沒有這個屬性時會發出例外,後者會給你個 null 而已,要怎麼處理,要想清楚。

結論:大部分的情況下, select() 配合 css 才是迭代的最好方案。


沒有留言:

張貼留言