Python之爬取網頁時遇到的問題——BeautifulSoup


Python之爬取網頁時遇到的問題——BeautifulSoup

     https://cuiqingcai.com/1319.html
http://cuiqingcai.com/1319.html    ,    http://blog.csdn.net/akak714/article/details/50130743

 


http://cuiqingcai.com/1319.html

http://blog.csdn.net/akak714/article/details/50130743

 

參考地址:Python爬蟲入門之BeautifulSoup

【beautifulsoup是用來做什么的】

首先,我們回顧一下beautifulsoup的作用。

我們接觸到這個Python模塊,是在寫Python爬蟲腳本時。

用來分析所抓取網頁的HTML代碼,以方便的從大量的HTML代碼中找到我們所需要的數據信息。

比單純使用正則表達式,方便了許多。

【構造soup對象】

以我們之前寫過的諸多代碼做基礎,構造一個soup對象出來,然后才能夠進行解析。

from bs4 import BeautifulSoup
mainUrl="http://www.bilibili.com/online.html"
'''進入在線列表頁面'''
resp=urllib2.urlopen(mainUrl)
html = resp.read().decode('utf-8').encode('gbk')
soup = BeautifulSoup(html, "html.parser", from_encoding="gbk")
構造成功。將返回的網頁代碼構造為一個可以解析的soup對象。
【拿到第一個標簽的內容】

我們可以通過指定soup對象的標簽,拿到該標簽的第一個內容。如:

soup = BeautifulSoup(html, "html.parser", from_encoding="gbk")
print soup.title
打印結果如下:
<title>褰撳墠鍦ㄧ嚎 - 鍝斿摡鍝斿摡寮瑰箷瑙嗛緗� - ( 銈�- 銈�)銇ゃ儹 涔炬澂~ - bilibili</title>

我們發現亂碼了,可以將其轉換為string類型然后在decode一下

print str(soup.title).decode('utf-8')
打印結果如下:
<title>當前在線 - 嗶哩嗶哩彈幕視頻網 - ( ゜- ゜)つロ 乾杯~ - bilibili</title>

 

這種soup.tag的方式,只能夠拿到html代碼中的第一個標簽的內容。

【Tag的屬性】

每個Tag,都有兩個重要的屬性,name和attrs

print soup.p
print soup.p.name
print soup.p.attrs
打印出的結果如下:

<p class="etitle">銆愮洏鐐廣�戣繎騫村湪B絝欑湅涓嶅埌鐨�8澶у己鐣�</p>
p
{u'class': [u'etitle']}
name,即是標簽名

attrs,顧名思義是屬性的意思,打印出改tag所具有的屬性名以及屬性值。

什么算一個標簽呢?<p></p>這就算一組標簽了,其中再加上class="etitle",這就屬於p標簽的一個屬性,我們還可以給標簽添加更多的屬性及對應的屬性值。

當然,很多標簽實際使用時,大多是有屬性的。

【獲取某標簽的某屬性值】

我們知道了一個標簽可能會有很多個屬性,對應也會有很多個屬性值。

如果我們想取得確定屬性的值。怎么做呢?

print soup.p['class']
直接打印出屬性值:[u'etitle']
【獲取標簽內部的字符串】

使用.string

print str(soup.p).decode('utf-8')
print soup.p.string
打印結果如下:
<p class="etitle">【盤點】近年在B站看不到的8大強番</p>
【盤點】近年在B站看不到的8大強番

我們發現,直接打印p.string,不亂碼

 

【獲取標簽的所有內容】

直接打印soup.tag只能拿到第一個,接下來我們來拿到所有!

使用soup對象的find_all函數

print soup.find_all('p')
print len(soup.find_all('p'))
打印結果如下:
[<p class="etitle">\u301。。。 bc1\uff1a<span>0910417</span></p>]
45

打印出了所有的p標簽內容。共45個p標簽。

【find_all函數的使用】

我們可以使用find_all函數找到所有標簽,當然也可以根據標簽名以及屬性來找到我們需要的標簽。

這時需要在find_all函數中傳遞對應參數。

【name參數】

傳字符串:

print soup.find_all('p')
傳正則表達式:

print soup.find_all(re.compile('^b'))
傳遞正則表達式時,需要引入Python的re模塊。
import re
提供對正則表達式的支持
傳列表:

print soup.find_all(['p','head'])
查出p標簽和head標簽的所有內容。即,同時查多種標簽。
當然還可以傳別的,這里不再贅述。基本用不到的就不說了。

【keyword函數】

按屬性以及屬性值來搜索值。

print soup.find_all(class_="ebox")
print len(soup.find_all(class_='ebox'))
打印結果如下:
[<div class="ebox" typeid="27"><a href="/video/av3297224/" target="_blank" title="\u3010\u76d8\u70b9\u3011\u8fd1\u5e74\u5728B\u7ad9\u770b\u4e0d\u5230\u76848\u5927\u5f3a\u756a"><img 。。。。。u5728\u7ebf</p></div>]
20

共20個ebox。

【注意】這里注意,因為class是Python的關鍵詞,所以在class后加下划線

這里雖然能夠找出來,但find_all函數有一個問題,就是中文編碼。

我們之前使用find_all函數尋找所需要的數據的時候,中文總是亂碼。find_all這個函數會把查出來的字符串搞亂,所以是有一定局限性的。

甚至最終我們都沒有使用find_all函數!

 

【CSS選擇器】

我們最終決定使用的是soup.select函數,又叫CSS選擇器。

我們使用CSS選擇器來尋找符合要求的數據。

soup.select()找到的數據,返回為list類型,即,尋找到的是所有符合要求的數據。

查找方式如下:

【通過標簽名查找】

print soup.select('div')
直接返回所有div標簽的所有內容

【通過類名查找】

print soup.select('.ebox')
print len(soup.select('.ebox'))
. 這個點表示查詢class="ebox"的,所有標簽內容
可以查詢出20條數據。

【通過id名查找】
————————————————
版權聲明:本文為CSDN博主「AKAK714」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/akak714/java/article/details/50130743

 

 

 

記下兩個與本文內容不太相關的知識點。

     import re   對正則表達式支持的包。

     str(soup.p).decode('utf-8')     對標簽內容轉碼。

 

     Beautiful Soup 是用Python寫的一個HTML/XML的解析器,它可以很好的處理不規范標記並生成剖析樹。 它提供簡單又常用的導航,搜索以及修改剖析樹的操作。它可以大大節省你的編程時間。

    

     通俗的來說,就是在

            req = urllib2.Request(url, headers=headers)
            page = urllib2.urlopen(req, timeout=60)
            contents = page.read()

    之后,對contents進行解析  soup = BeautifulSoup(contents, 'html.parser'),這樣構建的是Python標准庫,然后我們便可以對這個soup對象進行一系列的操作,提取我們所需要的元素。

    我們對用法進行一下解釋:

    soup.title    得到的是<title>標簽,以及標簽里的內容。但是得到的是所有<title>標簽中的第一個。<title>這里是內容</title>,紅字部分。

    soup.title.name    得到的是<title>標簽的name屬性的值。得到的是所有<title>標簽中的第一個。

    soup.title.string    得到的是<title>開始和結束標簽之間的值。<title>這里是內容</title>,即紅字部分。得到的是所有<title>標簽中的第一個。

    soup.find_all('title')     得到所有標簽為<title>的的標簽,以及標簽里的內容。返回的是一個序列,可以對它循環,得到自己想要的東西。

    soup.find(id='3')     得到id為3的標簽。

    soup.p.get_text()    返回的是<p>標簽的文本。

    soup.a['href']          返回<a>標簽的 herf 值 。

    soup.head.contents      獲得head下的所有子孩子。以列表的形式返回結果,可以使用 [num]  的形式獲得 。獲得標簽,使用.name 就可以。

    print soup.find_all(text="Elsie")     獲得文本為Elsie的標簽。

    print soup.find_all("a", limit=2)       返回兩個<a>標簽。

    string屬性,如果超過一個標簽的話,那么就會返回None,否則就返回第一個標簽的string。超過一個標簽的話,可以試用strings。

    獲取標簽的孩子,可以使用children,但是不能print soup.head.children,沒有返回列表,返回的是 <listiterator object at 0x108e6d150>,不過使用list可以將其轉化為列表。可以使用for 語句遍歷里面的孩子。

     向上查找可以用parent函數,如果查找所有的,那么可以使用parents函數。

     查找下一個兄弟使用next_sibling,查找上一個兄弟節點使用previous_sibling,如果是查找所有的,那么在對應的函數后面加s就可以。

 

     soup.select()找到的數據,返回為list類型,即,尋找到的是所有符合要求的數據。

 

      soup.select('div')     直接返回所有div標簽的所有內容

      soup.select('.ebox')      . 這個點表示查詢class="ebox"的,所有標簽內容。

      len(soup.select('.ebox'))      可以查詢出20條數據。

      soup.select('#index_nav')      查找所有id為 index_nav 的標簽。

      soup.select('div #index_nav')    表示尋找div標簽中id為index_nav的標簽內容。

      soup.select('p[class="etitle"]')     查找所有class為etitle的<p>標簽。

 

 

http://cuiqingcai.com/1319.html    ,    http://blog.csdn.net/akak714/article/details/50130743   這兩個網址可以學習一下。


免責聲明!

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



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