收到新需求,要把現有放在別家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網頁爬蟲幫你自動化下載圖片
程式碼上傳好用網站carbon