1. 程式人生 > >網路爬蟲之beautifulsoup

網路爬蟲之beautifulsoup

一個網頁的節點太多,一個個的用正則表示式去查詢不方便且不靈活。BeautifulSouphtml文件轉換成一個屬性結構,每個節點都是python物件。這樣我們就能針對每個結點進行操作。參考如下程式碼
def parse_url():

    try:

        req=urllib2.Request('http://www.xunsee.com/article/8c39f5a0-ca54-44d7-86cc-148eee4d6615/index.shtml')

        fd=urllib2.urlopen(req)html=BeautifulSoup(fd)except urllib2.URLError,e:

        
print e
BeautifulSoup中傳入的就是urlopen中反饋的html網頁。但是出現提示
E:\python2.7.11\python.exe E:/py_prj/test.py
E:\python2.7.11\lib\site-packages\bs4\__init__.py:181: UserWarning: No parser was explicitly specified, so I'm using the best available HTML parser for this system ("lxml"). This usually isn't a problem, but if you run this code on another system, or in a different virtual environment, it may use a different parser and behave differently.
The code that caused this warning is on line 43 of the file E:/py_prj/test.py. To get rid of this warning, change code that looks like this:
 BeautifulSoup([your markup])
to this:
 BeautifulSoup([your markup], "lxml")
  markup_type=markup_type))

這個提示的意思是沒有給BeautifulSoup中傳遞一個解析網頁的方式。有2中方式可以使用:html.parser以及lxml。這裡我們先用html.parser,lxml後面再講。程式碼改成如下就OK了

html=BeautifulSoup(fd,"html.parser")

在解析網頁前,我們先來看幾個概念,標籤,屬性。

比如下面的網頁結構。<ahref=”1.shtml”>第一節</a> 其中a就是標籤,裡面的href就是屬性。第一節就是標籤的內容


BeautifulSoup中查詢屬性的方法如下:

print html.meta.encode('gbk')
print html.meta.attrs
結合如下的程式碼,查詢tag為meta的元素。並列印meta的所有屬性:

得到的結果如下:

E:\python2.7.11\python.exeE:/py_prj/test.py

<meta content="text/html;charset=gbk" http-equiv="Content-Type"/>

{u'content': u'text/html; charset=gb2312',u'http-equiv': u'Content-Type'}

如果想得到某項屬性,可以按照如下的方式:

print html.meta.attrs['content'] 輸出結果是text/html
如果我們想得到標籤的內容也就是文字怎麼辦呢,比如下面的這個方式
print html.title.string.encode('gbk') .string的功能就是得到標籤所對應的文字
但是上面的方法只能找出第一個滿足的標籤,如果網頁中有多個相同名字的標籤該如何區分呢,比如下面的這種場景:有多個span以及a的標籤

那麼就需要另外的方式來獲取。如下程式碼用find_all的方式來獲取所有標籤為a的結構並打印出來
for a in html.find_all('a'):

    print a.encode('gbk')
得到的結果如下,由於太多,只列出了其中一部分。

如果想得到這些節點的內容可以用get_text()的方法。如下:
for a in html.find_all('a'):

    print a.get_text()
如果想得到這些節點的全部屬性,則可以用下面的方法:
for a in html.find_all('a'):

    print a.attrs
如果想得到某個屬性的值,前面的a.attrs返回的是一個字典。比如下面的要獲取class屬性的值,用如下的方法
for a in html.find_all('a'):

    print a.attrs['class']
find_all方法還可以給查詢加限定值:比如想獲取如下所示的<a href=”1.shtml”>的標籤

這裡第一個引數代表標籤名字,第二引數代表屬性名
for a in html.find_all('a',href="1.shtml"):

    print a.encode('gbk')
還可以設定多個引數查詢,比如查詢form這個標籤

for a in html.find_all('form',method="post",target="_blank"):

    print a.encode('gbk')
當然在查詢裡面也可以運用正則表示式,比如re.complie(“a.*”)之類的方法
另外還可以限制查詢的數目:下面的表示式就是獲取前5條查詢結果
for a in html.find_all('a',limit=5):

    print a.attrs['class']
find家族裡面還有find_parents/find_parent查詢父節點。Find_next_siblings()/find_next_sibling()查詢下一個兄弟以及
find_previous_siblings()/find_previous_sibling()查詢前面的兄弟節點。