網路爬蟲(web crawler),也叫網路蜘蛛(spider) 是一個強大的自動化工具,可以自由瀏覽、擷取訪問網頁的各項資訊,例如:新聞文章、電商商品價格,當專案中需要添加外部數據或進行大量資料收集時,網路爬蟲就是一個非常實用的工具。
這篇主要說明爬蟲的基礎概念原理、以及爬蟲常用的 package ,最後實作爬取運動視界的文章為範例,那我們開始吧 😝
基本概念是: 透過程式模擬瀏覽網頁訪問的行為,例如: 上下捲動頁面、登入、點選…等動作,然後自動化從網頁擷取想要的資訊,資訊可以是文字、圖片、表格,或是網站上的各種內容。
實際的技術行為是,爬蟲(自動化的程式),透過網路的傳輸協定(HTTP/HTTPS)發送請求到目標網站,然後目標網站的伺服器會 return 網頁的原始碼(HTML) 。這些原始碼就包含了網頁的內容,而我們可以利用 HTML Tag 去提取與篩選需要的資訊。
可以把他簡化成兩個步驟以及其對應的套件
1. 對目標網站伺服器發送請求 -> requests
2. 解析返回的網頁 html -> beautifulsoup4
pip install requests
pip install beautifulsoup4
我們選擇運動視界作為目標網站 : https://www.sportsv.net/basketball
這個頁面是一個所有文章的列表,他包含多篇文章在這個頁面上,那實作的測略為:
1. 先爬取此頁的所有文章連結
2. 再到每一個文章的頁面爬取該文章的標題與內文
另外為保留未來多支爬蟲運行,且有相同功能的 function 可以沿用與好管理,我們把程式的架構分成兩個部分和多個 function,架構為:
因為每個網站爬取的方式不太相同,要取的 tag 會不同,所以我們以獨立的 Crawler 去管理各個網站的爬蟲,但因為他們有一些功能會相同並且沿用,所以先以 BaseCrawler 定義基礎 fucntion ,並讓未來 Class 可以繼承。
# crawler.py
import os
import requests
from tqdm import tqdm
from datetime import datetime
from bs4 import BeautifulSoup
class BaseCrawler:
def __init__(self, root_url, topic_url):
self.root_url = root_url
self.topic_url = topic_url
def send_http_request(self, url):
response = requests.get(url)
return response
def parse_html(self, response):
soup = BeautifulSoup(response.text, 'html.parser')
return soup
def save_data(self, folder_path, title, content):
# check title and data is str
if not isinstance(title, str):
title = str(title)
if not isinstance(content, str):
content = str(content)
# check file exist
if not os.path.exists(folder_path):
os.makedirs(folder_path)
# valid title when it as filename
filename = "".join(c for c in title if c.isalnum() or c.isspace()).rstrip()
file_path = os.path.join(folder_path, f"{filename}.txt")
# save
with open(file_path, "w", encoding="utf-8") as f:
f.write(content)
class SportVisionCrawler(BaseCrawler):
def __init__(self, root_url, topic_url):
self.root_url = root_url
self.topic_url = topic_url
def get_all_links(self, topic_url):
# check request root_url
response = self.send_http_request(topic_url)
if not response.ok:
print("Request failed")
return
if response.ok:
print("Request successful")
soup = self.parse_html(response)
h4_elements = soup.find_all('h4')
link_list = []
for h4_element in h4_elements:
a_element = h4_element.find('a')
if a_element:
link = a_element['href']
link_list.append(link)
return link_list
def crawl(self, link_list):
for link in tqdm(link_list):
response = self.send_http_request(link)
soup = self.parse_html(response)
title = soup.find('h1').text
content = soup.find('div', class_='article-content').get_text(strip=True)
self.save_data('./output_crawl/Sport_vision_crawl',title, content)
if __name__ == "__main__":
print('SportVisionCrawler')
root_url = ''
topic_url = 'https://www.sportsv.net/basketball'
crawler = SportVisionCrawler(root_url, topic_url)
link_list = crawler.get_all_links(topic_url)
crawler.crawl(link_list)
爬取這篇產出的文:
用一顆籃球練出自信與成就感 翻轉孩子的未來舞台.txt
在花蓮,有一群偏鄉孩子與教練透過他們熱愛的籃球運動,實現改變自我的歷程。籃球已成為生活中、呼吸中不可或缺的一部分,在他們人生中扮演重要角色!走進花蓮市區「籃海計畫」比賽現場,熱鬧、快節奏的西洋歌曲將整個賽場的氛圍炒熱最高點,擔任花蓮熱血鳳凰隊副隊長的鄧安,頭一回穿上繡有自己姓名的球衣,不時穿梭在隊伍中,主動帶動氣氛,鼓勵隊友們拿出積極的精神、平日練好的球技,開心、努力地參賽。請繼續往下閱讀在台灣世界展望會的陪伴下 內斂鄧安勇敢蛻變成長Photo credit:TNL Brand Studio他是副隊長鄧安,今年從花蓮縣鳳林國中畢業,即將進入四維高中就讀,從國小與籃球結緣,在籃球場上他看見自己成長與蛻變。來自單親家庭的他,與媽媽一起生活,天生個性比較膽小、安靜,不會主動表達意見,但在鄧安的內心深處就蘊藏著一顆籃球魂。
1. 爬取所有文章列表的連結
2. 從連結在爬取所有標題與內文
3. 設計可擴展的框架,以管理未來新增的爬蟲管道
最近因為對外部數據有需要,而寫爬蟲程式,並且一邊學習一邊實作的過程,很感謝網上豐富的資源、還有 gpt 的協助
這是一個簡單的爬蟲範例,分享給從來沒有使用過爬蟲的人,也可以快速上手跟實作,那當然也有比較複雜的案例,有些網站的機制,可能要多繞幾層才能爬到對應的內容,或需要模擬登入、點擊的動作、甚至是前一頁是否為正常的連結導流的,這都可能成為在爬蟲的過程中需要去解決的問題。
不過覺得也不需要擔心,當爬不到的時候就再去找方法即可!
希望這篇分享有幫助正需要使用爬蟲的你,我們下次見!