網絡爬蟲: 從allitebooks.com抓取書籍信息並從amazon.com抓取價格(1): 基礎知識Beautiful Soup


開始學習網絡數據挖掘方面的知識,首先從Beautiful Soup入手( Beautiful Soup是一個Python庫,功能是從HTML和XML中解析數據),打算以三篇博文紀錄學習Beautiful Soup的過程, 第一篇是Beautiful Soup基礎知識,後兩篇利用前邊的Beautiful Soup知識 完成一個簡單的爬蟲,抓取allitebook.com的書籍信息和ISBN碼,再根據ISBN碼去amazon.com抓取書籍對應的價格

1、Beautiful Soup簡介

網絡數據挖掘指的是從網站中獲取數據的過程,數據挖掘技術可讓咱們從網站世界中收集大量有價值的數據。
Beautiful Soup是一個Python庫,能夠從HTML或XML文件中獲取數據,利用它你能夠作不少事情,好比你能夠持續解析某個商品的最新價格,以便跟蹤價格的波動狀況。

2、Beautiful Soup安裝(Mac)

安裝Beautiful Soup
sudo pip3 install beautifulsoup4
 
檢驗是否安裝成功
from bs4 import BeautifulSoup

 

3、建立一個Beautiful Soup對象

html_atag = """<html><body><p>Test html a tag example</p>
<a href="http://www. allitebook.com">Home</a>
<a href="http://www.allitebook.com/books">Books</a>
</body>
</html>"""
soup = BeautifulSoup(html_atag, "html5lib")
print(soup.a)

 

4、查找內容

find()方法
在find()方法中傳入節點名,例如ul,這樣就能夠獲取第一個匹配的ul節點的內容,例如:
#input
html_markup = """<div>
<ul id="students">
<li class="student">
<div class="name">Carl</div>
<div class="age">32</div>
</li>
<li class="student">
<div class="name">Lucy</div>
<div class="age">25</div>
</li>
</ul>
</div>"""
student_entries = soup.find("ul")
print(student_entries)

#output
<ul id="students">
<li class="student">
<div class="name">Carl</div>
<div class="age">32</div>
</li>
<li class="student">
<div class="name">Lucy</div>
<div class="age">25</div>
</li>
</ul>

 找到ul節點後,經過觀察html能夠得知,ul下有2個li,每一個li下有2個div,則經過student_entries.li能夠獲取第一個li節點的數據,繼續經過student_entries.li.div能夠獲取第一個li下第一個div的數據,例如:html

#input
print(student_entries.li)
#output
<li class="student">
<div class="name">Carl</div>
<div class="age">32</div>
</li>

#input
print(student_entries.li.div)
#output
<div class="name">Carl</div>
繼續經過div.string能夠獲取div的內容:
#input
print(student_entries.li.div.string)
#output
'Carl'

 

使用正則表達式查找:
find()方法支持根據正則表達式查找內容,例如:
#input
import re
email_id_example ="""<div>The below HTML has the information that has email ids.</div>
abc@example.com
<div>xyz@example.com</div>
<span>foo@example.com</span>"""
soup = BeautifulSoup(email_id_example,"lxml")
emailid_regexp = re.compile("\w+@\w+\.\w+")
first_email_id = soup.find(text=emailid_regexp)
print(first_email_id)

#output
abc@example.com

 

find_all()方法
find()方法返回第一個匹配的內容,find_all()方法會返回全部匹配的內容列表,例如上面的根據正則表達式查找郵箱地址,將find()方法換成find_all()方法,則會返回全部匹配成功的內容:
#input
all_email_id = soup.find_all(text=emailid_regexp)
print(all_email_id)

#output
['abc@example.com', 'xyz@example.com', 'foo@example.com']

 

find_parent()方法
find_parent()方法往上查找內容,例如,從第一個li節點上使用find_parent()方法,能夠獲取父節點的內容:
#input
print(first_student)

#output
<li class="student">
<div class="name">Carl</div>
<div class="age">32</div>
</li>

#input
all_students = first_student.find_parent('ul')
print(all_students)

#output
<ul id="students">
<li class="student">
<div class="name">Carl</div>
<div class="age">32</div>
</li>
<li class="student">
<div class="name">Lucy</div>
<div class="age">25</div>
</li>
</ul>

 

find_next_sibling()方法
sibling是兄弟姐妹的意思,find_next_sibling()方法獲取下一個同級別的兄弟節點,例如:
#input
second_student = first_student.find_next_sibling()
print(second_student)

#output
<li class="student">
<div class="name">Lucy</div>
<div class="age">25</div>
</li>

 

其它方法還有不少,例如:
find_next()方法
find_all_next()方法
find_previous_sibling()方法
find_all_previous()方法
用法都差很少,這裏再也不一一贅述,具體請查看官方文檔: https://www.crummy.com/software/BeautifulSoup/bs4/doc/#searching-the-tree

5、瀏覽內容

瀏覽子節點
使用子節點的標籤名便可獲取子節點的內容,例如:
#input
print(first_student)

#output
<li class="student">
<div class="name">Carl</div>
<div class="age">32</div>
</li>

#input
name = first_student.div
print(name)

#output
<div class="name">Carl</div>

 

瀏覽父節點
使用.parent屬性能夠瀏覽父節點,例如:
#input
print(name.parent)

#output
<li class="student">
<div class="name">Carl</div>
<div class="age">32</div>
</li>

 

瀏覽兄弟節點即同級節點,next_sibling和previous_sibling屬性分別獲取上一個和下一個兄弟節點。例如:
#input
print(first_student.next_sibling)

#output
<li class="student">
<div class="name">Lucy</div>
<div class="age">25</div>
</li>
 
和瀏覽相關的完整方法列表請查看: https://www.crummy.com/software/BeautifulSoup/bs4/doc/#navigating-the-tree

6、修改內容

修改標籤的名字
能夠經過.name屬性獲取某個節點的標籤名,一樣將某個標籤名賦值給.name屬性能夠很輕易改變標籤的名稱,例如:
#input
first_student
#output
<li class="student">
<div class="name">Carl</div>
<div class="age">32</div>
</li>

#input
first_student.name
#output
'li'

#input
first_student.name = 'div'
first_student.name
#output
'div'

#input
first_student
#output
<div class="student">
<div class="name">Carl</div>
<div class="age">32</div>
</div>

 

修改標籤的屬性
#input
first_student['class'] = 'student_new'
print(first_student)
#output
<div class="student_new">
<div class="name">Carl</div>
<div class="age">32</div>
</div>
注意:若是class屬性沒有的話,則此操做不會報錯,而變爲一個新增操做。

刪除一個標籤的屬性
使用del方法能夠將一個節點的某個屬性刪除。例如:
#input 
del first_student['class']
print(first_student)

#output
<div>
<div class="name">Carl</div>
<div class="age">32</div>
</div>

 

修改標籤的內容
使用.string屬性能夠獲取標籤的內容值('Carl'),一樣,對此屬性的賦值操做也能夠更該其值,例如:
#input
print(first_student.div.string)

#output
Carl

#input
first_student.div.string = 'carl_new'
print(first_student.div.string)

#output
carl_new

 

直接刪除某個節點
使用decompose()方法能夠直接刪除某個節點:
#input 
print(first_student)
#output
<li class="student">
<div class="name">carl_new</div>
<div class="age">32</div>
</li>

#input 
first_student.div.decompose()
print(first_student)
#output
<li class="student">
<div class="age">32</div>
</li>
使用extract()方法一樣能夠刪除某個節點,不過它和decompose()方法不一樣的是,extract()會返回被刪除的這個節點的內容。
 
咱們處於大數據時代,對數據處理感興趣的朋友歡迎查看另外一個系列隨筆: 利用Python進行數據分析 基礎系列隨筆彙總
 
接下來將利用這篇的Beautiful Soup基礎知識完成一個簡單的爬蟲,分別獲取兩個網站的書籍信息和價格並組合在一塊兒並輸出到csv文件中。有興趣的朋友歡迎關注本博客,也歡迎你們留言進行討論。
 
大數據,大數據分析、BeautifulSoup,Beautiful Soup入門,數據挖掘,數據分析,數據處理,pandas,網絡爬蟲,web scraper
相關文章
相關標籤/搜索