Python 小社-8

selenium

可能是這學期最後一堂課

嗎?

如果下學期想做DC bot的人可以熟悉一下

反正我去年整個機器人都是用爬蟲啦

複習

request

爬html

import request

url = 'url'
html = request.get(url)

BeautifulSoup

import requests 
from bs4 import BeautifulSoup 

url = 'https://ckefgisc.github.io/'
html = requests.get(url) 
soup = BeautifulSoup(html.text, 'html.parser')

BeautifulSoup

找標籤

import requests 
from bs4 import BeautifulSoup 

url = 'https://ckefgisc.github.io/'
html = requests.get(url) 
soup = BeautifulSoup(html.text, 'html.parser')
soup.find('標籤', class = 'class')

動態網頁爬蟲

動態網頁 顧名思義 網頁是動態的

每次瀏覽的結果可能不一樣

會載入網頁

也就是說你會看到一個自動開啟的視窗

先下載selenium

pip install selenium

webdriver

基本操作

from selenium import webdriver

driver = webdriver.Chrome()          #剛剛下載的exe檔和py檔在同一個資料夾下的話
driver = webdriver.Chrome('絕對路徑') #不在同一個資料夾下的話

driver.get('https://www.google.com')
driver.close()

版本夠新的selenium可以不用輸入路徑

不過如果你的版本太舊盡量放在同一個資料夾下

執行結果

按鍵輸入

from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys

先import By 和 Keys

按鍵輸入

對要輸入的地方按右鍵檢查

按鍵輸入

找到你要輸入的地方的html

按鍵輸入

用find_element(By.你要的方法)找

用send_keys()輸入

import time
from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()          #剛剛下載的exe檔和py檔在同一個資料夾下的話

driver.get('https://www.google.com')
element = driver.find_element(By.CLASS_NAME, 'gLFyf')
element.send_keys('python')
time.sleep(10)
driver.close()

常用搜尋方法

ID id
NAME name
XPATH xpath
LINK_TEXT link text
PARTIAL_LINK_TEXT partial link
text
TAG_NAME tag name
CLASS_NAME class name
CSS_SELECTOR css selector

基本上可以隨便選一種

但有些網站class會一直重複

這時後就右鍵copy xpath

常用按鍵

Keys.ENTER enter
element.clear() 清空
element.click() 點擊
字串 你輸入的字串

其實鍵盤上有的按鍵基本上都能用

但會上不完 所以只講等等會用的

等待

實際操作的時候網頁不可能馬上就跑好

所以我們必須給他一點緩衝時間

這時我們就要用內建的wait函式

Explicit Waits

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

element = WebDriverWait(driver, 10).until(
	EC.presence_of_element_located((By., ...))
)

明確等待 會等到特定條件達成才會執行

最多等待到你輸入的時間

Implicit Waits

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.implicitly_wait(10)

通常用在你不知道要等多久的時候

只需要在開頭寫一次就好

阿所以差在哪

簡單來講implicit 比 explicit方便

但是explicit更精確

實作上更推薦explicit

(implicit只能用在find_element)

上一頁

driver.back()

使用javascript

driver.execute_script(你要執行的javascript, 參數)

重新整理

driver.refresh()

爬網路上的圖片

import selenium
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options

option = webdriver.ChromeOptions()
option.add_experimental_option("detach", True)
driver = webdriver.Chrome(options=option)
driver.implicitly_wait(5)
driver.get('https://pic.sogou.com/pics?query=%23dog')
pic = driver.find_element(By.XPATH, '//*[@id="picPc"]/div/div[2]/div/ul/li[1]/div/a[1]/img')
print(pic.get_attribute('src'))

基本的操作大概像這樣

自動開啟gmail

import selenium
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By

option = webdriver.ChromeOptions()
option.add_experimental_option("detach", True)
driver = webdriver.Chrome(options=option)
driver.get("https://accounts.google.com/v3/signin/identifier?continue=https%3A%2F%2Fmail.google.com%2Fmail%2F&ifkv=ASKXGp24TmphTudM7FvvmeEC1USCo7PlMAvIK-z1Ju28TPiPd6_VGUSoKo3dfJnzpPFPC9J6pxDH&rip=1&sacu=1&service=mail&flowName=GlifWebSignIn&flowEntry=ServiceLogin&dsh=S-401840579%3A1701769561233889&theme=glif")
driver.implicitly_wait(500)
element = driver.find_element(By.NAME, 'identifier')
element.send_keys('才不跟你講我的帳號')
element.send_keys(Keys.ENTER)
element = driver.find_element(By.NAME, 'Passwd')
element.send_keys('猜猜看密碼阿')
element.send_keys(Keys.ENTER)

自動寫OJ

import selenium
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options

option = webdriver.ChromeOptions()
option.add_experimental_option("detach", True)
driver = webdriver.Chrome(options=option)
driver.get('https://iscoj.fg.tp.edu.tw/users/sign_in')
driver.implicitly_wait(50)
e = driver.find_element(By.NAME, 'user[username]')
e.send_keys('account')
e = driver.find_element(By.NAME, 'user[password]')
e.send_keys('password')
e = driver.find_element(By.NAME, 'commit')
e.click()
e = driver.find_element(By.LINK_TEXT, 'Problems')
e.click()
e = driver.find_element(By.LINK_TEXT, 'AaW 與他的 OJ')
e.click()
e = driver.find_element(By.LINK_TEXT, 'Submit')
e.click()
e = driver.find_element(By.NAME, 'submission[code_content_attributes][code]')
e.send_keys('#include<iostream>\n')
e.send_keys('int main(){\n')
e.send_keys('   std::cout<<\"AaW大哥牛逼!\";\n')
e.send_keys('}')
e = driver.find_element(By.NAME, 'commit')
e.click()

不要給我用這招去random刷題

你會把伺服器搞爆

程式碼可以改用之前教的file io輸入

option

option = webdriver.ChromeOptions()
option.add_experimental_option("detach", True)
driver = webdriver.Chrome(options=option)

有沒有注意到我剛剛的程式碼前面加了這段

option

option的主要功能就是對你開啟的網頁

做一些額外的設定

option

option.add_argument('--incognito') #無痕
option.addArgument('--start-maximized')#最大化視窗 == driver.maximize_window()
option.addArgument('--blink-settings=imagesEnabled=false') #禁止載入圖片
option.add_experimental_option("detach", True) #執行完成後不自動關閉

飯粒

import requests
import pandas as pd

url = 'https://tcgbusfs.blob.core.windows.net/blobyoubike/YouBikeTP.json'
response = requests.get(url)
if response.status_code == 200:
    json=response.json()
else:
    print("下載失敗")

data = list(json['retVal'].values())
sitename = []
district = []
can_take = []
can_give = []
full_num = []

for i in data:
    sitename.append(i['sna'])
    district.append(i['sarea'])
    can_take.append(i['sbi'])
    can_give.append(i['bemp'])
    full_num.append(i['tot'])

l = len(sitename)
ask = int(input('請選擇你要輸入1.站名或2.區域 ex:台北市政府or中正區\n'))
if ask == 1:
    name = input('請輸入站名')
    for i in range(l):
        if sitename[i] == name:
            print(f'站名: {sitename[i]} 區域: {district[i]} 尚可借{can_take[i]} 尚可還{can_give[i]}')
            break
    else:
        print('你打錯站名囉')
else:
    dis = input('請輸入你的行政區\n')
    for i in range(l):
        if district[i] == dis:
            print(f'{i+1}. {sitename[i]}')
    n = int(input('請輸入編號\n'))
    print(f'站名: {sitename[n-1]} 區域: {district[n-1]} 尚可借{can_take[n-1]} 尚可還{can_give[n-1]}')
Made with Slides.com