您好:
因為參考的書籍較舊,完全抓不到範例
要用selenium去抓資料 URL = "https://tw.hotels.com/"
但目前該網站已經改版,
想請問 他會跳出彈掉視窗,要如何銷掉
目前到這一步 就錯了
2.這些元件要如何選擇 或直接填入值?
3.下拉選單這要如何選值 或填入?
有試過用copilot問,但不能執行
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time
# 初始化WebDriver
driver = webdriver.Chrome() # 请确保chromedriver路径正确
driver.get('https://tw.hotels.com/')
# 输入搜索条件
search_box = driver.find_element(By.ID, 'qf-0q-destination')
search_box.send_keys('台北市')
search_box.send_keys(Keys.RETURN)
# 选择入住和退房日期
check_in = driver.find_element(By.ID, 'qf-0q-localised-check-in')
check_in.clear()
check_in.send_keys('2024-12-12')
check_out = driver.find_element(By.ID, 'qf-0q-localised-check-out')
check_out.clear()
check_out.send_keys('2024-12-14')
check_out.send_keys(Keys.RETURN)
# 等待页面加载
time.sleep(5)
# 抓取酒店信息
hotels = driver.find_elements(By.CLASS_NAME, 'hotel')
for hotel in hotels:
name = hotel.find_element(By.CLASS_NAME, 'hotel-name').text
price = hotel.find_element(By.CLASS_NAME, 'price').text
print(f'Hotel: {name}, Price: {price}')
# 关闭浏览器
driver.quit()
謝謝
你好~
我有稍微測試了一下你的程式碼
你使用了ID搜尋,但程式在瀏覽器找不到"qf-0q-destination"、"qf-0q-localised-check-in"等ID的物件,我自己用瀏覽器的開發人員工具搜尋也確實如此。
你在文中提到參考書籍較舊,不確定你是不是按照書上key進程式碼裡,程式才會找不到這些ID。
建議你先使用瀏覽器內建的開發人員工具(快捷鍵F12),或是對目標(button、input)右鍵>檢查,來查看物件有什麼名稱,例如ID、Class、Name等。
找好對應的名稱後,可以先測試程式能不能抓到該物件,再繼續往下走,避免只有開發人員工具抓到但程式抓不到的狀況。
程式抓取方面有分Name、ID、XPath等,我自己是使用XPath,如何使用XPath就請自行搜尋使用方式,這邊就不細講。
以下是範例,在網站選擇一個地點:
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
# 初始化WebDriver
driver = webdriver.Edge()
driver.get('https://tw.hotels.com/')
# 先隨意選一個選項
target_div = driver.find_element(By.XPATH, "//div[contains(@class, 'uitk-layout-grid-has-auto-rows')][1]") # 使用XPATH方式找尋物件,選擇找到的第一個
target_div.click() # 對目標點擊
# 等待選項出現
time.sleep(2)
select_one = driver.find_element(By.XPATH, "//ul/div[1]")
select_one.click()
至於你說的會跳出彈掉視窗,我這邊運行上他會自動消失,並沒有遇到這個狀況。
希望能幫助到你:-)
您好:謝謝您
我參考您的範例,先單純填地點
但 地點參數,台北市
他並不會秀在INPUT 上
再按搜尋鈕
並沒有反映
ElementNotInteractableException: element not interactable
(Session info: chrome=131.0.6778.86)
def search_hotels(searchKey, checkInDate, checkOutDate):
global driver
# xx=driver.find_elements(By().XPATH ,'//*[@id="app-layer-base"]/div[1]/div[2]/div[1]/div[1]/div') # 空白地方
target_div = driver.find_element(By.XPATH, "//div[contains(@class, 'uitk-layout-grid-has-auto-rows')][1]") # 使用XPATH方式找尋物件,選擇找到的第一個
target_div.click() # 對目標點擊
# 等待選項出現
time.sleep(2)
#select_one = driver.find_element(By.XPATH, "//ul/div[1]")
#select_one.click()
search_button=driver.find_elements(By().XPATH ,'//*[@id="search_button"]') # 查詢按鈕
#driver.find_elements_by_xpath('//*[@id="app-layer-base"]/div[1]/div[1]/header/div/section/div/div/div[2]/div[2]/div[2]')
#xx= driver.find_elements_by_xpath('//*[@id="app-layer-base"]/div[1]/div[2]/div[1]/div[1]/div/div/div') #空白地方
# 找出表單的HTML元素
#searchEle =driver.find_elements(By().XPATH ,'//input[contains(@id,"destination")]')
#searchEle =driver.find_elements(By.XPATH ,'//input[contains(@class,"uitk-field-input") and contains(@class,"is-hidden")]')
#searchEle =driver.find_elements(By.XPATH ,'//input[contains(@class,"uitk-field-input") and contains(@class,"typeahead-custom-text-input")]' )
searchEle =driver.find_elements(By.XPATH ,'//input[contains(@id,"destination_form_field-input")]')
#//*[@id="lodging_search_form"]/div/div/div[1]/div/div/div/div[1]/div
#EGDSSearchFormLocationField-Location-destination_form_field
# print("searchEle",searchEle)
#checkInEle = driver.find_elements(By().XPATH ,'//input[contains(@class,"check-in")]')
# print("checkInEle", checkInEle)
# checkOutEle = driver.find_elements(By().XPATH ,'//input[contains(@class,"check-out")]')
#能夠找到 3個HTML元素,找到就建立動作鏈,關閉JS彈出框(有時會有廣告) ,然後送出各輸入欄位的搜尋條件和日期
##if searchEle and checkInEle and checkOutEle:
if searchEle :
actions = ActionChains(driver) # 關閉彈出框
'''
actions.send_keys(Keys.TAB)
actions.send_keys(Keys.TAB)
actions.send_keys(Keys.TAB)
actions.send_keys(Keys.TAB)
'''
actions.send_keys(Keys.ENTER)
actions.perform() #執行儲存動作
print("searchKey:",searchKey)
searchEle[0].send_keys(searchKey) # 輸入搜尋條件
searchEle[0].send_keys(Keys.TAB)
'''
checkInEle[0].clear()
checkInEle[0].send_keys(checkInDate)
checkOutEle[0].clear()
checkOutEle[0].send_keys(checkOutDate)
'''
#checkOutEle[0].send_keys(Keys.ENTER) # 送出搜尋
search_button.click()
time.sleep(15)
'''
menu = driver.find_elements_by_xpath('//*[@id="sort-filter-dropdown-sort"][2]') #已改為Options
if menu:
actions = ActionChains(driver) # 選排序選單
actions.move_to_element(menu[0])
actions.perform()
# 找出價格從低至商排序
price=driver.find_elements_by_xpath('//*[@id="sort-submenu-price"]/li[2]/a')
if price:
price[0].click()
time.sleep(10)
return True
'''
return False
你好
先給你個建議,貼程式碼時,請盡量貼需要的程式碼,用不到的程式碼請刪除,這樣方便其他人看你的程式碼
分析你的程式碼之後,發現你的操作是要直接填入格子中,但hotels網站並不是這樣搜尋的,就算成功填入這個格子,搜尋結果並非是你想要的結果。該網站查詢地點時會呼叫一個API進行ID查詢的動作:API查詢高雄結果
你可以看到圖中高雄的ID是1808,標記為CITY。如果是圖中的高雄萬豪酒店,標記為HOTEL,ID為66588735。當使用者點擊任一選項後,網站會自動帶入ID數值到隱藏輸入。
所以你有兩種方式可以用,一種是用程式操作的方式,對"想要去哪裡?"點擊後,追蹤目的地輸入框並輸入文字,接著追蹤選項並點擊,網站的JS會自動帶入ID及文字等。
另一種方式是需要接API的方式查詢,解析JSON的內容後,因為selenium不能修改隱藏物件的value,因此你必須使用JS修改隱藏數值
以下是小範例:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time
# 初始化WebDriver
driver = webdriver.Edge()
driver.get('https://tw.hotels.com/')
# 先隨意選一個選項
target_div = driver.find_element(By.XPATH, "//div[contains(@class, 'uitk-layout-grid-has-auto-rows')][1]")
target_div.click()
# 等待選項出現
time.sleep(2)
select_one = driver.find_element(By.XPATH, "//ul/div[1]")
select_one.click()
# 修改數值區域
'''
查詢API的程式碼...
'''
location_id = "1808" # 高雄的地區代碼
location_input = driver.find_element(By.XPATH, "//input[@name='EGDSSearchFormLocationField-RegionId-destination_form_field']") # 找尋隱藏RegionId 的 input
driver.execute_script("arguments[0].value = arguments[1];", location_input, location_id) # 使用 JS 修改該值
print("新的 value 值:", location_input.get_attribute("value")) # 確認值是否被修改
# 修改入住日期的值
check_in_date = '2025-01-12'
check_in = driver.find_element(By.XPATH, "//input[@name='EGDSDateRangePicker-StartDate-date_form_field']")
driver.execute_script("arguments[0].value = arguments[1];", check_in, check_in_date)
print("新的 value 值:", check_in.get_attribute("value"))
# 修改退房日期
check_out_date = '2025-01-14'
check_out = driver.find_element(By.XPATH, "//input[@name='EGDSDateRangePicker-EndDate-date_form_field']")
driver.execute_script("arguments[0].value = arguments[1];", check_out, check_out_date)
print("新的 value 值:", check_out.get_attribute("value"))
# 按下搜尋
search_button = driver.find_element(By.ID, "search_button")
search_button.click()
# 等待頁面跳轉
time.sleep(5)
# 關閉瀏覽器
driver.quit()
您好!根據您提到的問題,您的 Selenium 自動化腳本遇到了一些挑戰,這裡我會幫您逐一解決,並提供一些具體的解決方案。
1. 處理彈跳視窗
網站上常常會彈出提示框或 cookie 同意視窗,這些視窗會影響您的操作。您可以透過以下方法來關閉這些視窗:
方法一:直接關閉彈出視窗 您可以嘗試定位彈出視窗的“關閉”按鈕,並進行點擊操作。首先要找到該視窗的定位方式,這可以使用瀏覽器開發者工具來獲取該元素的 XPath 或 CSS Selector。
假設彈出視窗有一個 close-button 類名,您可以這樣寫:
python
Copy code
# 等待彈出視窗並關閉
time.sleep(2) # 等待幾秒鐘確保視窗已經顯示
close_button = driver.find_element(By.CLASS_NAME, 'close-button')
close_button.click()
如果視窗的關閉按鈕是由其他 ID 或 XPath 定位,請根據實際情況修改。
方法二:使用 WebDriverWait 等待 另外,為了避免 sleep 造成的延遲,您可以使用顯式等待來確保元素在可點擊時被操作。
python
Copy code
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
# 等待彈出視窗出現並點擊關閉
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.CLASS_NAME, "close-button"))
).click()
2. 填寫表單字段
在您的範例中,您需要填寫搜尋框、入住日期和退房日期。
搜索框 (qf-0q-destination): 您的代碼已經能夠正確地填寫搜索框,這部分不需要更改。
python
Copy code
search_box = driver.find_element(By.ID, 'qf-0q-destination')
search_box.send_keys('台北市')
search_box.send_keys(Keys.RETURN)
入住和退房日期 (qf-0q-localised-check-in, qf-0q-localised-check-out): 根據您的描述,您需要進行日期的填入,這部分的代碼基本正確,您只需要確保日期格式與網站要求的格式匹配。以下是填入日期的代碼:
python
Copy code
check_in = driver.find_element(By.ID, 'qf-0q-localised-check-in')
check_in.clear()
check_in.send_keys('2024-12-12')
check_out = driver.find_element(By.ID, 'qf-0q-localised-check-out')
check_out.clear()
check_out.send_keys('2024-12-14')
check_out.send_keys(Keys.RETURN)
如果填寫日期仍然不成功,您可以檢查日期欄位是否會觸發日曆選擇器,並通過直接選擇日期來填寫。
3. 選擇下拉選單中的選項
如果您需要選擇下拉選單中的項目,可以使用 Select 類來操作。
假設您的下拉選單是基於 ID 或 name 屬性識別,您可以這樣操作:
python
Copy code
from selenium.webdriver.support.ui import Select
# 假設有一個下拉選單 `room-selection`
select_element = driver.find_element(By.ID, 'room-selection')
select = Select(select_element)
# 選擇一個選項,可以通過索引、選項文字或值來選擇
select.select_by_visible_text('2 位成人')
# 或者
select.select_by_value('2')
# 或者
select.select_by_index(1) # 根據選項的順序選擇
4. 等待網頁加載
在進行交互之前,最好等到網頁完全加載。使用顯式等待可以幫助您避免因為網頁尚未加載完成而造成的錯誤。
python
Copy code
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 等待搜索結果加載
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CLASS_NAME, 'hotel'))
)
5. 抓取資料
當網頁加載完成後,您可以繼續抓取酒店信息。假設您希望抓取酒店名稱和價格:
python
Copy code
hotels = driver.find_elements(By.CLASS_NAME, 'hotel')
for hotel in hotels:
try:
name = hotel.find_element(By.CLASS_NAME, 'hotel-name').text
price = hotel.find_element(By.CLASS_NAME, 'price').text
print(f'Hotel: {name}, Price: {price}')
except Exception as e:
print("Error:", e)
完整範例
綜合上述,以下是完整的範例代碼:
python
Copy code
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select
import time
# 初始化WebDriver
driver = webdriver.Chrome() # 请确保chromedriver路径正确
driver.get('https://tw.hotels.com/')
# 等待彈出視窗並關閉
WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.CLASS_NAME, 'close-button'))
).click()
# 输入搜索条件
search_box = driver.find_element(By.ID, 'qf-0q-destination')
search_box.send_keys('台北市')
search_box.send_keys(Keys.RETURN)
# 等待網頁加載完成
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, 'qf-0q-localised-check-in'))
)
# 选择入住和退房日期
check_in = driver.find_element(By.ID, 'qf-0q-localised-check-in')
check_in.clear()
check_in.send_keys('2024-12-12')
check_out = driver.find_element(By.ID, 'qf-0q-localised-check-out')
check_out.clear()
check_out.send_keys('2024-12-14')
check_out.send_keys(Keys.RETURN)
# 等待頁面加載酒店信息
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.CLASS_NAME, 'hotel'))
)
# 抓取酒店信息
hotels = driver.find_elements(By.CLASS_NAME, 'hotel')
for hotel in hotels:
try:
name = hotel.find_element(By.CLASS_NAME, 'hotel-name').text
price = hotel.find_element(By.CLASS_NAME, 'price').text
print(f'Hotel: {name}, Price: {price}')
except Exception as e:
print("Error:", e)
# 关闭浏览器
driver.quit()
這樣您應該可以成功處理彈出視窗、填寫表單欄位和選擇下拉選單。希望這些建議能幫助您順利完成自動化任務!