我們都知道在開發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格式資料,爬取到想要的網頁資料。
你可能有興趣的文章
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYqMPD_mPLEileg1IdrsIYhFSWZkYFKYmEnUqWqiqdiJv2XYnkT23CFcXoTN6HBtGCEUylgVoUIVKm6KPRPM_TjcjsSei4lGE_YmZdrWA6Ulw1fp6-o8Cn-bVwr7_FANFoC4tjTe-ak6w-atFYq-a1pipQbZvQzt4wHRNK7tywcSG0dSCnpJpqoMP5wA/s1600/Python%E7%B6%B2%E9%A0%81%E7%88%AC%E8%9F%B2%E5%85%8D%E8%B2%BB%E7%B7%9A%E4%B8%8A%E5%9F%B9%E8%A8%93.png)
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh-fK9Da5M7X1lSpbZVan4Eo-PunVnQv-YHw3EDahTUhZr5FayVLaCPqrW44W3_xwQQO-gAWZEwe_A-SxL_nltT__ArbFOgLYAAIsi3RzETT9GqVsfyfN9PXDs-xGTkxZSqj_W1SCxwD2UcrJLqHZSYIrLB-HIU75vSom4YoqoWFUQz_o4PbnvTQUbE6Bab/w640-h426/2.png)
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg61JC7N1hyphenhyphenPpzb1hNJauunevoWrOsJxk_Upz0ywnLtIAJ2rdd1ZxChyphenhyphenFPq8GHYfywtHv2mTce5NGdwwxWFWYARhA6In0xlOzkwlRb9kM04mwgdy9Un9JgVCoLQnwV25oUcitQy2OY4TeA3gVIs067wR4StGfkldbykOeL3TfPchWfNClWKhL10ZzWaxFtf/w640-h426/3.png)
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgh1XFQE0AmkZHSFB0Icq3uY4_FdsIYZ9nUqllOlo9ulRu0ri-LS1OeW2ybKOO2QRg-gyUOUr_3sMLYf7S4Q5ULZpIcXsS1pAkSMPm0OwqpbnLET51WEpQ3EoY5WaEVEWyTixBkRqp2tA7SpePM_MCIY6tnyUvu917rulqbLJTEEPsEho6Q-4Tf74DFdakd/w640-h426/4.png)
留言
張貼留言