1. 程式人生 > 實用技巧 >你要偷偷的學Python,然後驚呆所有人(第十二天)

你要偷偷的學Python,然後驚呆所有人(第十二天)

標題無意冒犯,就是覺得這個廣告挺好玩的

文章目錄

  • 前言
  • 歡迎來到我們的圈子
  • 先上一段程式碼,雲淡風輕
  • 程式碼解釋
  • 第一個坑:find_element_name
  • 第二個坑: switch_to_frame()
  • cookies繞過登入驗證,繞進了荒漠
  • 迎來轉機
  • 成功路前的磕磕碰碰

前言

前期回顧:你要偷偷學Python(第十一天)

上一篇啊,上一篇說這一篇要帶大家玩selenium,那自然是沒錯的。不過這一篇會不一樣一點,這一篇會持續更新。

插播一條推送:(如果是小白的話,可以看一下下面這一段)

歡迎來到我們的圈子

我建了一個Python學習答疑群,有興趣的朋友可以瞭解一下:如果大家在學習中遇到困難,想找一個python學習交流環境,可以加入我們的python圈,裙號947618024,可領取python學習資料,會節約很多時間,減少很多遇到的難題。


本系列文預設各位有一定的C或C++基礎,因為我是學了點C++的皮毛之後入手的Python。
本系列文預設各位會百度,學習‘模組’這個模組的話,還是建議大家有自己的編輯器和編譯器的,上一篇已經給大家做了推薦啦?

然後呢,本系列的目錄嘛,說實話我個人比較傾向於那兩本 Primer Plus,所以就跟著它們的目錄結構吧。

本系列也會著重培養各位的自主動手能力,畢竟我不可能把所有知識點都給你講到,所以自己解決需求的能力就尤為重要,所以我在文中埋得坑請不要把它們看成坑,那是我留給你們的鍛鍊機會,請各顯神通,自行解決。
1234567

先上一段程式碼,雲淡風輕

# 本地Chrome瀏覽器設定方法
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  #Xpath導航所需的包
import time #延時所需的包
from selenium.webdriver.chrome.options import Options



class golden_data:
    def __init__(self):
        options = Options()
        #chrome_options.add_argument('--no-sandbox')  # 解決DevToolsActivePort檔案不存在的報錯
        #options.add_argument('--disable-gpu')  # 谷歌文件提到需要加上這個屬性來規避bug
        #options.add_argument('blink-settings=imagesEnabled=false')  # 不載入圖片, 提升速度
        #options.add_argument('--headless')  # 瀏覽器不提供視覺化頁面. linux下如果系統不支援視覺化不加這條會啟動失敗

        self.driver = webdriver.Chrome(options=options,executable_path="D:/Python3.9/chromedriver.exe")  # 獲取谷歌瀏覽器控制控制代碼
        self.driver.get('https://jinshuju.net/login')  # 開啟金資料登入頁面
        self.wait = WebDriverWait(self.driver, 10)  # Xpath導航
        time.sleep(2)

    #登入金資料
    def login_data(self):
        # 往賬戶欄寫入內容
        name_input = self.wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="auth_key"]')))
        name_input.clear()
        name_input.send_keys('18039027069')  # 在這寫入你的姓名
        time.sleep(2)

        # 點選“下一步”
        next_step = self.wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="login_form"]/div/div[3]/button')))
        next_step.click()
        time.sleep(2)

        # 往密碼欄輸入內容
        pwd_input = self.wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="password"]')))
        pwd_input.clear()
        pwd_input.send_keys('123456.sp')  # 在這寫入你的姓名
        time.sleep(2)

        # 點選登入
        login_click = self.wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="login_form"]/div/div[4]/button')))
        login_click.click()
        time.sleep(2)
    #建立表單
    #def create_table(self):


    #收集表單資料
    def collect_data(self):
        #點選第一個問卷
        first_block = self.wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="5fa54cff61936cdee3121fa5"]/div/a')))
        first_block.click()
        time.sleep(2)

        #點選‘資料’
        table_click = self.wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="entries_nav"]')))
        table_click.click()
        time.sleep(2)

        #資料匯出
        data_out = self.wait.until(EC.presence_of_element_located((By.XPATH, '/html/body/div[3]/div[1]/div[3]/div/div[2]/table/tbody/tr/td[15]')))
        data_out.click()
        time.sleep(60)  #這裡的等待時間有點不好控制

        #資料預下載
        data_fore_download = self.wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="export_job_modal"]/div/div/div[3]/div/a[1]')))
        data_fore_download.click()
        time.sleep(10)

        #資料下載
        data_download = self.wait.until(EC.presence_of_element_located((By.XPATH, '/html/body/div[3]/div[1]/div[3]/div/div[2]/table/tbody/tr/td[15]/table/tbody/tr/td/div[1]/span[2]/a[1]')))
        data_download.click()
        self.driver.close()


test = golden_data()
test.login_data()
test.collect_data()
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081

別噴,我知道程式碼健壯性不行,也知道沒有什麼高可用性。但是這只是我作為一個新手一天的成果而已,又不是學不會,後面慢慢就補上了。

程式碼解釋

還記得多少就解釋多少吧。

第一個坑:find_element_name

最開始的時候,我的程式碼並不是像上面那套寫的,是這類的:

···
name_in = driver.find_element_by_name('···')
teacher.send_keys('····')
pwd_in = driver.find_element_by_name('···')
assistant.send_keys('····')
time.sleep(1)
button = driver.find_element_by_class_name('···')
time.sleep(1)
button.click()
time.sleep(1)
driver.close()
1234567891011

好傢伙,報什麼錯呢?
NoSuchFrameException: Message: no such frame

好傢伙,我雖然沒有身經百戰,大大小小也數十戰了吧,我果斷的打開了百度,一大堆的解決方案映入眼簾,我會眼花繚亂?會個球,我一眼就抓出了這堆凌亂的解決方案中的共同點,他們都在重複著一個標籤名“ifraem”,哎,不重要,反正就這幾個字母的組合排列。

說什麼,是由於存在了標籤頁的切換,所以要先進入到那個標籤頁,只需要把那頁的id或者class提出來做一個引導就好。

吶,像這樣:browser.switch_to_frame('新iframe')

嘿,你還真別說,我還就照做了,這也成了我一晚上崩潰的起點。

第二個坑: switch_to_frame()

哇,這個巨坑。一貼上去這行程式碼就顯示被刪掉了,然而我並不這麼認為,於是。。。

那麼這個是怎麼肥四呢?

這個函式確實是被棄用了,在我的不斷努力之下,我找到了替代函式:switch_to.frame()

這個解決了就萬事大吉了?

請繞回第一個問題。

崩潰嗎?當你以為自己正在過關斬將,一路高歌猛進的時候,突然發現自己原來還在原地打轉。

繞來繞去繞不出來,都大晚上的一兩點了,我就果斷的去睡了。

睡之前,我思量再三,明天起來換cookies吧。


cookies繞過登入驗證,繞進了荒漠

用cookies怎麼繞我就不多說了,不會繞的請回到“第七天”開始。

就直接說我繞過去之後得出了個什麼玩意兒吧:

D:\pythonProject3\Scripts\python.exe C:/Users/asus/PycharmProjects/pythonProject3/main.py
<Response [200]>
<!DOCTYPE html>

<html lang="zh-CN">
<head>
<meta charset="utf-8"/>
<title>金資料 - 找不到頁面</title>
<meta content="IE=Edge,chrome=1" http-equiv="X-UA-Compatible"/>
<link href="https://gd-assets.jinshujucdn.com/assets/favicon-62fe2f27ea9d532a13fc76ed0e8b5e68bc2f61dde4a7935f54ff5dc3e3a727b2.ico" rel="shortcut icon" type="image/x-icon"/>
<link href="https://gd-assets.jinshujucdn.com/assets/blank-layout-67aac9b8f147aa0bf1d9b85c3683738452c3f41160e169b85e61130171db5992.css" media="screen" rel="stylesheet"/>
</head>
<body>
<div class="main-content blank-container">
<div class="page-alert">
<div class="status-code">404</div>
<h2>對不起,您要找的頁面不存在</h2>
<p>您確定是這個網址嗎?或者<a href="/">返回首頁</a></p>
</div>
</div>
<footer>
<a class="powered-by" data-no-turbolink="true" href="/">
<p><span>Powered By </span><i class="gd-icon-logo powered-logo"></i><span> 金資料</span></p>
</a> </footer>
<script>
  var _hmt = _hmt || [];
  (function() {
    if(document.querySelectorAll("script[src*='hm.baidu.com']").length === 0){
      var hm = document.createElement("script");
      hm.src = "//hm.baidu.com/hm.js?47cd03e974df6869353431fe4f4d6b2f";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    }
  })();
  </script>
</body>
</html>
12345678910111213141516171819202122232425262728293031323334353637

你知道嗎?當我繞過了登入驗證的時候,我心裡還有一陣竊喜,嘿,小樣兒,還不是讓我過了。
然後,‘pia’

後來想了想,還是回來用selenium了。
為什麼呢?首先肯定是有我的考量的。其次還是有我的考量的,最後是因為專案中的其他模組還要用到selenium呢,早晚都要面對,早死晚死都得死。


迎來轉機

就在這山窮水盡之時,我抱著試一試的心態,直接搜“selenium操作金資料”。。
死馬當活馬醫了,你們猜怎麼著?

果然球都沒查到哈哈哈哈哈

最後,迫於無奈,我又去換了套教程,“selenium自動化測試操作Chrome”,哎,翻來覆去翻來覆去,找到一個電科大的學長留給他的學弟們的偷懶指令碼,我的天,終於幫我開張了(注意,此前我一步都沒邁出去,連UI都摸不到)!!!

於是,就出現了文章開頭那段程式碼。

其實那段程式碼也不簡單,並不是說改一下就完了,那麼簡單的早就搞好了。


成功路前的磕磕碰碰

其實我剛開始並不是寫成這樣的,剛開始我是寫成C語言格式的,雖然我知道現在這個也是C語言風格的,誰要是跟我說這是面向物件,那我勸你回去學一下設計模式吧。

# 本地Chrome瀏覽器設定方法

class golden_data:
    def __init__(self):
    	#這幾行用於隱藏瀏覽器,但是會導致檔案無法下載,所以暫時擱置
        #options = Options()
        #chrome_options.add_argument('--no-sandbox')  # 解決DevToolsActivePort檔案不存在的報錯
        #options.add_argument('--disable-gpu')  # 谷歌文件提到需要加上這個屬性來規避bug
        #options.add_argument('blink-settings=imagesEnabled=false')  # 不載入圖片, 提升速度
        #options.add_argument('--headless')  # 瀏覽器不提供視覺化頁面. linux下如果系統不支援視覺化不加這條會啟動失敗

        獲取控制代碼,登入,略過


    #收集表單資料
    def collect_data(self):
        #點選第一個問卷
        這裡需要提高可拓展性
        first_block = self.wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="5fa54cff61936cdee3121fa5"]/div/a')))
        first_block.click()
        time.sleep(2)

        #點選‘資料’
        table_click = self.wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="entries_nav"]')))
        table_click.click()	這裡曾經死活點不過去,後來發現是由於複製貼上之後忘記把first_block改成table_click了
        time.sleep(2)

        #資料匯出
        data_out = self.wait.until(EC.presence_of_element_located((By.XPATH, '/html/body/div[3]/div[1]/div[3]/div/div[2]/table/tbody/tr/td[15]')))	這裡曾經無法將資料匯出,直接copy Xpath已經無法滿足業務需求了
        注(1)
        data_out.click()
        time.sleep(60)  #這裡的等待時間有點不好控制
這裡曾經在函式寫法改為類寫法的時候出現超時,原因在於那時候我就放了10秒
所以這裡的速度就非常之受網路影響,此處應該應try···throw···


        #資料預下載
        data_fore_download = self.wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="export_job_modal"]/div/div/div[3]/div/a[1]')))
        data_fore_download.click()
        time.sleep(10)

        #資料下載
        data_download = self.wait.until(EC.presence_of_element_located((By.XPATH, '/html/body/div[3]/div[1]/div[3]/div/div[2]/table/tbody/tr/td[15]/table/tbody/tr/td/div[1]/span[2]/a[1]')))
這裡問題和上面一樣,無法滿足業務需求,不過有了上面做鋪墊,所以這裡解決起來就很快
        data_download.click()
        self.driver.close()


test = golden_data()
test.login_data()
test.collect_data()
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051

在我看來,copy full Xpath比較穩一些,也不知道是不是Xpath比較快一些嘛,畢竟絕對路徑和相對路徑比起來,相對路徑就是快一些的。

先到這裡,其實前面的表單自動生成我也寫的快OK了,不過保留一些懸念,慢慢加進來,對,就是放在這篇,這篇持續更新!!!

最後多說一句,想學習Python可聯絡小編,這裡有我自己整理的整套python學習資料和路線,想要這些資料的都可以進q裙947618024領取。

本文章素材來源於網路,如有侵權請聯絡刪除。