如題最近在爬一個網站
發現裡面我要的一個地方

我想取得所有影片網址然後把影片抓下來
如果直接把網址跟XPATH丟給CHATGPT寫爬蟲
結果就是他定位不到
後來檢查原因原來是

那個攝影機是包在一個ajaxTable裡面
所以做法變成要先確認這個ajaxTable有載入否則根本定位不到
解法就是要先點擊球員名字

之後拉到底讓整個table載入

之後才有辦法定位到右邊那排攝影機
貼上我跟chatgpt互動的情況



ChatGPT 說:
- 這段程式是用 Selenium 模擬瀏覽器,適合動態載入或需要點擊互動的頁面。
id_676979
是你指定的元素ID,你可以換成其他ID或用其他定位方式。- 如果需要擷取點擊後展開的特定資料,可能要用更精準的方式找到該資料元素並抓取內容。
- 如果你想要爬大量資料,記得遵守網站的 robots.txt 和使用規範,避免被封鎖。
如果你有想要我幫你擷取點開後的具體數據,也可以提供更詳細的需求,我幫你客製化。
我說:
點開之後尋找到所有類似 //*[@id="ajaxTable_676979"]這個東西 應該是動態載入的 所以點開之後還要拉到最下面才會出現
ChatGPT 說:
了解,你的需求是: 用 Selenium 打開頁面 點擊 id="id_676979" 這個元素展開動態內容 展開後頁面會透過 Ajax 載入動態表格(例如 id="ajaxTable_676979") 且動態表格是分頁或滾動加載的,需要滾動到最下面讓資料全部載入
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
def scroll_to_bottom(driver, pause_time=2, max_scrolls=20):
"""滾動到頁面最底部,等待 Ajax 載入"""
last_height = driver.execute_script("return document.body.scrollHeight")
scrolls = 0
while scrolls < max_scrolls:
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(pause_time)
new_height = driver.execute_script("return document.body.scrollHeight")
if new_height == last_height:
# 沒有新高度,可能已經到底
break
last_height = new_height
scrolls += 1
# 主程式
driver_path = 'chromedriver' # 改成你的路徑
options = webdriver.ChromeOptions()
# options.add_argument('--headless') # 有需要可開啟無頭模式
driver = webdriver.Chrome(executable_path=driver_path, options=options)
try:
url = 'https://baseballsavant.mlb.com/statcast_search?hfPT=&hfAB=&hfGT=R%7C&hfPR=&hfZ=&hfStadium=&hfBBL=&hfNewZones=&hfPull=&hfC=&hfSea=2025%7C&hfSit=&player_type=pitcher&hfOuts=&hfOpponent=&pitcher_throws=&batter_stands=&hfSA=&game_date_gt=&game_date_lt=&hfMo=&hfTeam=&home_road=&hfRO=&position=&hfInfield=&hfOutfield=&hfInn=&hfBBT=&hfFlag=&metric_1=&group_by=name&min_pitches=0&min_results=0&min_pas=0&sort_col=pitches&player_event_sort=api_p_release_speed&sort_order=desc#results'
driver.get(url)
wait = WebDriverWait(driver, 15)
# 等待 id_676979 可點擊
target = wait.until(EC.element_to_be_clickable((By.ID, 'id_676979')))
target.click()
time.sleep(3) # 等 ajax 開始載入
# 滾動到底部讓所有資料載入
scroll_to_bottom(driver, pause_time=3, max_scrolls=30)
# 等待 ajaxTable_676979 出現
ajax_table = wait.until(EC.presence_of_element_located((By.ID, 'ajaxTable_676979')))
# 抓取該表格的HTML
table_html = ajax_table.get_attribute('outerHTML')
print(table_html)
finally:
driver.quit()
ChatGPT 說:
程式流程說明 用 Selenium 開啟網址 等待「id_676979」按鈕可點擊並點擊 等待一段時間讓 Ajax 觸發載入 執行 scroll_to_bottom 函式,模擬瀏覽器往下滾動多次,讓懶加載資料被全部載入 等待動態載入的表格「ajaxTable_676979」出現 抓取該表格的 HTML 內容 如果你想要解析表格裡的資料,可以接著用 BeautifulSoup 處理 table_html,或者直接用 Selenium 找表格裡的 <tr>、<td> 等元素。 如果你需要我幫你寫解析表格欄位的程式,或批量點開多個 id 來抓資料,也可以告訴我!
你說:
ajaxtable載入後 尋找//*[@id="ajaxTable_676979"]/tbody/tr[1]/td[15]/a 注意這裡的tr[1]可變也有tr[2]依此類推 都要找到
ChatGPT 說:
了解!你的需求是在動態載入的表格 id="ajaxTable_676979" 裡,遍歷所有的 <tr> 列,然後從每一列的第15個 <td> 找 <a> 標籤,將所有這些 <a> 標籤元素找出來。 以下示範用 Selenium 來做這件事:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
def scroll_to_bottom(driver, pause_time=2, max_scrolls=20):
last_height = driver.execute_script("return document.body.scrollHeight")
scrolls = 0
while scrolls < max_scrolls:
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(pause_time)
new_height = driver.execute_script("return document.body.scrollHeight")
if new_height == last_height:
break
last_height = new_height
scrolls += 1
driver_path = 'chromedriver'
options = webdriver.ChromeOptions()
# options.add_argument('--headless')
driver = webdriver.Chrome(executable_path=driver_path, options=options)
try:
url = 'https://baseballsavant.mlb.com/statcast_search?hfPT=&hfAB=&hfGT=R%7C&hfPR=&hfZ=&hfStadium=&hfBBL=&hfNewZones=&hfPull=&hfC=&hfSea=2025%7C&hfSit=&player_type=pitcher&hfOuts=&hfOpponent=&pitcher_throws=&batter_stands=&hfSA=&game_date_gt=&game_date_lt=&hfMo=&hfTeam=&home_road=&hfRO=&position=&hfInfield=&hfOutfield=&hfInn=&hfBBT=&hfFlag=&metric_1=&group_by=name&min_pitches=0&min_results=0&min_pas=0&sort_col=pitches&player_event_sort=api_p_release_speed&sort_order=desc#results'
driver.get(url)
wait = WebDriverWait(driver, 15)
target = wait.until(EC.element_to_be_clickable((By.ID, 'id_676979')))
target.click()
time.sleep(3)
scroll_to_bottom(driver, pause_time=3, max_scrolls=30)
ajax_table = wait.until(EC.presence_of_element_located((By.ID, 'ajaxTable_676979')))
# 取得 tbody 裡所有 tr
rows = ajax_table.find_elements(By.XPATH, ".//tbody/tr")
print(f"共找到 {len(rows)} 列")
all_links = []
for i, row in enumerate(rows, 1):
try:
# 找每列第15個td裡的a標籤
link = row.find_element(By.XPATH, "./td[15]/a")
href = link.get_attribute('href')
text = link.text
print(f"Row {i} - Link text: {text}, href: {href}")
all_links.append((text, href))
except Exception as e:
print(f"Row {i} - 找不到第15欄<a>標籤或發生錯誤: {e}")
finally:
driver.quit()
重點說明:
- 用
ajax_table.find_elements(By.XPATH, ".//tbody/tr")
找所有資料列(tr
) - 每一列用相對 XPath
./td[15]/a
找第15個欄位的<a>
- 用 try-except 避免某些列沒有第15欄
<a>
導致錯誤 - 印出文字和連結,並存在
all_links
裡方便後續處理
你可以改成自己需要的資料儲存或其他後續操作。如果資料很多或有分頁,你也可以做迴圈去點下一頁再抓。
如果想要我幫你做分頁自動翻頁也可以告訴我。
結果

大功告成
所以爬蟲絕對不是把網址跟XPATH丟給CHATGPT他就能幫你寫的
像這種動態載入的情況 要像剝洋蔥一樣 要先定位到外層 點擊後展開內層
才有辦法繼續往內剝
使用者必須先自己在網站上跟所要爬的元素做互動 觀察
看看該元素包在那些結構底下
這些結構是否是動態載入的
若是動態載入則要用selenium
模擬使用者操作才能取得