我們都知道在開發Python網頁爬蟲之前,都要先檢視網頁原始碼,瞭解網頁資料的結構之後才會進行爬取的動作。但是有些網頁在檢視網頁原始碼的時候,會發現找不到網頁上的資料,這就是網站為了防止資料被輕易的爬走,使用JavaScript的技術,動態載入網頁上的資料,讓Python網頁爬蟲無法從網頁原始碼裡面爬取到資料。這篇文章我就用雄獅旅遊網站,來和大家分享Python網頁爬蟲如何爬取JavaScript型網站的資料,其中的爬取步驟如下:
- JavaScript型網頁特性
- Python網頁爬蟲爬取JavaScript網頁資料
- Python網頁爬蟲解析取得的JSON格式資料
一、JavaScript型網頁特性
首先,前往雄獅旅遊的花現釜山鎮海旅遊網頁,如下圖:
假設我們想要爬取網頁下方的每日旅遊行程,如下圖:
如果檢視網頁原始碼,會發現無法在網頁原始碼裡面找到景點的名稱,這時候就可以開啟開發者模式(滑鼠右鍵 / 檢查),切換到Network(網路)頁籤,並且按下Ctrl + R重新整理網頁,使用網頁資料當關鍵字搜尋,是否有利用JavaScript撈取網頁資料的請求,如下圖:
搜尋到之後,在Preview(檢視)頁籤底下,就可以看到JavaScript回傳的結果,其中的DailyList欄位,就是每天的行程資料,如下圖:
我們點開第一天的行程,可以看到AttractionsList欄位,就是當天的行程清單,其中的Name欄位是景點名稱,如下圖:
接下來切換到Headers(標頭)頁籤,可以看到它的請求網址(Request URL)和請求方法(Request Method),這也就是Python網頁爬蟲爬取JavaScript網頁資料所要發送的請求網址和方法,如下圖:
由於請求方法(Request Method)是POST,所以我們再切換到Payload頁籤,看要傳入什麼參數,如下圖:
二、Python網頁爬蟲爬取JavaScript網頁資料
瞭解JavaScript網頁的特性之後,就可以建立Python網頁爬蟲專案,引用相關的模組,如下範例:
import requests
接著,利用requests模組發送POST請求到JavaScript的請求網址,如下範例:
response = requests.post( 'https://travel.liontravel.com/detail/daytripinfojson')
定義需要傳入的參數資料(Payload),並且傳入requests發送的請求中,如下範例:
payload = { 'TourID': "24JKMAR7CE", 'IsPreview': 'false', 'TravelType': '1' } response = requests.post( 'https://travel.liontravel.com/detail/daytripinfojson', data=payload)
三、Python網頁爬蟲解析取得的JSON格式資料
發送請求之後,就可以使用Python內建的json()方法解析JavaScript回傳的JSON格式資料,並且存取DailyList每日行程欄位,如下範例第9行:
payload = { 'TourID': "24JKMAR7CE", 'IsPreview': 'false', 'TravelType': '1' } response = requests.post( 'https://travel.liontravel.com/detail/daytripinfojson', data=payload) dailyLists = response.json()['DailyList'] # 存取DailyList欄位
由於DailyList每日行程欄位是多筆資料,所以利用For迴圈進行讀取,並且分別存取它下面的Day(天)、AttractionsList(行程清單)欄位,如下範例第13、15行:
payload = { 'TourID': "24JKMAR7CE", 'IsPreview': 'false', 'TravelType': '1' } response = requests.post( 'https://travel.liontravel.com/detail/daytripinfojson', data=payload) dailyLists = response.json()['DailyList'] # 存取DailyList欄位 for dailyList in dailyLists: day = dailyList['Day'] # 存取DailyList下的Day(天)欄位 attractionsLists = dailyList['AttractionsList'] # 存取DailyList下的AttractionsList(行程)欄位
其中,AttractionsList(行程清單)欄位也是多筆資料,所以利用For迴圈進行讀取,並且將每天相應的景點名稱(Name)加入到自訂的串列(List)中,如下範例第17~22行:
payload = { 'TourID': "24JKMAR7CE", 'IsPreview': 'false', 'TravelType': '1' } response = requests.post( 'https://travel.liontravel.com/detail/daytripinfojson', data=payload) dailyLists = response.json()['DailyList'] # 存取DailyList欄位 for dailyList in dailyLists: day = dailyList['Day'] # 存取DailyList下的Day(天)欄位 attractionsLists = dailyList['AttractionsList'] # 存取DailyList下的AttractionsList(行程)欄位 attractionsName = [] # 行程名稱 for attractionsList in attractionsLists: # 將當天的每個行程名稱加入到自訂的attractionsName串列變數中 attractionsName.append(attractionsList['Name'])
最後,把每天相應的景點名稱串列(List),加入到自訂的字典(Dictionary)變數中,如下範例第11、26行:
payload = { 'TourID': "24JKMAR7CE", 'IsPreview': 'false', 'TravelType': '1' } response = requests.post( 'https://travel.liontravel.com/detail/daytripinfojson', data=payload) dailyLists = response.json()['DailyList'] # 存取DailyList欄位 result = {} for dailyList in dailyLists: day = dailyList['Day'] # 存取DailyList下的Day(天)欄位 attractionsLists = dailyList['AttractionsList'] # 存取DailyList下的AttractionsList(行程)欄位 attractionsName = [] # 行程名稱 for attractionsList in attractionsLists: # 將當天的每個行程名稱加入到自訂的attractionsName串列變數中 attractionsName.append(attractionsList['Name']) # 將"天"和"對應的行程"加入到自訂的result字典變數中 result[str(day)] = attractionsName print(result)
執行結果如下:
{ '1': ['SPACE WALK環湖公園', '浦項鐵路林', '【韓劇拍攝場景】九龍浦近代歷史文化街區', '東萊溫泉川市民公園'], '2': ['余佐川羅曼史橋', '帝皇山公園', '慶和火車站', '西面鬧區'], '3': ['【Running Man拍攝地】甘川洞彩繪文化村', '韓國人蔘專賣店', '保肝靈專賣店', '時尚彩妝店', '洛東江三樂生態公園', '【綜藝玩很大拍攝地】南浦洞國際市場', '富平罐頭夜市'], '4': ['【世界文化遺產】佛國寺', '普門觀光園區', 'E WORLD樂園(特別贈送纜車+大邱塔)', '前山日落觀景台', '大邱東城鬧區'] }
四、小結
以上就是Python網頁爬蟲爬取JavaScript網頁的步驟,先開啟開發者模式,搜尋JavaScript撈取網頁資料所發送的請求網址,接下來,就可以建置網頁爬蟲發送請求,透過解析回傳的JSON格式資料,爬取到想要的網頁資料。
留言
張貼留言