Closed Yonion2 closed 2 months ago
根据之前一些同学的反应,可能原因是 1. 开了vpn (需要关掉) 2. 没在内网(可能需要) 3. 配置selenium的时候,系统的chorme浏览器版本和chormedriver的版本不对应
谢谢,我换成内网试一下 ---- 回复的原邮件 ---- @.>发送日期2024年8月29日 @.>@.>, @.>主题Re: [MinhZou/FudanCourtReservation] 最大请求数超时 (Issue #1) 根据之前一些同学的反应,可能原因是 1. 开了vpn (需要关掉) 2. 没在内网(可能需要) 3. 配置selenium的时候,系统的chorme浏览器版本和chormedriver的版本不对应 — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you authored the thread.Message ID: @.***>
排除了1234种可能性还是不行,代码也被gpt指导改来改去,太晕了,求指导,不知道是怎么回事。
""" Use to book sports venues on the Fudan campus @author: MinhZou @date: 2022-04-03 update 2024-07-25 @e-mail: 770445973@qq.com """
import os import io import sys import re import yaml import json import random import time import datetime import logging from bs4 import BeautifulSoup from lxml import etree import urllib.parse import requests from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.by import By from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.alert import Alert from apscheduler.schedulers.blocking import BlockingScheduler from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import multiprocessing import threading import base64 import numpy as np from PIL import Image from io import BytesIO import cv2 from utils.chaojiying import Chaojiying_Client from selenium.webdriver.common.action_chains import ActionChains
from utils import send_email, image_process
logging.basicConfig(level=logging.INFO, format='[%(asctime)s - %(name)s - %(levelname)s - %(process)s - %(thread)s] %(message)s')
class Client(object): def init(self, configs): if isinstance(configs, str): with open(configs, 'r') as file: configs = yaml.safe_load(file)
self.username = configs['username']
self.password = configs['password']
self.orderuser = configs['orderuser']
self.mobile = configs['mobile']
self.court_name = configs['court_name']
self.email = configs['email']
self.driver_path = './chromedriver/chromedriver.exe'
# self.time_end = time_end
self.time_end = '23:59:59'
self.cookie = ''
self.cookie_dic = {}
self.courts_dic = {
# '江湾体育馆网球场':'8aecc6ce7176eb18017225bfcd292809',
# '江湾体育馆排球场': '8aecc6ce7176eb18017225c2e7d62831',
'张江校区网球场': '8aecc6ce8ee75f34018f047dc8ca407a',
'杨詠曼楼琴房': '8aecc6ce7bc2eea5017bed81312c5f49',
'张江校区食堂三楼羽毛球(非标)': '8aecc6ce7641d43101764ac0e3c1524d',
'江湾体育馆羽毛球场':'8aecc6ce749544fd01749a31a04332c2',
'江湾体育馆室内网球': '8aecc6ce90ae440c0191458edad81857',
'江湾体育馆篮球场(半场)': '8aecc6ce7176eb18017225c1505f2819',
'江湾体育馆排球场1号': '8aecc6ce878581d701879c7548c6737d',
'江湾体育馆排球场2号': '8aecc6ce7176eb18017225c2e7d62831',
'江湾室外网球场':'8aecc6ce780fe18301786c51f2a5627b',
'正大体育馆羽毛球(标场)': '2c9c486e4f821a19014f82418a900004',
'正大体育馆羽毛球(非标场)': '2c9c486e4f821a19014f86df4f662ba9',
'南区国权路网球场': '8aecc6ce7d2dffbd017de9ea4e7e4ece',
'南区网球场': '8aecc6ce6b6e6698016bc5dc173c11b7',
'邯郸路足球场': '2c9c486e4f821a19014f8266341f002f',
'北区体育馆羽毛球(标场)':'2c9c486e4f821a19014f826f2a4f0036',
'北区体育馆羽毛球(非标场)': '000000005079fc7001507a0f09a2000e',
'北区体育馆篮球': '2c9c486e4f821a19014f82706dfb003c',
'北区体育馆排球':'2c9c486e4f821a19014f827298da0047',
'北区体育馆舞蹈房(二楼)': '2c9c486e4f821a19014f82746a000052',
'北区体育馆舞蹈房(三楼)': '2c9c486e4f821a19014f82754b190058',
'枫林学生活动中心三楼羽毛球馆': '8aecc6ce66f1173501675d11508e75eb',
'枫林综合体育馆篮球(半场)': '8aecc6ce66f117350167070ac2393bca',
'枫林综合体育馆排球场': '8aecc6ce8672f0cd01869b1151d540f3',
'北区体育馆乒乓球': '8aecc6ce8d17fc0e018e50bc62d0332b',
'南区体育馆乒乓球': '8aecc6ce8d17fc0e018e50c24f3a3367',
'枫林学生活动中心乒乓球': '8aecc6ce8d17fc0e018e50cafd7b33b8',
'张江学生活动中心乒乓球': '8aecc6ce8d17fc0e018e50d1a00633f1',
'江湾体育馆乒乓球场': '8aecc6ce8ee75f34018eeef359057431',
}
self.content_id = self.courts_dic[self.court_name]
self.category_id = '2c9c486e4f821a19014f82381feb0001'
self.count_var = multiprocessing.Value('i', 0)
self.resource_dic = multiprocessing.Manager().dict()
self.status_dic = multiprocessing.Manager().dict()
self.reserved_dic = multiprocessing.Manager().dict()
self.today_date = datetime.datetime.now().strftime("%Y-%m-%d") # '2022-03-20'
self.search_date = (datetime.datetime.now() + datetime.timedelta(days=2)).strftime("%Y-%m-%d")
self.time_scheduled = datetime.datetime.strptime('{} {}'.format(self.today_date, self.time_end), '%Y-%m-%d %H:%M:%S')
# self.logger = log.get_logger('logs', name='client') logging not support multiprocess
# Use to recognize the Verification Code (http://www.chaojiying.com/).
self.cjy_usrname = '###'
self.cjy_password = '###'
self.cjy_soft_id = '###'
self.Chaojiying_Client = Chaojiying_Client(self.cjy_usrname, self.cjy_password, self.cjy_soft_id)
# Preseted time order
# self.stage_1 = ['20:00', '19:00', '18:00']
self.stage_1 = configs['stage_1']
# self.stage_1 = ['14:00', '15:00', '16:00']
self.stage_2 = ['17:00', '16:00', '15:00']
self.stage_3 = ['11:00', '10:00', '09:00']
#
self.user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ' \
'(KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36'
def get_cookie_by_selenium(self):
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.binary_location = "C:/Program Files/Google/Chrome/Application/chrome.exe" # 这里使用您找到的路径
# 无头模式配置
chrome_options.add_argument("--headless") # 无头模式
chrome_options.add_argument("--disable-gpu") # 禁用GPU加速
chrome_options.add_argument("--no-sandbox") # 禁用沙盒模式
chrome_options.add_argument("--disable-dev-shm-usage") # 禁用共享内存
service = Service(
executable_path='C:/Users/A/Downloads/FudanCourtReservation-main/FudanCourtReservation-main/chromedriver/chromedriver.exe')
browser = webdriver.Chrome(service=service, options=chrome_options)
browser.get(
"https://uis.fudan.edu.cn/authserver/login?service=https%3A%2F%2Felife.fudan.edu.cn%2Flogin2.action")
time.sleep(5)
browser.find_element(By.ID, "username").send_keys("{}".format(self.username))
browser.find_element(By.ID, "password").send_keys("{}".format(self.password))
logging.info('成功填充账号和密码!!!')
time.sleep(2)
browser.find_element(By.ID, "idcheckloginbtn").click()
time.sleep(6)
cookie_items = browser.get_cookies()
cookie_str = ''
for item_cookie in cookie_items:
item_str = item_cookie["name"] + "=" + item_cookie["value"] + "; "
cookie_str += item_str
browser.quit()
if 'iPlanetDirectoryPro' in cookie_str:
logging.info('成功获取cookie!!!')
logging.info(cookie_str)
self.cookie = cookie_str
cookie_lst = self.cookie.split(';')
for c_item in cookie_lst:
c = c_item.strip()
c_new = c.split('=')
if len(c_new) == 2:
self.cookie_dic[c_new[0]] = c_new[1]
return cookie_str
def get_resource(self):
import requests
import ssl
# 创建自定义的HTTP适配器
class CustomHttpAdapter(requests.adapters.HTTPAdapter):
def init_poolmanager(self, *args, **kwargs):
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
context.options |= ssl.OP_ALL # 允许所有选项
context.options &= ~ssl.OP_NO_SSLv2
context.options &= ~ssl.OP_NO_SSLv3
context.options &= ~ssl.OP_NO_TLSv1
context.options &= ~ssl.OP_NO_TLSv1_1
context.options &= ~ssl.OP_NO_TLSv1_2
context.options &= ~ssl.OP_NO_TLSv1_3
kwargs['ssl_context'] = context
return super(CustomHttpAdapter, self).init_poolmanager(*args, **kwargs)
# 创建一个Session对象
session = requests.Session()
# 将自定义的HTTP适配器挂载到Session对象上
session.mount('https://', CustomHttpAdapter())
# 定义请求的URL和头部信息
resource_url = 'https://elife.fudan.edu.cn/public/front/getResource2.htm?' \
'contentId={}&ordersId=¤tDate={}'.format(self.content_id, self.search_date)
headers = {
'cookie': self.cookie,
'referer': 'https://elife.fudan.edu.cn/public/front/toResourceFrame.htm?contentId={}'.format(
self.content_id),
'user-agent': self.user_agent,
'Connection': 'close'
}
try:
logging.info('获取ID中...')
resource_resp = session.get(resource_url, headers=headers)
html_resource = resource_resp.text
# 进一步处理HTML资源
except Exception as e:
logging.info(str(e))
time.sleep(5)
self.cookie = self.get_cookie_by_selenium()
def get_captcha_image_and_valid_text(self, browser):
try:
img_selector = "img.valid_bg-img"
valid_text_selector = "span.valid_tips__text"
wait = WebDriverWait(browser, 5) # 等待最多5秒
img_element = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, img_selector)))
valid_tips_text = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, valid_text_selector)))
valid_text = valid_tips_text.text.split("请依次点击:")[-1]
print(f"Successfully retrieved valid text: {valid_text}")
base64_str = img_element.get_attribute('src')
if base64_str:
captcha_image = image_process.base64_to_image(base64_str)
else:
captcha_image = None
except Exception as e:
print(f"An error occurred: {e}")
valid_text = None
captcha_image = None
return captcha_image, valid_text
def get_captcha_results(self, captcha_image):
if captcha_image:
res_dic = self.Chaojiying_Client.post_pic(captcha_image, 9501)
captcha_dic = self.Chaojiying_Client.extract_coordinates(res_dic)
else:
captcha_dic = None
return captcha_dic
def click_captcha(self, browser, valid_text, captcha_dic):
captcha_element = browser.find_element(By.CLASS_NAME, 'valid_bg-img')
def replace_similar_chars(s, d):
for char in s:
matches = sum(1 for k in d if k == char)
if matches >= 3:
for k in list(d.keys()):
if k == char:
d[char] = d.pop(k)
return d
# 文字识别不准确,手动调整,减少retry次数
if len(valid_text) == len(captcha_dic) == 4:
replace_similar_chars(valid_text, captcha_dic)
if valid_text and captcha_dic:
for _, valid_word in enumerate(valid_text):
left = captcha_dic.get(valid_word, {}).get('left', 50) # - 10
top = captcha_dic.get(valid_word, {}).get('top', 50) # - 20
actions = ActionChains(browser)
actions.move_to_element_with_offset(captcha_element, left, top).click().perform()
time.sleep(0.5)
return
def get_order_page_by_selenium(self, resource_id):
chrome_options = Options()
chrome_options.add_argument("--headless")
chrome_options.binary_location = "C:/Program Files/Google/Chrome/Application/chrome.exe"
s = Service(r'{}'.format(self.driver_path))
# browser = webdriver.Chrome(service=s)
browser = webdriver.Chrome(service=s, options=chrome_options)
order_page_url = 'https://elife.fudan.edu.cn/public/front/loadOrderForm_ordinary.htm?' \
'serviceContent.id={}&serviceCategory.id={}&codeStr=&resourceIds={}&orderCounts=1'.format(self.content_id, self.category_id, resource_id)
browser.get(order_page_url)
for key, val in self.cookie_dic.items():
c_dic = {"name": key, "value": val}
browser.add_cookie(c_dic)
browser.get(order_page_url)
# browser.refresh()
time.sleep(5)
try:
verify_button = browser.find_element_by_css_selector('#verify_button1')
verify_button.click() #
time.sleep(1)
except Exception as e:
logging.info('Faild to click verify_button', exc_info=True)
browser.quit()
return
captcha_image, valid_text = self.get_captcha_image_and_valid_text(browser)
captcha_dic = self.get_captcha_results(captcha_image)
print(f"Successfully retrieved captcha results: {captcha_dic}")
# # Test
# valid_text = "农务民息"
# captcha_dic = {'务': {'left': 285, 'top': 129}, '息': {'left': 197, 'top': 127},
# '民': {'left': 121, 'top': 102}, '农': {'left': 56, 'top': 81}}
self.click_captcha(browser, valid_text, captcha_dic)
max_tries = 3
time.sleep(1)
for i in range(max_tries):
value = None
try:
input_element = browser.find_element(By.ID, 'validateCode')
value = input_element.get_attribute('value')
except Exception as e:
print("Error:", e)
if value:
print("Verification passed!")
break
else:
print("Verification failed!")
print("Retrying...")
time.sleep(3)
captcha_image, valid_text = self.get_captcha_image_and_valid_text(browser)
captcha_dic = self.get_captcha_results(captcha_image)
print(f"Successfully retrieved captcha results: {captcha_dic}")
# # Test
# valid_text = "农务民息"
# captcha_dic = {'务': {'left': 285, 'top': 129}, '息': {'left': 197, 'top': 127},
# '民': {'left': 121, 'top': 102}, '农': {'left': 56, 'top': 81}}
self.click_captcha(browser, valid_text, captcha_dic)
time.sleep(1)
try:
element = browser.find_element_by_id('btn_sub')
browser.execute_script("arguments[0].click();", element)
except Exception as e:
print("=======")
raise
browser.quit()
return
def get_status(self):
import requests
import ssl
# 创建自定义的HTTP适配器
class CustomHttpAdapter(requests.adapters.HTTPAdapter):
def init_poolmanager(self, *args, **kwargs):
context = ssl.create_default_context()
context.options |= ssl.OP_LEGACY_SERVER_CONNECT
kwargs['ssl_context'] = context
return super(CustomHttpAdapter, self).init_poolmanager(*args, **kwargs)
# 创建一个Session对象
session = requests.Session()
# 将自定义的HTTP适配器挂载到Session对象上
session.mount('https://', CustomHttpAdapter())
# 定义请求的URL和头部信息
status_url = 'https://elife.fudan.edu.cn/public/userbox/index.htm?userConfirm=&orderstateselect='
headers = {
'cookie': self.cookie,
'referer': 'https://elife.fudan.edu.cn/public/userbox/index2.htm',
'user-agent': self.user_agent,
'Connection': 'close',
}
# 使用Session对象发送请求
resource_resp = session.get(status_url, headers=headers)
# 处理响应
if resource_resp.status_code == 200:
html_resource = resource_resp.text
# 进一步处理HTML资源
else:
print(f"请求失败,状态码: {resource_resp.status_code}")
def cancel_reservation(self, search_date, time):
order_id = self.status_dic[self.search_date + '-' + time]
cancel_url = 'https://elife.fudan.edu.cn/public/userbox/canCancel.htm?orderid={}'.format(order_id)
cancel_headers = {
'cookie': self.cookie,
'referer': 'https://elife.fudan.edu.cn/public/userbox/index.htm?userConfirm=&orderstateselect=',
'user-agent': self.user_agent,
'Connection': 'close',
}
data_form = {
'pageNo': '',
'orderdate': '',
'orderstateselect': '',
'userConfirm': '0',
'orderId': '',
}
cancel_get_url = 'https://elife.fudan.edu.cn/public/userbox/cancelMyself.htm?orderid={}'.format(order_id)
post_resp = requests.post(url=cancel_url, data=data_form, headers=cancel_headers)
get_resp = requests.get(url=cancel_get_url, headers=cancel_headers)
post_resp.close()
get_resp.close()
return post_resp
def book_court(self, order_time, time_str):
resource_id = self.resource_dic[order_time]
logging.info('正在预定{}-{} {}'.format(self.court_name, self.search_date, order_time))
self.get_order_page_by_selenium(resource_id)
count = 1
while True:
self.get_status()
# if len(updated_status) > self.status_dic:
# self.status_dic = updated_status
# status_dic = self.get_status()
key = self.search_date[-5:] + '-' + order_time
logging.info(self.status_dic)
logging.info(key)
if key in self.status_dic:
# logging.info('长度为{}:{}'.format(len(resp_txt), resp_txt))
self.reserved_dic[order_time] = 1
now_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
flag = send_email.send_mail(now_time, time_str, self.court_name, self.username, self.email)
if flag:
logging.info('邮件发送成功!')
else:
logging.info('邮件发送失败!')
break
else:
time.sleep(1)
# logging.info('长度为{}:{}'.format(len(resp_txt), resp_txt))
logging.info('第{}次重新预定{}-{} {}'.format(count, self.court_name, self.search_date, order_time))
self.get_order_page_by_selenium(resource_id)
count += 1
if count >= 3:
break
return
def single_job(self, order_time):
self.today_date = datetime.datetime.now().strftime("%Y-%m-%d") # '2022-03-20'
self.search_date = (datetime.datetime.now() + datetime.timedelta(days=2)).strftime("%Y-%m-%d")
# self.time_scheduled = datetime.datetime.strptime('{} {}'.format(self.today_date, self.time_end), '%Y-%m-%d %H:%M:%S')
self.time_scheduled = datetime.datetime.now() + datetime.timedelta(minutes=5, seconds=40)
# ******************************************************************************************
logging.info('*********************************Settings******************************')
logging.info('预定人: {}'.format(self.orderuser))
logging.info('手机号: {}'.format(self.mobile))
logging.info('今天的日期: {}'.format(self.today_date))
logging.info('预定的日期: {}'.format(self.search_date))
logging.info('预定的场地:{}'.format(self.court_name))
logging.info('预定的时间段:{}'.format(self.stage_1))
logging.info('已预约的时间段:{}'.format(self.reserved_dic))
logging.info('***********************************************************************')
# ******************************************************************************************
try:
self.cookie = self.get_cookie_by_selenium()
except Exception as e:
logging.info(str(e))
time.sleep(5 + 2*random.random())
self.cookie = self.get_cookie_by_selenium()
while 'iPlanetDirectoryPro' not in self.cookie:
logging.info('cookie获取失败,重新获取...')
time.sleep(5 + 2*random.random())
self.cookie = self.get_cookie_by_selenium()
while True:
self.get_status()
# updated_status = self.get_status(self.cookie)
# if len(updated_status) > self.status_dic:
# self.status_dic = updated_status
# key = search_date[-5:] + '-' + order_time
self.count_var.value = len(self.status_dic)
if self.count_var.value >= 2:
break
now_time = datetime.datetime.now()
if (now_time - self.time_scheduled).total_seconds() > 0:
break
try:
if not self.resource_dic:
logging.info('{} {} 无场地可约'.format(self.court_name, self.search_date))
# resource_jobs = []
for _ in range(2):
t = threading.Thread(target=self.get_resource, args=())
t.setDaemon(True)
t.start()
time.sleep(0.4)
if (datetime.datetime.now() - (self.time_scheduled - datetime.timedelta(minutes=1, seconds=40))).total_seconds() > 0:
time.sleep(1 + 0.8*random.random())
else:
time.sleep(4 + 2*random.random())
else:
for key, val in self.resource_dic.items():
logging.info('{}-{} {} 可约, ID为{}'.format(self.court_name, self.search_date, key, val))
if self.count_var.value >= 3:
break
time_str = self.search_date + ' ' + order_time
now_time = datetime.datetime.now()
if order_time in self.resource_dic and order_time not in self.reserved_dic.keys():
self.book_court(order_time, time_str)
elif order_time in self.reserved_dic.keys():
logging.info("已经预定 {}-{} {}".format(self.court_name, self.search_date, order_time))
break
else:
logging.info("不可约 {}-{} {}".format(self.court_name, self.search_date, order_time))
for _ in range(1):
t = threading.Thread(target=self.get_resource, args=())
t.setDaemon(True)
t.start()
time.sleep(5 + 2*random.random())
except Exception as e:
logging.info(str(e))
time.sleep(5)
self.cookie = self.get_cookie_by_selenium()
def scheduled_job(self):
my_jobs = []
for order_time in self.stage_1:
p = multiprocessing.Process(target=self.single_job, args=(order_time,))
my_jobs.append(p)
time.sleep(3)
p.start()
# # other time
# time.sleep(190)
# for order_time in self.stage_2:
# if self.count_var.value < 3:
# p = multiprocessing.Process(target=self.single_job, args=(order_time,))
# my_jobs.append(p)
# time.sleep(0.1)
# p.start()
# time.sleep(10)
# for order_time in self.stage_3:
# if self.count_var.value < 3:
# p = multiprocessing.Process(target=self.single_job, args=(order_time,))
# my_jobs.append(p)
# time.sleep(0.1)
# p.start()
for p in my_jobs:
p.join()
这是后台的显示:
DevTools listening on ws://127.0.0.1:54018/devtools/browser/46a52ebe-d379-4c18-99cf-2ebe95c786cd [2024-08-31 03:42:10,719 - root - INFO - 6680 - 9816] 成功填充账号和密码!!! [2024-08-31 03:42:13,872 - root - INFO - 24112 - 24936] 成功填充账号和密码!!! [2024-08-31 03:42:22,001 - root - INFO - 6680 - 9816] 成功获取cookie!!! [2024-08-31 03:42:22,001 - root - INFO - 6680 - 9816] NSC_Xfc-DpoufouTxjudi-443=ffffffff096ca61a45525d5f4f58455e445a4a423660; JSESSIONID=21A3BCEF3680FDB8D85A1DAD8397B0D3; iPlanetDirectoryPro=ejysUHdvP4llKodEnyijEn; [2024-08-31 03:42:25,161 - root - INFO - 24112 - 24936] 成功获取cookie!!! [2024-08-31 03:42:25,161 - root - INFO - 24112 - 24936] NSC_Xfc-DpoufouTxjudi-443=ffffffff096ca61a45525d5f4f58455e445a4a423660; JSESSIONID=3FD2D9308B51B24284A8E0198362D11D; iPlanetDirectoryPro=JyzWtMM9boaz2BjIzFIxQW; Process Process-4: Traceback (most recent call last): File "C:\Users\A\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\process.py", line 314, in _bootstrap self.run() File "C:\Users\A\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\process.py", line 108, in run self._target(*self._args, *self._kwargs) File "C:\Users\A\Downloads\FudanCourtReservation-main\FudanCourtReservation-main\scripts\client.py", line 462, in single_job self.get_status() File "C:\Users\A\Downloads\FudanCourtReservation-main\FudanCourtReservation-main\scripts\client.py", line 352, in get_status session.mount('https://', CustomHttpAdapter()) ^^^^^^^^^^^^^^^^^^^ File "C:\Users\A\AppData\Local\Programs\Python\Python311\Lib\site-packages\requests\adapters.py", line 222, in init self.init_poolmanager(pool_connections, pool_maxsize, block=pool_block) File "C:\Users\A\Downloads\FudanCourtReservation-main\FudanCourtReservation-main\scripts\client.py", line 344, in init_poolmanager context.options |= ssl.OP_LEGACY_SERVER_CONNECT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AttributeError: module 'ssl' has no attribute 'OP_LEGACY_SERVER_CONNECT' Process Process-5: Traceback (most recent call last): File "C:\Users\A\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\process.py", line 314, in _bootstrap self.run() File "C:\Users\A\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\process.py", line 108, in run self._target(self._args, **self._kwargs) File "C:\Users\A\Downloads\FudanCourtReservation-main\FudanCourtReservation-main\scripts\client.py", line 462, in single_job self.get_status() File "C:\Users\A\Downloads\FudanCourtReservation-main\FudanCourtReservation-main\scripts\client.py", line 352, in get_status session.mount('https://', CustomHttpAdapter()) ^^^^^^^^^^^^^^^^^^^ File "C:\Users\A\AppData\Local\Programs\Python\Python311\Lib\site-packages\requests\adapters.py", line 222, in init self.init_poolmanager(pool_connections, pool_maxsize, block=pool_block) File "C:\Users\A\Downloads\FudanCourtReservation-main\FudanCourtReservation-main\scripts\client.py", line 344, in init_poolmanager context.options |= ssl.OP_LEGACY_SERVER_CONNECT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AttributeError: module 'ssl' has no attribute 'OP_LEGACY_SERVER_CONNECT'
C:\Users\A\Downloads\FudanCourtReservation-main\FudanCourtReservation-main>
我的建议是先直接使用这个库里最原始的代码,然后排除1234就可以了,现在这个报错部分因为是额外加的代码,大概是后加session部分是不对的,这里应该不能这样用,具体我也不是很清楚,所以我建议用回原始的代码,跑通之后再修改代码。
好的,我再试试!谢谢☺️
发自我的iPhone
------------------ 原始邮件 ------------------ 发件人: Minhao @.> 发送时间: 2024年8月31日 10:06 收件人: MinhZou/FudanCourtReservation @.> 抄送: cocoILoveYoucoco @.>, Comment @.> 主题: Re: [MinhZou/FudanCourtReservation] 最大请求数超时 (Issue #1)
我的建议是先直接使用这个库里最原始的代码,然后排除1234就可以了,现在这个报错部分因为是额外加的代码,大概是后加session部分是不对的,这里应该不能这样用,具体我也不是很清楚,所以我建议用回原始的代码,跑通之后再修改代码。
— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you commented.Message ID: @.***>
您好,我试了1、2、3、4,还是没有解决,用的是最原始的代码没改过,我自己的账号能抢场地,4应该没有问题,这个代码爬其他网页是没啥问题的,就是爬抢场地系统会超时,是被ban了嘛
刚运行了,并不存在问题,还是请再次检查3,因为之前有同学看错版本号的,系统的chorme浏览器版本和chormedriver的版本不对应,具体方式如这个教程说明: https://zhuanlan.zhihu.com/p/661200102
[2024-08-31 21:37:03,402 - root - INFO - 17276 - 10228] *Settings** [2024-08-31 21:37:03,402 - root - INFO - 17276 - 10228] 预定人: xxx [2024-08-31 21:37:03,404 - root - INFO - 17276 - 10228] 手机号: xxx [2024-08-31 21:37:03,408 - root - INFO - 17276 - 10228] 今天的日期: 2024-08-31 [2024-08-31 21:37:03,408 - root - INFO - 17276 - 10228] 预定的日期: 2024-09-02 [2024-08-31 21:37:03,409 - root - INFO - 17276 - 10228] 预定的场地:江湾体育馆排球场1号 [2024-08-31 21:37:03,409 - root - INFO - 17276 - 10228] 预定的时间段:['09:00', '08:00'] [2024-08-31 21:37:03,411 - root - INFO - 17276 - 10228] 已预约的时间段:{} [2024-08-31 21:37:03,411 - root - INFO - 17276 - 10228] ***
DevTools listening on ws://127.0.0.1:3210/devtools/browser/d48caa86-d8eb-4837-b670-da61213f8cdc [2024-08-31 21:37:06,406 - root - INFO - 9236 - 12652] *Settings** [2024-08-31 21:37:06,407 - root - INFO - 9236 - 12652] 预定人: xxx [2024-08-31 21:37:06,408 - root - INFO - 9236 - 12652] 手机号: xxxx [2024-08-31 21:37:06,409 - root - INFO - 9236 - 12652] 今天的日期: 2024-08-31 [2024-08-31 21:37:06,413 - root - INFO - 9236 - 12652] 预定的日期: 2024-09-02 [2024-08-31 21:37:06,413 - root - INFO - 9236 - 12652] 预定的场地:江湾体育馆排球场1号 [2024-08-31 21:37:06,414 - root - INFO - 9236 - 12652] 预定的时间段:['09:00', '08:00'] [2024-08-31 21:37:06,416 - root - INFO - 9236 - 12652] 已预约的时间段:{} [2024-08-31 21:37:06,416 - root - INFO - 9236 - 12652] ***
DevTools listening on ws://127.0.0.1:3232/devtools/browser/f31913aa-7e57-4e00-ae86-30f3f2e56498 [2024-08-31 21:37:10,165 - root - INFO - 17276 - 10228] 成功填充账号和密码!!! [2024-08-31 21:37:12,989 - root - INFO - 9236 - 12652] 成功填充账号和密码!!! [2024-08-31 21:37:21,410 - root - INFO - 17276 - 10228] 成功获取cookie!!! [2024-08-31 21:37:21,410 - root - INFO - 17276 - 10228] NSC_Xfc-DpoufouTxjudi-443=xxx; JSESSIONID=xxx; iPlanetDirectoryPro=xxx; [2024-08-31 21:37:21,780 - root - INFO - 17276 - 10228] 已预定{} [2024-08-31 21:37:21,783 - root - INFO - 17276 - 10228] 江湾体育馆排球场1号 2024-09-02 无场地可约 [2024-08-31 21:37:21,783 - root - INFO - 17276 - 5756] 获取ID中... [2024-08-31 21:37:22,192 - root - INFO - 17276 - 9224] 获取ID中... [2024-08-31 21:37:24,366 - root - INFO - 9236 - 12652] 成功获取cookie!!! [2024-08-31 21:37:24,366 - root - INFO - 9236 - 12652] NSC_Xfc-DpoufouTxjudi-443=xxx; JSESSIONID=xxx; iPlanetDirectoryPro=xxx; [2024-08-31 21:37:24,748 - root - INFO - 9236 - 12652] 已预定{} [2024-08-31 21:37:24,751 - root - INFO - 9236 - 12652] 江湾体育馆排球场1号-2024-09-02 08:00 可约, ID为8aecc6ce8f7d1a2501902999fddc1cc0 [2024-08-31 21:37:24,752 - root - INFO - 9236 - 12652] 江湾体育馆排球场1号-2024-09-02 09:00 可约, ID为8aecc6ce8f7d1a2501902999fddc1cc2 [2024-08-31 21:37:24,752 - root - INFO - 9236 - 12652] 江湾体育馆排球场1号-2024-09-02 10:00 可约, ID为8aecc6ce8f7d1a2501902999fddc1cc4 [2024-08-31 21:37:24,752 - root - INFO - 9236 - 12652] 江湾体育馆排球场1号-2024-09-02 11:00 可约, ID为8aecc6ce8f7d1a2501902999fddc1cc6 [2024-08-31 21:37:24,753 - root - INFO - 9236 - 12652] 江湾体育馆排球场1号-2024-09-02 12:00 可约, ID为8aecc6ce8f7d1a2501902999fddc1cc8 [2024-08-31 21:37:24,753 - root - INFO - 9236 - 12652] 江湾体育馆排球场1号-2024-09-02 13:00 可约, ID为8aecc6ce8f7d1a2501902999fddc1cca [2024-08-31 21:37:24,753 - root - INFO - 9236 - 12652] 正在预定江湾体育馆排球场1号-2024-09-02 08:00
DevTools listening on ws://127.0.0.1:3298/devtools/browser/697ea7c4-e95b-4faa-abfc-c3871136805e [2024-08-31 21:37:27,433 - root - INFO - 17276 - 10228] 已预定{} [2024-08-31 21:37:27,435 - root - INFO - 17276 - 10228] 江湾体育馆排球场1号-2024-09-02 08:00 可约, ID为8aecc6ce8f7d1a2501902999fddc1cc0 [2024-08-31 21:37:27,436 - root - INFO - 17276 - 10228] 江湾体育馆排球场1号-2024-09-02 09:00 可约, ID为8aecc6ce8f7d1a2501902999fddc1cc2 [2024-08-31 21:37:27,436 - root - INFO - 17276 - 10228] 江湾体育馆排球场1号-2024-09-02 10:00 可约, ID为8aecc6ce8f7d1a2501902999fddc1cc4 [2024-08-31 21:37:27,436 - root - INFO - 17276 - 10228] 江湾体育馆排球场1号-2024-09-02 11:00 可约, ID为8aecc6ce8f7d1a2501902999fddc1cc6 [2024-08-31 21:37:27,436 - root - INFO - 17276 - 10228] 江湾体育馆排球场1号-2024-09-02 12:00 可约, ID为8aecc6ce8f7d1a2501902999fddc1cc8 [2024-08-31 21:37:27,437 - root - INFO - 17276 - 10228] 江湾体育馆排球场1号-2024-09-02 13:00 可约, ID为8aecc6ce8f7d1a2501902999fddc1cca [2024-08-31 21:37:27,438 - root - INFO - 17276 - 10228] 正在预定江湾体育馆排球场1号-2024-09-02 09:00
DevTools listening on ws://127.0.0.1:3322/devtools/browser/7e9ea8c1-2b1d-4ce3-b4d4-56e16244cfc3 [22064:15544:0831/213729.316:ERROR:page_load_metrics_update_dispatcher.cc(179)] Invalid first_paint 0.224 s for first_image_paint 0.208 s [22064:15544:0831/213729.561:ERROR:page_load_metrics_update_dispatcher.cc(179)] Invalid first_paint 0.224 s for first_image_paint 0.208 s [22064:15544:0831/213730.057:ERROR:page_load_metrics_update_dispatcher.cc(179)] Invalid first_paint 0.224 s for first_image_paint 0.208 s Successfully retrieved valid text: 朋心合力 Successfully retrieved captcha results: {'心': {'left': 141, 'top': 121}, '力': {'left': 253, 'top': 57}, '合': {'left': 187, 'top': 61}, '朋': {'left': 47, 'top': 123}} Successfully retrieved valid text: 乐事劝功 Successfully retrieved captcha results: {'心': {'left': 140, 'top': 16}, '事': {'left': 199, 'top': 128}, '功': {'left': 249, 'top': 67}, '劝': {'left': 40, 'top': 135}, '乐': {'left': 129, 'top': 95}} Verification passed! Verification passed! [2024-08-31 21:37:41,294 - root - INFO - 9236 - 12652] 已预定{'09-02-09:00': '8aecc6ce90ae440c0191a8a7e5200588', '09-02-08:00': '8aecc6ce90ae440c0191a8a7da120586'} [2024-08-31 21:37:41,297 - root - INFO - 9236 - 12652] {'09-02-09:00': '8aecc6ce90ae440c0191a8a7e5200588', '09-02-08:00': '8aecc6ce90ae440c0191a8a7da120586'} [2024-08-31 21:37:41,297 - root - INFO - 9236 - 12652] 09-02-08:00 [2024-08-31 21:37:42,290 - root - INFO - 9236 - 12652] 邮件发送成功! [2024-08-31 21:37:42,632 - root - INFO - 9236 - 12652] 已预定{'09-02-09:00': '8aecc6ce90ae440c0191a8a7e5200588', '09-02-08:00': '8aecc6ce90ae440c0191a8a7da120586'} [2024-08-31 21:37:43,897 - root - INFO - 17276 - 10228] 已预定{'09-02-09:00': '8aecc6ce90ae440c0191a8a7e5200588', '09-02-08:00': '8aecc6ce90ae440c0191a8a7da120586'} [2024-08-31 21:37:43,899 - root - INFO - 17276 - 10228] {'09-02-09:00': '8aecc6ce90ae440c0191a8a7e5200588', '09-02-08:00': '8aecc6ce90ae440c0191a8a7da120586'} [2024-08-31 21:37:43,899 - root - INFO - 17276 - 10228] 09-02-09:00 [2024-08-31 21:37:44,768 - root - INFO - 17276 - 10228] 邮件发送成功! [2024-08-31 21:37:45,101 - root - INFO - 17276 - 10228] 已预定{'09-02-09:00': '8aecc6ce90ae440c0191a8a7e5200588', '09-02-08:00': '8aecc6ce90ae440c0191a8a7da120586'}
非常感谢,我试试看把chrome版本将低于一些,因为之前是128的
应该不用降版本,我自己有一个配置是win10+chorme 128.0.6613.113,chromedriver用的是https://storage.googleapis.com/chrome-for-testing-public/128.0.6613.86/win64/chromedriver-win64.zip 能正常运行。
同学方便线下指点一下吗?可以请你吃饭打球,主要是这个问题卡了几天有点恶心了,我又试了一下,结果一样的,整不明白了 ---- 回复的原邮件 ---- @.>发送日期2024年8月31日 @.>@.>, @.>主题Re: [MinhZou/FudanCourtReservation] 最大请求数超时 (Issue #1) 应该不用降版本,我自己有一个配置是win10+chorme 128.0.6613.113,chromedriver用的是https://storage.googleapis.com/chrome-for-testing-public/128.0.6613.86/win64/chromedriver-win64.zip 能正常运行。 — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you authored the thread.Message ID: @.***>
已修复python 3.10+导致的ssl错误
你好,我修改了学号和密码,注册了超级鹰账号,但是运行的时候会出现下面这种报错,不知道是哪里有问题,方便帮忙看看吗? [2024-08-29 00:25:33,695 - root - INFO - 24416 - 22052] 成功获取cookie!!! [2024-08-29 00:25:33,695 - root - INFO - 24416 - 22052] JSESSIONID=0F74202052AF1671B64FD4851093F28A; iPlanetDirectoryPro=VYNqnsOIPEIynqxUvA2mHE; Process Process-5: urllib3.exceptions.SSLError: [SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED] unsafe legacy renegotiation disabled (_ssl.c:1006)
The above exception was the direct cause of the following exception:
Traceback (most recent call last): File "D:\anaconda3\Lib\site-packages\requests\adapters.py", line 486, in send resp = conn.urlopen( ^^^^^^^^^^^^^ File "D:\anaconda3\Lib\site-packages\urllib3\connectionpool.py", line 845, in urlopen retries = retries.increment( ^^^^^^^^^^^^^^^^^^ File "D:\anaconda3\Lib\site-packages\urllib3\util\retry.py", line 515, in increment raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='elife.fudan.edu.cn', port=443): Max retries exceeded with url: /public/userbox/index.htm?userConfirm=&orderstateselect= (Caused by SSLError(SSLError(1, '[SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED] unsafe legacy renegotiation disabled (_ssl.c:1006)')))
During handling of the above exception, another exception occurred:
Traceback (most recent call last): File "D:\anaconda3\Lib\multiprocessing\process.py", line 314, in _bootstrap self.run() File "D:\anaconda3\Lib\multiprocessing\process.py", line 108, in run self._target(*self._args, self._kwargs) File "D:\Document\footscript\FudanCourtReservation\scripts\client.py", line 405, in single_job self.get_status() File "D:\Document\footscript\FudanCourtReservation\scripts\client.py", line 297, in get_status resource_resp = requests.get(status_url, headers=headers) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\anaconda3\Lib\site-packages\requests\api.py", line 73, in get return request("get", url, params=params, kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\anaconda3\Lib\site-packages\requests\api.py", line 59, in request return session.request(method=method, url=url, kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\anaconda3\Lib\site-packages\requests\sessions.py", line 589, in request resp = self.send(prep, send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\anaconda3\Lib\site-packages\requests\sessions.py", line 703, in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\anaconda3\Lib\site-packages\requests\adapters.py", line 517, in send raise SSLError(e, request=request) requests.exceptions.SSLError: HTTPSConnectionPool(host='elife.fudan.edu.cn', port=443): Max retries exceeded with url: /public/userbox/index.htm?userConfirm=&orderstateselect= (Caused by SSLError(SSLError(1, '[SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED] unsafe legacy renegotiation disabled (_ssl.c:1006)'))) Process Process-6: urllib3.exceptions.SSLError: [SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED] unsafe legacy renegotiation disabled (_ssl.c:1006)
The above exception was the direct cause of the following exception:
Traceback (most recent call last): File "D:\anaconda3\Lib\site-packages\requests\adapters.py", line 486, in send resp = conn.urlopen( ^^^^^^^^^^^^^ File "D:\anaconda3\Lib\site-packages\urllib3\connectionpool.py", line 845, in urlopen retries = retries.increment( ^^^^^^^^^^^^^^^^^^ File "D:\anaconda3\Lib\site-packages\urllib3\util\retry.py", line 515, in increment raise MaxRetryError(_pool, url, reason) from reason # type: ignore[arg-type] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='elife.fudan.edu.cn', port=443): Max retries exceeded with url: /public/userbox/index.htm?userConfirm=&orderstateselect= (Caused by SSLError(SSLError(1, '[SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED] unsafe legacy renegotiation disabled (_ssl.c:1006)')))
During handling of the above exception, another exception occurred:
Traceback (most recent call last): File "D:\anaconda3\Lib\multiprocessing\process.py", line 314, in _bootstrap self.run() File "D:\anaconda3\Lib\multiprocessing\process.py", line 108, in run self._target(*self._args, self._kwargs) File "D:\Document\footscript\FudanCourtReservation\scripts\client.py", line 405, in single_job self.get_status() File "D:\Document\footscript\FudanCourtReservation\scripts\client.py", line 297, in get_status resource_resp = requests.get(status_url, headers=headers) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\anaconda3\Lib\site-packages\requests\api.py", line 73, in get return request("get", url, params=params, kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\anaconda3\Lib\site-packages\requests\api.py", line 59, in request return session.request(method=method, url=url, kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\anaconda3\Lib\site-packages\requests\sessions.py", line 589, in request resp = self.send(prep, send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\anaconda3\Lib\site-packages\requests\sessions.py", line 703, in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "D:\anaconda3\Lib\site-packages\requests\adapters.py", line 517, in send raise SSLError(e, request=request) requests.exceptions.SSLError: HTTPSConnectionPool(host='elife.fudan.edu.cn', port=443): Max retries exceeded with url: /public/userbox/index.htm?userConfirm=&orderstateselect= (Caused by SSLError(SSLError(1, '[SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED] unsafe legacy renegotiation disabled (_ssl.c:1006)'))) 2024-08-29 00:25:43.118077 [2024-08-29 00:25:43,118 - apscheduler.scheduler - INFO - 26168 - 5308] Adding job tentatively -- it will be properly scheduled when the scheduler starts [2024-08-29 00:25:43,136 - apscheduler.scheduler - INFO - 26168 - 5308] Added job "Client.scheduled_job" to job store "default" [2024-08-29 00:25:43,136 - apscheduler.scheduler - INFO - 26168 - 5308] Scheduler started