Python 以Beautiful Soup 抓取與解析網頁資料,網路爬蟲

Doran Wu
此生故彼生
Published in
7 min readMay 25, 2021
以python下載多個檔案

收到新需求,要把現有放在別家ERP廠商的檔案全部下載下來,之後放到我們自己的家裡,但因為對方廠商不提供檔案全部匯出的服務,就只能我們公司自己來,是個做苦工去一個檔各自點擊下載歸檔,然後有時限完成。

瀏覽了一下,檔案蠻多蠻大的,我想了想,自己可是寫程式的耶!記得Python有這樣爬取資料並下載的功能,雖然之前沒玩過,但這次就是很好的機會練習,雖然要花點時間研究,但我相信完成之後,可以重複利用以及省時絕對值得投資,後續結果是否成功呢?會出現這篇文章就代表成功啦~

需求:於網頁中下載該頁面的檔案,包含音樂檔、圖檔、文檔等類型。

怎麼安裝python環境就請自行搜尋,網路上有很多文章教學,蠻容易的。首先,安裝需要的模組,沒有模組的請使用 pip install <模組名稱> 安裝

Request

為了造訪網頁,需要使用request套件獲得網頁資訊

BeautifulSoup

使用BeautifulSoup解析網頁內容

Time

時間模組中各函數的使用,我們會在迴圈讀取時使用

對網頁解析

從解析出來的資料中,看要用哪些方式來選取需要的內容,以我的需求例子,要取出<a>標籤中的 href 的連結。

用解析後的b來進行選擇內容,這裡有多種方式,可使用find方法,以 HTML 屬性搜尋或CSS的selector來選取,可利用函數prettify()讓印出的內容好看 print(soup.prettify())

find 的各種用法

1.print(soup.find('h2'))
2.print(soup.h2)


1、2 寫法都同


另外一種寫法
suop = find('h2').find('a')
print(soup.text)

可以直接縮寫成以下format

print(soup.h2.a.text)
-------------------------------------------

先取大標籤,轉換成list,再印出tag 'a'

main_titles = soup.find_all('h2')
for title in main_titles:
print(title.a.text)
---------------------------------------------

使用class
soup.find_all('h2', 'card-title')

soup.find_all('h2', {'class': 'card-title'})
soup.find_all('h2', class_='card-title')

-----------------------------------------------


divs = soup.find_all('div', 'content')

for div in divs:
一、使用 text (會包含許多換行符號)
print(div.text)
二、使用 tag 定位
print(div.h6.text.strip(), div.h4.a.text.strip(), div.p.text.strip())
三、使用.stripped_strings
print([s for s in div.stripped_strings])

同時搜尋多種標籤

若要同時搜尋多種 HTML 標籤,可以使用 list 來指定所有的要列出的 HTML 標籤名稱:

# 搜尋所有超連結與粗體字
tags = soup.find_all(["a", "b"])
print(tags)
----[<a href="/my_link1" id="link1">Link 1</a>, <a href="/my_link2" id="link2">Link 2</a>, <b class="boldtext">Bold Text</b>]

限制搜尋節點數量

find_all 預設會輸出所有符合條件的節點,但若是遇到節點數量很多的時候,就要花比較久的計算時間,如果不需要所有符合條件的節點,可以用 limit 參數指定搜尋節點數量上限值,這樣就只找出限制符合條件的節點:

# 限制搜尋結果數量
tags = soup.find_all(["a", "b"], limit=2)
print(tags)
----[<a href="/my_link1" id="link1">Link 1</a>, <a href="/my_link2" id="link2">Link 2</a>]

如果只抓出第一個符合的節點,可直接使用 find

# 只抓出第一個符合條件的節點
a_tag = soup.find("a")
print(a_tag)
<a href="/my_link1" id="link1">Link 1</a>

遞迴搜尋

預設的狀況下,find_all 會以遞迴的方式尋找所有的子節點:

# 預設會以遞迴搜尋
soup.html.find_all("title")
[<title>Hello World</title>]

如果想要限制 find_all 只找尋次一層的子節點,可以加上 recursive=False 關閉遞迴搜尋功能:

# 不使用遞迴搜尋,僅尋找次一層的子節點
soup.html.find_all("title", recursive=False)
[]

更多搜尋方法,請參考Python 使用 Beautiful Soup 抓取與解析網頁資料,開發網路爬蟲教學

發現網址不是完整的,可能是相對的,所以要拼湊出來,要把前面網址補上,所以要加上headers

Python使用open()打開檔案

f = open('檔案或路徑', '模式')

模式

r — 讀取(檔案需存在)

w — 新建檔案寫入(檔案可不存在,若存在則清空)

a — 資料附加到舊檔案後面(游標只在EOF)

r+ — 讀取舊資料並寫入(檔案需存在且游標只在開頭)

w+ — 清空檔案內容,新寫入的東西可在讀出(檔案可不存在,會自行新增)

a+ — 資料附加到舊檔案後面(游標只在EOF),可讀取資料

b — 二進位模式

寫入檔案內容

f.write(string) - 寫入檔案,並回傳寫入的string長度ex:
f.write('今年天氣真正好,太陽微笑!')

整個程式完成了大量下載檔案的所有程序,完整程式碼如下:

更多參考資料:

[Python爬蟲教學]有效利用Python網頁爬蟲幫你自動化下載圖片

[python爬蟲]從網頁上下載大量檔案

程式碼上傳好用網站carbon

--

--