---
tags: web crawler
---
# 爬蟲3(selenium)
## selenium 是什麼
`selenium`是一個可以讓你的程式碼模擬真實操作 ex: 點擊、輸入文字、播放影片.....
十分的方便,基本上有了他你也不會想用`requests`了,那為什麼不先教他呢,<del>因為我不會</del>,因為`requests`可以讓你對網站的瀏覽有最基本的認識`get`, `post`, `put`, `delete`,當然,這只是極度基礎的部分,如果還想要深挖的話可能還有一堆協議`https`、`tcp`...,還有封包之類的東西(我也不會了 :poop: )。
總而言之,高中想做專案的話`selenium`就可以了,因為他也可以抓取網頁上的原始碼(html),而且還可以更方便的進行登錄(基本上就是 跟你登陸的過程差不多( 點擊 -> 輸入密碼 -> 送出 ) , 基本上你在瀏覽器上手動作的他都可以做到。
## 準備工作
基本上,如果你需要瀏覽網頁的話你需要一個瀏覽器 :poop:,那對於`selenium`來說,你就會需要[chrome driver](https://chromedriver.chromium.org/downloads)這個瀏覽器,當然你的電腦上要有chrome,然後版本要記得對上,不然會出事,
所以就可以把他下仔之後跟你的code放在同一個目錄之下。
之後在`terminal(cmd)`上安裝`selenium`就可以了
```
在 cmd/terminal 內:
pip install selenium
```
## 初使化瀏覽器
最基礎的就這樣就可以了
```python=
from selenium import webdriver
driver = webdriver.Chrome()
```
當然,如果沒有遇到bug的話那你可能沒有寫過程式 :poop:
有時候可能遇到這種錯誤
```
USB: usb_device_handle_win.cc:1046 Failed to read descriptor from node connection:
連結到系統的某個裝置失去作用。 (0x1F)
```
那這個時候就可以查一下,基本上就把錯誤複製貼上就好了 :poop:
那你就可以發現說他可能是因為某些東西然後出錯,耶會找到解決辦法。
```python=
options = webdriver.ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-logging'])
driver = webdriver.Chrome(options=options);
```
那就愉快的複製上去 :poop: 他就又能動了
## click
那我們先來看一個最簡單的例子[pop cat](https://popcat.click/),基本上用selenium一下子就會被封了,所以我們只是拿來當作練習(不要問我怎麼知道的 :poop: ) ,然後python十個線程跟一個線程差不多 :poop:
:::spoiler 舊的寫法, 會抱錯
```python=
""" 初始化 driver"""
options = webdriver.ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-logging'])
driver = webdriver.Chrome(options=options);
""" 獲取網址 (有點像你在搜尋欄那邊直接打網址) 他還會幫你enter"""
driver.get("https://popcat.click/")
login = driver.find_element_by_class_name("title")
while 1==1 : # this is magic
login.click() 就是點擊
```
:::
```python=
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("https://popcat.click/")
login = driver.find_element(By.CLASS_NAME, "title")
while 1==1 : # this is magic
login.click()
```
## send key
基本上這個就是可以打字的東西,他可以幫你模擬鍵盤
```python=
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from time import sleep
driver = webdriver.Chrome()
driver.get("https://google.com/")
typing_blank = driver.find_element(By.XPATH, "/html/body/div[1]/div[3]/form/div[1]/div[1]/div[1]/div/div[2]/textarea")
typing_blank.send_keys("hello, world")
typing_blank.send_keys(Keys.RETURN)
sleep(5)
driver.quit();
driver.close()
```
至於XPATH如何或取,你只要到網頁原始碼(右鍵 -> 檢查)然後找到你要的區域再按一次又見,找到複製,就可以複製XPATH了,當然,它除了可以`By.XPATH`外,`id`, `class`也都是被允許的。
## login
那現在就讓我們來進行合併的練習吧。
`./data.json`
```jsonld=
{
"contestid": [229, 226],
"url" :{
"login": "https://dandanjudge.fdhs.tyc.edu.tw/Login",
"Ranking" : "https://dandanjudge.fdhs.tyc.edu.tw/ContestRanking",
"Edit": "https://dandanjudge.fdhs.tyc.edu.tw//EditContestants"
},
"TimeLimit": 3
}
```
```python=
BaseDataFileFatherName = "Test_1"
DataFilePos = "./data.json"
Cookie = list()
def WriteData( filepos, Data ) :
print( f"Ouptut Data into file {filepos}..." );
with open( filepos, 'w', encoding="utf-8" ) as f :
f.write( Data );
def readJson ( filepos ) :
with open( filepos ) as f :
data =json.loads( f.read() );
return data;
UnitData = readJson( DataFilePos );
def Login(driver) :
"""login"""
driver.get( UnitData['url'][ 'login' ] );
""" 如果有cookie存下來的話,在完整的code的時候可以把它刪掉"""
try:
lgcookie = readJson( f'./{BaseDataFileFatherName}/cookie.json' );
for c in lgcookie :
driver.add_cookie( {'name':c['name'], 'value':c['value']} );
except:
print("No Cookie Now")
driver.refresh();
if driver.current_url == "https://dandanjudge.fdhs.tyc.edu.tw/" :
Cookie = driver.get_cookies()
print(Cookie);
WriteData(f'./{BaseDataFileFatherName}/cookie.json', json.dumps(Cookie, indent=4, ensure_ascii=False));
return "Login Sucess"
""" 輸入帳號"""
AccountName = input("Your account:");
""" 找到帳號框( blank )"""
AccountEle = driver.find_element(By.CSS_SELECTOR ,'div.col-md-4:nth-child(2) > form:nth-child(1) > div:nth-child(1) > div:nth-child(2) > input:nth-child(2)' ) ;
""" 輸入帳號框( blank )"""
AccountEle.send_keys( AccountName );
""" 輸入密碼 """
PassWordName = input("your password:")
""" 找到密碼框( blank )"""
PasswordEle = driver.find_element( By.XPATH, '//*[@id="passwd"]' );
""" 輸入密碼框( blank )"""
PasswordEle.send_keys( PassWordName )
""" 找到登入按鈕 """
driver.find_element( By.XPATH,'/html/body/div[4]/div[2]/div[2]/form/button[1]' ).click();
sleep(5)
""" 這邊是觀察到如果有成功登陸的話就可以發現它會自動導回到首頁 """
if driver.current_url == "https://dandanjudge.fdhs.tyc.edu.tw/" :
Cookie = driver.get_cookies()
print(Cookie);
WriteData(f'./{BaseDataFileFatherName}/cookie.json', json.dumps(Cookie, indent=4, ensure_ascii=False));
print("Login Sucess")
return "Login Sucess"
else :
print( "Login Fail" )
return "Login Fail"
options = webdriver.ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-logging'])
driver = webdriver.Chrome(options=options);
Login(driver)
```
## 取代 selenium
`driver.page_source`就可以拿到網頁的原碼了,所以就可以用`BeautifulSoup`處理,
## 成果
[我的code](https://github.com/william1010121/DDJ-contest-score/tree/WindowCode)