最大的問題就是解決登錄和驗證碼,登錄之后get東西就簡單了
直接上原始碼:
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import requests
import time
import numpy
import cv2
import os
'''
建議網速好一點執行此程式,否則可能會get不到資源導致程式終端或者get到的題目和答案為空
question_list_url 題目串列鏈接(只能是編程題的鏈接,其他題型同理判斷一下即可我這里沒寫)
file_name 要保存的檔案名,我使用的markdown格式
access_interval 根據網速自定義設定,訪問每到題的時間間隔s,訪問太快總會被提示,不過我寫了出現提示繼續訪問的邏輯;
'''
def Programming_questions(question_list_url,file_name,access_interval):
#創建 WebDriver 物件,指明使用chrome瀏覽器驅動
web = webdriver.Chrome(r'C:\Program Files\Google\Chrome\Application\chromedriver.exe')
web.implicitly_wait(5)
#呼叫WebDriver 物件的get方法 可以讓瀏覽器打開指定網址
web.get('https://pintia.cn/auth/login')
zh = web.find_element_by_xpath('/html/body/div[1]/div[3]/div/div[2]/form/div[1]/div[1]/div/div/div[1]/input')
mm = web.find_element_by_xpath('/html/body/div[1]/div[3]/div/div[2]/form/div[1]/div[2]/div/div/div[1]/input')
#在PTA的賬號密碼:
zh.send_keys('xxxx@qq.com')
mm.send_keys('xxxx')
#找到登錄按鈕并點擊
web.find_element_by_xpath('/html/body/div[1]/div[3]/div/div[2]/form/div[2]/button/div/div').click()
for i in range(5):
#等待一會,時間間隔可根據網速調整,驗證碼加載完成
time.sleep(3)
print('當前url:'+web.current_url)
#如果當前url沒變說明驗證未通過,回圈5(可修改)次重新驗證
if(web.current_url!='https://pintia.cn/auth/login'):
break
#bg背景圖片
bg_img_src = web.find_element_by_xpath(
'/html/body/div[3]/div[2]/div/div/div[2]/div/div[1]/div/div[1]/img[1]').get_attribute('src')
#front可拖動圖片
front_img_src = web.find_element_by_xpath(
'/html/body/div[3]/div[2]/div/div/div[2]/div/div[1]/div/div[1]/img[2]').get_attribute('src')
#保存圖片
with open("bg.jpg", mode="wb") as f:
f.write(requests.get(bg_img_src).content)
with open("front.jpg", mode="wb") as f:
f.write(requests.get(front_img_src).content)
#將圖片加載至記憶體
bg = cv2.imread("bg.jpg")
front = cv2.imread("front.jpg")
#將背景圖片轉化為灰度圖片,將三原色降維
bg = cv2.cvtColor(bg, cv2.COLOR_BGR2GRAY)
#將可滑動圖片轉化為灰度圖片,將三原色降維
front = cv2.cvtColor(front, cv2.COLOR_BGR2GRAY)
front = front[front.any(1)]
#用cv演算法匹配精度最高的xy值
result = cv2.matchTemplate(bg, front, cv2.TM_CCOEFF_NORMED)
#numpy決議xy,注意xy與實際為相反,x=y,y=x
x, y = numpy.unravel_index(numpy.argmax(result), result.shape)
#找到可拖動區域
div = web.find_element_by_xpath('/html/body/div[3]/div[2]/div/div/div[2]/div/div[2]/div[2]')
#拖動滑塊,以實際相反的y值代替x
ActionChains(web).drag_and_drop_by_offset(div, xoffset=y // 0.946, yoffset=0).perform()
#至此成功破解驗證碼,由于演算法問題,準確率不能達到100%,所以加了回圈判斷
#要get的題目集串列
web.get(question_list_url)
#獲取所以題目行
trp_problems = web.find_elements_by_xpath('/html/body/div/div[3]/div[3]/div/div[3]/table//tbody/tr')
#存放所有題目的鏈接
problems_href=[]
for tr in trp_problems:
problems_href.append(tr.find_element_by_xpath('td[3]/a').get_attribute('href'))
#count用來方便測驗,如果中間程式斷掉也可以通過修改count的值和條件判斷從上次的地方繼續執行
count = 0
filePro = open(file_name,'a')
for problem in problems_href:
if count>=0:
#訪問太快會被彈出提示頁面,所以加個回圈一直訪問(回圈次數自定義)
for i in range(5):
try:
web.get(problem)
time.sleep(access_interval) # 根據網速設定時間間隔,訪問太快也會被提示
# 獲取題目和答案
tm_title = web.find_element_by_css_selector("[class='text-center black-3 text-4 font-weight-bold my-3']").text
mycode = web.find_element_by_css_selector('textarea').get_attribute('value')
print('題目:' + tm_title)
print(mycode)
#寫入格式是markdown檔案:題目和代碼
filePro.write('**' + tm_title + '**\n' + '```\n' + mycode + '\n```' + os.linesep)
break #全部正常執行完說明沒有彈出提示頁面,退出即可
except:
continue
count += 1
print('--------------------------------完成數量'+str(count)+'---------------------------------------')
filePro.close()
if __name__ == '__main__':
Programming_questions('https://pintia.cn/problem-sets/1371739727887736832/problems/type/7','test2.md',2.5)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/271985.html
標籤:python
