攝影或3C

Python: 如何使用selenium打開chrome瀏覽器連線Facebook,自動輸入帳密後登入?from selenium import webdriver ; driver = webdriver.Chrome() ; driver.get(url)

教學範例:

code:

# -*- coding: utf-8 -*-
"""
Created on Sun Feb  4 10:35:36 2024

@author: SavingKing
"""
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.chrome.options import Options

driver = webdriver.Chrome()
#selenium.webdriver.chrome.webdriver.WebDriver

url = "https://www.facebook.com/"
driver.get(url)

#注意code沒有
service = Service(executable_path=”…”)
執行結果:

順利打開Chrome瀏覽器
並連線facebook

推薦hahow線上學習python: https://igrape.net/30afN

Chrome瀏覽器
按Ctrl + Shift + I
可檢視原始碼
原始碼左上角的這一個icon
可以同步外觀vs原始碼

選擇想看原始碼的外觀位置
點擊左鍵,右邊的原始碼就會定住
name點擊兩下,
可以使用Ctrl + A 全選
Ctrl + C 複製
再到IDE Ctrl +V 貼上
電子郵件位置對應的原始碼:

<input type="text" class="inputtext _55r1 _6luy" name="email" id="email" data-testid="royal_email" placeholder="電子郵件地址或手機號碼" autofocus="1" aria-label="電子郵件地址或手機號碼">

對應python code:

.element_to_be_clickable((By.CSS_SELECTOR, 'input[name="email"]'))

.element_to_be_clickable()
接收Tuple[str, str]當參數,
所以多一層()

密碼位置對應的原始碼:

<input type="password" class="inputtext _55r1 _6luy _9npi" name="pass" id="pass" data-testid="royal_pass" placeholder="密碼" aria-label="密碼">

對應的python code:

.element_to_be_clickable((By.CSS_SELECTOR, 'input[name="pass"]'))

name=”pass”可以替換為
id=”pass”
data-testid=”royal_pass”

也可對應以下python code:

password = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable((By.NAME, "pass")))

也可以使用placeholder或aria-label屬性進行元素定位
但需注意:
準確性:使用placeholder或aria-label作為定位機制可能在國際化(i18n)的環境中遇到問題,因為這些屬性的值可能會根據用戶的語言設置而改變。如果您的測試或自動化腳本需要在多種語言環境下運行,使用這些屬性可能不是最佳選擇。

穩定性:頁面的UI文本(如placeholder和aria-label的值)可能更頻繁地變化,尤其是在開發初期或者進行UI文案調整時。與之相比,id、name或data-testid等屬性通常更穩定,不太可能因為UI更新而改變。

因此,盡管技術上可行,但在實際應用中,建議優先考慮更穩定、不易因界面調整而變動的屬性作為元素的定位策略。

登入位置的原始碼:

<button value="1" class="_42ft _4jy0 _6lth _4jy6 _4jy1 selected _51sy" name="login" data-testid="royal_login_button" type="submit" id="u_0_5_kH">登入</button>

對應的python code:

login = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable(
        (By.CSS_SELECTOR, 'button[name="login"]')
        )
    )

完整code:

# -*- coding: utf-8 -*-
"""
Created on Sun Feb  4 10:35:36 2024

@author: SavingKing
"""

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.chrome.options import Options
import os
import json

option = webdriver.ChromeOptions()
prefs = {"profile.default_content_setting_values":{"notifications":2}}
option.add_experimental_option("prefs",prefs)

driver = webdriver.Chrome(options=option)
#selenium.webdriver.chrome.webdriver.WebDriver

url = "https://www.facebook.com/"
driver.get(url)

dirname = r"D:\Python code\240107_爬蟲\selenium_chrome"
basename = "fb.json"
path = os.path.join(dirname, basename)

dic={}
with open(path,"r") as f:
    dic=json.load(f)
account = dic["account"]
pw= dic["password"]

username = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable(
        (By.CSS_SELECTOR, 'input[name="email"]')
        )
    )
# username = WebDriverWait(driver,
10).until(EC.element_to_be_clickable( (By.CSS_SELECTOR,'input[name="email"]')  ))
"""
#selenium.webdriver.support.wait.WebDriverWait
#selenium.webdriver.remote.webelement.WebElement
By.CSS_SELECTOR
Out[21]: 'css selector'
"""
username.clear() 
username.send_keys(account)

# password = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.CSS_SELECTOR, 'input[name="pass"]')))
# #selenium.webdriver.remote.webelement.WebElement
password = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable(
    (By.NAME, "pass")
    ))

password.clear()
password.send_keys(pw)


login = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable(
        (By.CSS_SELECTOR, 'button[name="login"]')
        )
    )
# login.click()
login.send_keys(Keys.ENTER)

會打開Chrome瀏覽器
輸入帳/密,按登入

推薦hahow線上學習python: https://igrape.net/30afN

密碼的HTML:

<input type="password" class="inputtext _55r1 _6luy _9npi" name="pass" id="pass" data-testid="royal_pass" placeholder="密碼" aria-label="密碼">

這個標簽同時具有四種class值:inputtext、_55r1、_6luy、_9npi。在HTML中,一個元素可以有多個class,這些class通過空格分隔。這種設計使得CSS樣式和JavaScript功能可以更靈活地應用於HTML元素。

對於BeautifulSoup和Selenium,處理具有多個class的元素時的行為略有不同:

BeautifulSoup:

  • .find().find_all()方法:當使用class_參數搜索具有多個class值的元素時,你可以傳入單個class值或class值列表。如果傳入列表,則元素必須具有列表中的所有class值才會被匹配。
    .find(“input”, class_=”inputtext _55r1 _6luy _9npi”)
  • .select()方法:使用CSS選擇器時,可以通過串聯class值(無空格,每個class前加.)來選擇具有多個class的元素。例如,要選擇具有inputtext _55r1 _6luy _9npi所有class的元素,可以使用.inputtext._55r1._6luy._9npi。

Selenium:

  • 通过class查找元素:當使用find_element_by_class_name或find_elements_by_class_name方法時,Selenium要求只能傳入單個class名,不能傳入包含空格的多個class名。這意味著你只能基於其中一個class來查找元素。
  • CSS选择器:與BeautifulSoup的.select()方法類似,Selenium的find_element_by_css_selector或find_elements_by_css_selector方法允許使用CSS選擇器來定位具有多個class的元素。使用方法也是通過串聯class值(無空格,每個class前加.)。
driver.find_element(By.CSS_SELECTOR, 'input.inputtext._55r1._6luy._9npi')

因此,雖然處理具有多個class的元素時有一些限制(尤其是在Selenium中直接通過class名查找時),但你仍然可以通過CSS選擇器(在兩者中都可用)來精確地定位這些元素。

  • Seleniumfind_element() 方法用于定位页面上的单个元素,类似于 BeautifulSoup.find() 方法,用于在 HTML 或 XML 解析树中查找第一个匹配特定标准的元素。
  • Seleniumfind_elements() 方法用于定位页面上符合条件的所有元素,类似于 BeautifulSoup.find_all() 方法,用于查找所有匹配特定标准的元素。

这两套方法在各自的库中都是用来根据给定的标识符(如标签名、类名、ID等)查找页面元素。不过,它们操作的上下文不同:Selenium 直接与浏览器交互,操作实时的网页元素;而 BeautifulSoup 解析和操作的是静态的 HTML 或 XML 内容。

推薦hahow線上學習python: https://igrape.net/30afN

儲蓄保險王

儲蓄險是板主最喜愛的儲蓄工具,最喜愛的投資理財工具則是ETF,最喜愛的省錢工具則是信用卡