Skip to content

Instantly share code, notes, and snippets.

@arthur-tomsjj
Last active May 30, 2021 08:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arthur-tomsjj/925f60313fad7c83bd8cf5dbe4eb7603 to your computer and use it in GitHub Desktop.
Save arthur-tomsjj/925f60313fad7c83bd8cf5dbe4eb7603 to your computer and use it in GitHub Desktop.
拓元自動購票系統
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from PIL import Image
from bs4 import BeautifulSoup
import cv2
import requests
import numpy as np
import pytesseract
import time
import os
url = "https://tixcraft.com/activity/detail/21_Eclipse"
driver = webdriver.Chrome('D:\\PythonLab\\chromedriver_win32\\chromedriver.exe')
driver.get(url)
#下拉視窗
def scroll(num):
js="var q=document.documentElement.scrollTop = "+str(num)
driver.execute_script(js)
time.sleep(1)
scroll(500)
#點開購票
elem_operate_1 = driver.find_element_by_xpath("//*[@id='content']/div/div/ul/li[1]/a")
elem_operate_1.click()
time.sleep(2)
#立即購票
elem_operate_2 = driver.find_element_by_xpath("//*[@id='gameList']/table/tbody/tr/td[4]/input")
elem_operate_2.click()
time.sleep(1)
#新網頁下拉
scroll(500)
#尋找還能購買的座位
seat_number = 1
while 1:
elem_choose = driver.find_element_by_xpath("/html/body/div/div[2]/div[2]/div/div[2]/div[2]/div[2]/ul["+str(seat_number)+"]/li")
if elem_choose.text.find("已售完") < 0:
break
seat_number += 1
elem_choose.click()
time.sleep(1)
#到購買頁面
#下拉視窗
scroll(400)
#選擇票數
elem_select_num = driver.find_element_by_xpath("//*[@id='TicketForm_ticketPrice_10']")
Select(elem_select_num).select_by_value("1")
#下載驗證
#無法使用以下圖片下載法,因為下載來後會因requests再次訪問網站使載到的驗證圖改變
#html = driver.page_source
#page = BeautifulSoup(html,'html.parser')
#captcha_IMG = page.find(id = 'yw0')
#IMG_url = "https://tixcraft.com" + captcha_IMG['src']
#print()
#IMG_NAME = IMG_url.split('=')
#fname = 'captcha/'+IMG_NAME[-1]+'.png'
#data = requests.get(IMG_url)
#with open(fname,'wb') as f:
# f.write(data.content)
# f.close() '''
#要用截圖大法
path = 'captcha/screenshot.png'
driver.save_screenshot(path) # 先將目前的 screen 存起來
time.sleep(1)
element = driver.find_element_by_xpath("//*[@id='yw0']")
location = element.location # 取得圖片 element 的位置
size = element.size # 取得圖片 element 的大小
left = location['x']+75 # 決定上下左右邊界
top = location['y']-370
right = location['x'] + size['width']+100
bottom = location['y'] + size['height']-350
image = Image.open(path) # 將 screen load 至 memory
image = image.crop((left,top,right,bottom)) # 根據位置剪裁圖片
image.save('captcha/captcha'+'.png', 'png') # 重新儲存圖片為 png 格式
#抓下驗證後,用tesseract圖片辨識
# 灰度 0-255 255-當前灰度值
img = cv2.imread('captcha/captcha.png')
imginfo = img.shape #取得圖片size的長寬 (長,寬) ,tuple型態
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #opencv的彩色轉灰階
height = imginfo[0]
width = imginfo[1]
center = (width//2,height//2) #取得圖片中心位置
M = cv2.getRotationMatrix2D(center,-5,1.0) #以中心順時鐘旋轉5度,負為順,正為逆;1.0 為縮放
gray1 = cv2.warpAffine(gray,M,(width,height)) #warpAffine為圖片旋轉或平移的式子 參數: 圖檔, 旋轉or平移參數, (長寬)
dst = np.zeros((height, width, 1), np.uint8)
for i in range(height): #顏色反轉
for j in range(width):
grayPixel = 255 - gray1[i, j]
dst[i, j] = grayPixel
cv2.imwrite('captcha/captcha_gray.png',dst) #OpenCV 圖片儲存的方法
#進行圖片二元化
picture = Image.open('captcha/captcha_gray.png')
gray = picture.convert('L')
table = []
threshold = 115
for i in range(256):
if i < threshold:
table.append(0)
else:
table.append(1)
binary = gray.point(table,'1')
binary.save('captcha/captcha_binary.png') #PIL 圖片儲存方法
#圖片識別
Pic_read = Image.open('captcha/captcha_binary.png')
pytesseract.pytesseract.tesseract_cmd = r'D:\PythonLab\OCR_database\tesseract.exe'
text = pytesseract.image_to_string(Pic_read)
#進行驗證碼輸入
input_captcha = driver.find_element_by_xpath("//*[@id='TicketForm_verifyCode']")
input_captcha.send_keys(text)
try:
driver.switch_to_alert().accept() #若出現彈出視窗,點掉
except Exception as e:
input_captcha.send_keys(text)
pass
#點選"我同意"
accept = driver.find_element_by_xpath("//*[@id='TicketForm_agree']")
accept.click()
#提交
confirm = driver.find_element_by_xpath("//*[@id='ticketPriceSubmit']")
confirm.click()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment