BeautifulSoup操作大全


 1 一、獲取BeautifulSoup文檔的對象
 2     1.對象
 3         Beautiful Soup將復雜HTML文檔轉換成一個復雜的樹形結構,每個節點都是Python對象,
 4         所有對象可以歸納為4種: Tag , NavigableString , BeautifulSoup , Comment .
 5         
 6         Comment 對象是一個特殊類型的 NavigableString 對象,其輸出的內容不包括注釋符號。
 7             
 8             <a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>
 9             #a 標簽里的內容實際上是注釋,但是如果我們利用 .string 來輸出它的內容時,注釋符號已經去掉了。
10             type(soup.a.string)  -->   <class 'bs4.element.Comment'>
11             
12             
13         可以傳入一段字符串或一個文件句柄.
14         from bs4 import BeautifulSoup
15         soup = BeautifulSoup(open("index.html"))   or    soup = BeautifulSoup("<html>data</html>")    
16     2.編碼
17         使用Beautiful Soup解析后,文檔都被轉換成了Unicode
18         Beautiful Soup用了 編碼自動檢測 子庫來識別當前文檔編碼並轉換成Unicode編碼.
19         BeautifulSoup 對象的 .original_encoding 屬性記錄了自動識別編碼的結果
20         
21         #通過傳入 from_encoding 參數來指定編碼方式
22         soup = BeautifulSoup(markup, from_encoding="iso-8859-8")
23         
24         #節點可通過encode() 方法來指定輸出編碼
25         soup.p.encode("utf-8")
26         
27         #通過Beautiful Soup輸出文檔時,不管輸入文檔是什么編碼方式,輸出編碼均為UTF-8編碼
28         print(soup.prettify("latin-1"))   #如果不想用UTF-8編碼輸出,可以將編碼方式傳入 prettify() 方法
29         prettify() #增加換行符,html格式打印
二、Tag對象屬性
    name 
    attrs  返回一個字典    例如:{'class':'sister'}  #可以操作字段
        def __getitem__(self, key):   return self.attrs[key]
        def has_attr(self, key):    key in self.attrs
    contents
        注意 空格換行等 都包含在contents內
        def __len__(self): return len(self.contents)
        def __contains__(self, x): return x in self.contents
        def __iter__(self): return iter(self.contents)
    string       
            child = self.contents[0]
            if isinstance(child, NavigableString):  #如果tag.contents[0] 為 NavigableString 類型子節點,直接得到子節點
                return child
            return child.string  #如果不是 則獲取子標簽的string屬性
    children 
        ==  iter(self.contents)
    next_element 和 previous_elemen
        如同字面意思,前一個ele和后一個ele
        next_elements 和 previous_elements
            當前Tag前面和后面ele的迭代器
    descendants
        迭代器,從contents[0] 然后.next_element直到.next_sibling.previous_element        
    strings 和 stripped_strings  
        迭代器
        for descendant in self.descendants:
            strings --> 遍歷descendants屬性,獲取所有NavigableString對象
            stripped_strings  --> 遍歷descendants屬性,獲取所有len(descendant.strip()) != 0 的 NavigableString對象
    parent 和 parents
        parent:元素的父節點
        parents:迭代器一直獲取.parent屬性  
    next_sibling 和 previous_sibling
        查詢兄弟節點
        實際文檔中的tag的 .next_sibling 和 .previous_sibling 屬性通常是字符串或空白
        next_siblings 和 previous_siblings 屬性可以對當前節點的兄弟節點迭代輸出
三、通過API獲取Tag對象
    一個Tag可能包含多個字符串或其它的Tag,這些都是這個Tag的子節點.
    1.根據標簽查找(type:bs4_obj)
        tag_p = soup.p  #返回HTML文檔第一個Tag p標簽
    
    2.通過 find 和 find_all
        find(name=None, attrs={}, recursive=True, text=None, **kwargs) 
        #內部調用find_all方法返回第一個Tag    
        find_all(self, name=None, attrs={}, recursive=True, text=None, limit=None, **kwargs)
        #recursive=True 默認會檢索當前tag的所有子孫節點,參數 recursive=False 只檢索子節點
        #limit參數 限制返回數量
        
        #名字為 name 的tag,如果name不是內置的參數名,搜索時會按tag的屬性來搜索注意class的寫法
        soup.find_all("title") or soup.find_all(class_ = 'tb')  or  soup.find_all(id='link2')  
        
        soup.find_all("a", class_="sister") or soup.find_all("a", attrs={"class": "sister"})
        #class_ 參數同樣接受不同類型的 過濾器 ,字符串,正則表達式,方法或 True
        soup.find_all(class_=re.compile("itl"))
        def has_six_characters(css_class):
            return css_class is not None and len(css_class) == 6
        soup.find_all(class_=has_six_characters)  # 過濾其class屬性長度為6的標簽
        # text 參數可以搜搜文檔中的字符串內容,接受 字符串 , 正則表達式 , 列表, True .
        soup.find_all(text=re.compile("Dormouse"))
        soup.find_all("a", text="Elsie")   #包含“Elsie”的<a>標簽
        soup.find_all(text="Elsie")  #返回一個NavigableString對象
        
        #實際上就是對 .children 屬性的迭代搜索
    3.通過soup()
        內部調用find_all方法
        def __call__(self, *args, **kwargs):    return self.find_all(*args, **kwargs)
    4.通過find_parents() 和 find_parent()
        find_parent(self, name=None, attrs={}, **kwargs)  #搜索當前節點的第一個父節點
        find_parents(self, name=None, attrs={}, limit=None, **kwargs) #搜索當前節點的所有父節點,父父節點等
        #實際上就是對 .parents 屬性的迭代搜索
    5.通過find_previous_siblings() 和 find_previous_sibling(): #一個與多個(list)
        find_previous_siblings(self, name=None, attrs={}, text=None, limit=None, **kwargs)
        #實際上就是對 .previous_siblings 屬性的迭代搜索
    6.通過find_all_next() 和 find_next():
        find_all_next(self, name=None, attrs={}, text=None, limit=None, **kwargs)
        #實際上就是對 .next_elements 屬性的迭代搜索
    7.通過find_all_previous() 和 find_previous():
        find_all_previous(self, name=None, attrs={}, text=None, limit=None, **kwargs)
        #實際上就是對 .previous_elements 屬性的迭代搜索
四、通過CSS選擇器獲取Tag對象
    (1)通過標簽名查找:
        soup.select('a')  #返回所有的a標簽  list
    (2)通過類名查找:
        soup.select('.sister') #返回所有包含class="sister"的標簽  list
        soup.select('a.sister')
    (3)通過 id 名查找:
        soup.select('#link1')  #返回所有包含 id="link1"的標簽  list
        soup.select("p#link1")
    (4)組合查找:
        soup.select('p #link1')  #查找所有 p 標簽中,id 等於 link1的標簽  注意區分soup.select('p#link1')
        soup.select("html head title") or soup.select("body a")   #逐層查找    
        soup.select("p > a")  #直接子標簽查找  注意是子標簽不是子孫標簽
    (5)通過是否存在某個屬性和屬性的值來查找:
        soup.select('a[href]')
        soup.select('a[href="http://example.com/elsie"]')
        soup.select('a[href^="http://example.com/"]')    #  ^=  開頭
        soup.select('a[href$="tillie"]')                #  $=  結尾
        soup.select('a[href*=".com/el"]')               #  *=  包含
五、解析部分文檔
    將整片文檔進行解析,實在是浪費內存和時間.最快的方法是從一開始就把想要獲取以外的東西都忽略掉.
    SoupStrainer 類可以定義文檔的某段內容,這樣搜索文檔時就不必先解析整篇文檔。
    三種SoupStrainer 對象:
        from bs4 import SoupStrainer
        only_a_tags = SoupStrainer("a")  #把<a>標簽以外的東西都忽略掉
        
        only_tags_with_id_link2 = SoupStrainer(id="link2") #把屬性id="link2"標簽以外的東西都忽略掉
        
        def is_short_string(string):
            return len(string) < 10
        only_short_strings = SoupStrainer(text=is_short_string) #把文本內容長度大於等於10的標簽都忽略掉
    
    將 SoupStrainer 對象作為 parse_only 參數給 BeautifulSoup 的構造方法即可
        print(BeautifulSoup(html_doc, "html.parser", parse_only=only_a_tags).prettify())

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM