### Python是什麼? Python 是種廣泛使用的程式設計語言,用於 Web 應用程式、軟體開發、資料科學與機器學習。由於 Python 效率高又容易學習,且可以在許多不同的平台上執行,因此許多開發人員選擇使用 Python 。 ### Python主要特點 * **縮排**:縮排不只為了排版,也是定義程式碼塊的一種方式,讓 Python 程式碼易於閱讀和維護。 * **直譯語言(Interpreted language)**:Python 在主機上運行時無須編譯,開發過程時可以快速地編寫和測試。 * **弱型別(weak typing)**:宣告變數時無須指定型別,而是根據值來推斷。雖然可以加快編寫速度,但也可能增加出錯風險。 * **豐富的標準函式庫(standard library)和第三方函式庫(third-party library)**:可以幫助工程師快速開發。標準函式庫包括操作作業系統、網路程式設計、多執行緒、數據處理等,而第三方函式庫則包括數據庫、科學計算、機器學習等。 ### 與其他程式語言比較 | | Python | JavaScript | C# | SQL | | ---- | ------------------------------------------ | -------------- | ----------------------------------------- | -------------- | | 排版 | 縮排、冒號 | 大括弧、分號 | 大括弧、分號 | 無 | | 型別 | 弱型別 | 弱型別 | 強型別 | 弱型別 | | 類型 | 指令式程式設計 | 指令式程式設計 | 指令式程式設計 | 宣告式程式設計 | | 應用 | 網頁、數據分析、自動化、遊戲、應用程式開發 | 網頁前端、後端 | 各種App,如網站、遊戲、手機 App、電腦 App | 資料庫 | > 命令式程式設計(Imperative Programming)與宣告式程式設計(Declarative Programming) 分別是什麼? > > 這是兩種不同的程式設計典範(Programming Paradigm),也就是不同風格的程式設計方式。 > > ◆ 命令式程式設計:描述電腦所需作出的行為,例如:Python、JavaScript、C#。 > ◆ 宣告式程式設計:表達計算的邏輯而不用描述控制流程,例如:SQL、HTML、Regular expression(正規表示式)。 > > 簡單來說,多數情況下程式語言需要用一大段程式才可實踐一個功能,而在 SQL 上只需要一個語句就可以表達。這邊也再提供一個很生動的敘述([參考文章](https://ithelp.ithome.com.tw/articles/10288311?sc=iThelpR)): ### 爬蟲是什麼?需要用到什麼概念? 爬蟲可以模擬人類瀏覽網頁的過程,並將資料存取下來使用。可以應用在取得天氣資訊、股票價格、匯率、建立網站索引等。在寫爬蟲程式時,具備以下先備知識可加快學習: * 網頁基礎知識:了解HTML、CSS和JavaScript的基礎語法和結構,可以幫助開發者更好理解和分析網頁。 * 網路協定:了解HTTP、HTTPS等網路協定,可以更好理解網路資源的請求過程。 * 程式語言:熟悉至少一種語言,例如:Python、Java、JavaScrip t等,可以幫助開發者更好撰寫爬蟲程式。 ### 程式碼範例 *目標網站與預覽圖:待補。* 爬蟲程式碼可以分為以下五個部分: 1. 導入所需模組:引入需要用到的模組,幫助我們進行 HTTP 請求、建立資料與處理資料。 * urllib.request 用於從網路上獲取資源。 * bs4 用於解析 HTML 資料。 * csv 用於操作 CSV 檔案。 * os 用於檔案路徑相關操作。 * urllib.parse.quote() 用於將 URL 中的特殊字符進行轉換。 **這幾個導入的步驟要寫耶** ```python= # 安裝 Python 2 的 Beautiful Soup 4 模組 pip install beautifulsoup4 # 安裝 Python 3 的 Beautiful Soup 4 模組 pip3 install beautifulsoup4 ``` ```python= import urllib.request as req import bs4 import os import csv from urllib.parse import quote ``` 2. 獲取目標網站 HTML 資料 使用 req 模組發送 HTTP 請求,需要指定需要獲取的頁面 URL,並用 urlopen() 打開指定的 URL。read() 用於讀取網頁內容;decode() 將編碼為 utf-8 的位元組流轉換為字串,否則中文會亂碼。 取得網站內容後,使用 BeautifulSoup 解析 HTML:用 BeautifulSoup() 創建一個 BeautifulSoup 對象,並指定解析器 html.parser。接著要取出指定的 DOM 物件,故先來觀察網站的HTML結構: *用開發者工具看網頁結構,圖片待補* 可發現每一個最新消息都放在名為「accordion-item」的div裡面。因此用 find_all('div’, ‘accordion-item’) 來找指定的 HTML 標籤。 ```python= url = "https://.../" with req.urlopen(url) as response: data = response.read().decode("utf-8") soup = bs4.BeautifulSoup(data, 'html.parser') news_items = soup.find_all('div', 'accordion-item') ``` 3. 建立存放檔案的資料夾 如果目錄不存在就建立一個新的目錄;os.path.exists() 用於檢查目錄是否存在,os.makedirs() 用於創建目錄。 ```python= save_dir = './爬蟲資料夾/' if not os.path.exists(save_dir): os.makedirs(save_dir) ``` 4. 資料寫入 CSV 檔案 開啟一個 CSV 檔案,並寫入表頭;open() 是 Python 中用來開啟檔案的內建函式。用 for 迴圈取出每個項目的資料,需要取出「標題」、「內文」、「內文HTML」、「附件名稱」、「附件HTML」。為了取出這些資料,先觀察網站架構: *網頁結構示意圖,圖片待補* 找到指定的 DOM 物件分別為「標題(button標籤,class為accordion-button)」、「內文(div標籤,class為container)」、「附件名稱(ul標籤,class為list-group)」。其中,附件有可能無,也可能多於一項,因此 news_file_list 做判斷式,如果有內容用迴圈做出附件名稱清單。 text 是用來獲取HTML標籤內的文字內容,strip() 則是將文字內容中的空白(包括換行符號)刪除,以防止文字內容前後有不必要的空格。 ```python= with open(save_dir + '內容.csv', 'w', encoding='utf-8-sig', newline='') as csv_file: csv_writer = csv.writer(csv_file) csv_writer.writerow(['標題', '內文', '內文HTML', '附件名稱', '附件HTML']) for news_item in news_items: news_title = news_item.find('button', 'accordion-button').text.strip() news_content = news_item.find('div', 'container').text.strip() news_content_html = news_item.find('div', 'container') news_file_list = '' news_files = news_item.find_all('ul', 'list-group') if news_item.find('ul', 'list-group') != None: for news_file in news_files: file_name = news_file.find('h6').text.strip() news_file_list += file_name + ',' news_files_html = news_item.find_all('ul', 'list-group') csv_writer.writerow( [news_title, news_content, news_content_html, news_file_list, news_files_html]) ``` 5. 下載附件 取出每個附件的名稱與連結,依所屬最新消息的名稱建立資料夾,並存入檔案。其中,因網址含有中文,需要轉成 ASCII(美國標準資訊交換碼)才可以用,使用 quote() 這個方法轉換。 另外,因為轉換時會將部分網址保留字元轉換掉,因此命一個 safe_chars 的變數帶入 quote() ,代表這些字元不需要進行編碼。 ```python= for news_file in news_files: file_name = news_file.find('h6').text.strip() news_file_list += file_name save_file_dir = './爬蟲資料夾/' + news_title if not os.path.exists(save_file_dir): os.makedirs(save_file_dir) safe_chars = "!#$&'()*+,/:;=?@[]" file_href = 'https://...' + \ quote(news_file.find('a')['href'], safe=safe_chars) with req.urlopen(file_href) as response: content = response.read() with open(save_file_dir + '/' + file_name, "wb") as file: file.write(content) ``` #### 成果 *成果圖片待補* 完整程式碼與註解 ```python= # ==== 導入所需模組 ==== # 用於從網路上獲取資源 import urllib.request as req # 用於解析 HTML 資料 import bs4 # 用於操作 CSV 檔案 import csv # 用於檔案路徑相關操作 import os # 用於將 URL 中的特殊字符進行轉換 from urllib.parse import quote # ==== 從目標網站中獲取 HTML 資料 ==== # 設定網站URL url = "https://.../" # 讀取網頁內容(須解碼中文字);urlopen() 用於打開指定的 URL 資源 with req.urlopen(url) as response: # read() 用於讀取網頁內容;decode() 將編碼為 utf-8 的位元組流轉換為字串 data = response.read().decode("utf-8") # 使用 BeautifulSoup 解析 HTML;BeautifulSoup() 方法用於創建一個 BeautifulSoup 對象,並指定解析器 html.parser soup = bs4.BeautifulSoup(data, 'html.parser') # 找出所有最新消息項目;find_all() 方法用於查找指定的 HTML 標籤 news_items = soup.find_all('div', 'accordion-item') # ==== 建立存放檔案的資料夾 ==== save_dir = './爬蟲資料夾/' # 如果目錄不存在就建立一個新的目錄;os.path.exists() 方法用於檢查目錄是否存在。 if not os.path.exists(save_dir): # os.makedirs() 方法用於創建多層目錄。 os.makedirs(save_dir) # ==== 使用 csv 模組將獲取的最新消息資料寫入 CSV 檔案 ==== # 開啟一個 CSV 檔案,並寫入表頭;open() 是 Python 中用來開啟檔案的內建函式 with open(save_dir + '內容.csv', 'w', encoding='utf-8-sig', newline='') as csv_file: # 建立 CSV 寫入器,寫入表頭 csv_writer = csv.writer(csv_file) csv_writer.writerow(['標題', '內文', '內文HTML', '附件', '附件HTML']) # 遍歷所有最新消息項目,並取出相關資訊 for news_item in news_items: # 取得標題;text 是用來獲取HTML標籤內的文字內容 # strip() 則是將文字內容中的空白(包括換行符號)刪除,以防止 文字內容前後有不必要的空格。 news_title = news_item.find('button', 'accordion-button').text.strip() # 取得內文與內文HTML news_content = news_item.find('div', 'container').text.strip() news_content_html = news_item.find('div', 'container') # 取得附件與附件HTML news_file_list = '' news_files = news_item.find_all('ul', 'list-group') if news_item.find('ul', 'list-group') != None: for news_file in news_files: file_name = news_file.find('h6').text.strip() news_file_list += file_name + ',' news_files_html = news_item.find_all('ul', 'list-group') # 將標題、內文、內文HTML、附件和附件HTML寫入CSV檔案 csv_writer.writerow( [news_title, news_content, news_content_html, news_file_list, news_files_html]) # ==== 下載附件檔案 ==== for news_file in news_files: file_name = news_file.find('h6').text.strip() news_file_list += file_name save_file_dir = './內容/' + news_title # 如果目錄不存在就建立一個新的目錄;os.path.exists() 方法用於檢查目錄是否存在。 if not os.path.exists(save_file_dir): # os.makedirs() 方法用於創建多層目錄。 os.makedirs(save_file_dir) # 排除特殊字符 safe_chars = "!#$&'()*+,/:;=?@[]" file_href = 'https://www.sfea.org.tw' + \ quote(news_file.find('a')['href'], safe=safe_chars) # 下載附件 with req.urlopen(file_href) as response: content = response.read() # "w" 表示文字寫入模式,"b" 表示二進位寫入模式。 "wb" 表示以二進位形式寫入檔案。 with open(save_file_dir + '/' + file_name, "wb") as file: file.write(content) # 印出下載完成訊息 print("==========下載完成==========") ```