Python 從零開始爬蟲(二)——BeautifulSoup解析網頁

學了requests,瞭解了假裝技巧後,終於能爬到些比較正常的網頁源碼(html文檔)了,但這離結果還差最後和是最重要的一步——篩選。這個過程就像在泥沙中淘金同樣,沒有合適的篩子,你就會把有價值的漏掉了,或者作了無用功把沒用的也篩了出來。
淘金者看土質,作篩子。對應到爬蟲領域就是觀察html,定製篩選器html

稍稍瞭解HTML

信息都在網頁源碼裏,瀏覽器經過解析源碼來加載咱們所看到的東西,那咱們是否是也應該學下如何看源碼呢?——是的html5

但不要方,這不是html語法課,作爬蟲的,只需瞭解一下html的原理和標籤關係就好了,這跟認親戚同樣簡單,你會看家族樹的話根本不成問題。python

<?xml version="1.0" encoding="ISO-8859-1"?>

<bookstore>

    <book>
      <title lang="en">Harry Potter</title>
      <author>J K. Rowling</author> 
      <year>2005</year>
      <price>29.99</price>
    </book>

</bookstore>


有時候會堆成一行,影響觀察但不影響使用,丟到排版器排一下就行了
<bookstore><book><title lang="en">Harry Potter</title><author>J K. Rowling</author<year>2005</year><price>29.99</price></book></bookstore>

這是個很是短的示例html,但足以解釋全部節點關係。正則表達式

  • <bookstore>,<book>這些有尖括號的叫作標籤(或節點),成對存在。bookstore,book是標籤名,標籤間能夠放字符串。
  • 標籤能夠擁有屬性,屬性在尖括號裏,如title標籤有名爲lang的屬性,屬性值爲"en"。
  • A節點被B節點包起來,A就是B的子,或B是A的父。如book和title都是是bookstore的子,可是book是bookstore的直接子(只有一層包含關係)
  • 有同一個直接父的標籤互相爲兄弟,如title,author,year,price互爲兄弟。

BeautifulSoup

慣例貼上官方文檔
煲靚湯嘛!
把html文檔轉換爲可定位的樹結構,並提供索引,查找,修改(對爬蟲沒什麼用)功能。
圖片描述ubuntu

安裝

煲湯模塊瀏覽器

  • ubuntu下:apt-get install Python-bs4
  • win下:pip install beautifulsoup4

若是你還須要使用第三方解釋器lxml或html5lib,那也安裝一下spa

  • apt-get install Python-lxml(/html5lib)
  • pip install lxml(/html5lib)

標籤索引

Beautiful Soup將複雜HTML文檔轉換成一個複雜的樹形結構,每一個節點都是一個對象,全部對象能夠概括爲4種: Tag(標籤) , NavigableString(字符串), BeautifulSoup(湯) , Comment(註釋) , 知道就行.code

  • BeautifulSoup類接收2個參數,第一個是html文檔,第二個是解釋器名,不寫的話會自動選擇。實例化後生成樹結構,這裏順便附上各類解釋器比較
    圖片描述xml

    from bs4 import BeautifulSoup#注意不是直接導入beautifulsoup4
    r = requests(......)
    soup = BeautifulSoup(r.text,"lxml")
  • Tag(標籤)類,包含該標籤的全部內容,有多種方法用於索引元素/獲取字符串(下面的tag,tag1指的是標籤名soup至關於最大的Tag對象
  • 定位:標籤訂位,previous_sibling/next_siblinghtm

    tag2 = soup.tag1.tag2#定位到tag1下的tag2,並將其返回
    tag4 = tag2.tag3.tag4,#標籤對象能夠繼續向下定位
    brother_tag = tag.previous_sibling/next_sibling#定位到該tag的上一個/下一個兄弟標籤並將其返回
    brother_tag = tag.previous_siblings/next_siblings#返回的是生成器,內含多個兄弟標籤。
  • 索引: attrs,中括號索引

    dict1 = tag.attrs #以字典形式返回該tag下的元素及其對應值
    lang = tag["lang"] #返回該tag下的lang屬性的值,和字典索引用法同樣
  • 獲取字符串: string,strings,get_text()

    string = tag.string #僅限於夾在該tag的字符串,不包子的字符串,將每段字符串無縫鏈接後返回。
    #如對`<a>A1<b>BB</b>A2<c>CC</c>A3<d>DD</d>A4</a>`使用a.string返回的是"A1A2A3A4"
    
    strings = tag.strings #以生成器形式返回該tag下(**不包括子**)的**每段字符串**,供for循環使用。
    strings = tag.stripped_strings #來先去除空行/空格再返回生成器
    
    text = tag.get_text(分隔符,strip=False) #返回該tag下(包括全部子孫)的字符串,同一個tag下的字符串無縫鏈接,不一樣tag下字符串間以指定分隔符鏈接,strip默認爲False,改成True時自動去除空行/空格。
  • 以上的方法都是單次定位的,若是有多個符合標準的定位則以出現的第一個爲準!!!
  • 索引和獲取字符串的方法必定是最後用的,由於它再也不返回Tag對象!!!

find_all&find方法

將它們單獨出來是由於它真的過重要太靈活了,它們們能實現某個範圍內的條件定位(不經過父子兄弟關係),返回Tag對象供使用各類索引方法。

  • find()的做用是實現範圍內的單次條件定位
  • find_all()的做用是以可迭代的形式返回範圍內多個符合要求的定位可是你要確保這個標籤對你要的信息具備惟一性。

信息有時是分塊的,這時定位也應分塊,再對每一個分塊使用單次定位,下面是一個最經常使用的篩選器。

for each in soup.find_all(.......):#一般第一句就是用find_all進行分塊
    string = each.find().string #而後在該分塊中使用條件定位,再使用索引方法
    id = each.find()['id']
    ........

find和find_all接收的參數是同樣的,現以find_all爲例:Tag.find_all(name,attrs,recursive,limit,text,*kwards)

  • name:標籤名,定位到指定標籤名的節點如'a'

    • 想匹配多種標籤名可傳列表如['div','a','b']
    • 想自定標籤名規則可傳正則表達式如re.compile(規則)【正則後面再講】
  • **kwards:實際上是標籤裏的屬性及其值,定位到有指定屬性,屬性值的標籤,如.find_all(lang='en')

    • 若是屬性叫class,爲防止與類的「class」衝突要在後面加下橫線,如.find_all(class_='sakura')
    • 能夠設立多個條件如.find_all(class_='sakura',lang='en')
    • 屬性值能夠用傳正則表達式如.find_all(lang=re.compile(r''))
  • recursive:默認True,檢索當前tag下的全部子孫標籤。設置爲False時只檢索當前tag下的直接子標籤
  • limit:設置匹配上限,接收天然數,決定了有效定位的數量上限。
  • text:搜索文檔中的字符串內容,返回匹配字符串的列表,可接收字符串,字符串列表和正則表達式(這個極少用到,一般不理)

到這裏BeautifulSoup的主要用法都總結完了,全是文字沒有實例可能會有些難啃,可是下一篇會放出幾個實例出來讓你們體驗一下它的用法,到時就比較好理解了。動手能力強的話,如今就能夠開是搗鼓些小爬蟲出來啦,加油,頑張って。!!!!!!!!!!!!!記得常按F12看html源碼啊!!!!!!!!!!!!!!

相關文章
相關標籤/搜索