1 from selenium import webdriver
2 from time import sleep
3 from bs4 import BeautifulSoup
4 import re
5 from pyperclip import copy, paste
6 import win32api
7 import win32con
8 from jpype import *
9 import urllib.parse
10 import http.client
11 import requests
12 from urllib import request
13
14
15 class Tools:
16 @staticmethod
17 def ctrl_c():
18 win32api.keybd_event(17, 0, 0, 0)
19 win32api.keybd_event(67, 0, 0, 0)
20 win32api.keybd_event(67, 0, win32con.KEYEVENTF_KEYUP, 0)
21 win32api.keybd_event(17, 0, win32con.KEYEVENTF_KEYUP, 0)
22
23 @staticmethod
24 def ctrl_v():
25 win32api.keybd_event(17, 0, 0, 0)
26 win32api.keybd_event(86, 0, 0, 0)
27 win32api.keybd_event(86, 0, win32con.KEYEVENTF_KEYUP, 0)
28 win32api.keybd_event(17, 0, win32con.KEYEVENTF_KEYUP, 0)
29
30 @staticmethod
31 def click():
32 win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0)
33 win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0)
34
35 # 处理从微信获取的答案
36 @staticmethod
37 def handel_answer(question):
38 answers = re.findall(pattern=re.compile('➖➖➖➖➖➖➖➖➖➖([\s\S]*)➖➖➖➖➖➖➖➖➖➖'), string=paste())
39 question = question.replace('(', '').replace(')', '').replace('。', '')
40 answers = answers[0].replace('\ue020', '').replace('\n', ''). \
41 replace('(', '').replace('。', '').replace(')', '').split(question)
42 num = 0
43 for i in range(answers.__len__()):
44 if answers[num] == '' or answers[num].encode('UTF-8').isalpha():
45 answers.remove(answers[num])
46 else:
47 answers[num].replace(' ', '')
48 num += 1
49 return answers
50
51 # 发送信息,通知来确认答题
52 @staticmethod
53 def send_sms():
54 params = urllib.parse.urlencode(
55 {'account': "", 'password': "",
56 'content': '您的验证码是:911。请不要把验证码泄露给其他人。',
57 'mobile': "", 'format': 'json'})
58 headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"}
59 conn = http.client.HTTPConnection("106.ihuyi.com", port=80, timeout=30)
60 conn.request("POST", "/webservice/sms.php?method=Submit", params, headers)
61 response = conn.getresponse()
62 response_str = response.read()
63 conn.close()
64 return response_str
65
66 # 获取视频播放时弹出的答案和弹出时间
67 @staticmethod
68 def get_answer_and_wait_time(source_code, headers, type):
69 knowledgeid = re.findall(pattern=re.compile('knowledgeid=(.*)&num'), string=source_code)[0]
70 if type == 1:
71 return knowledgeid
72 courseid = re.findall(pattern=re.compile('courseId=(.*)&classId'), string=source_code)[0]
73 mdiea_id = requests.get('https://mooc1-2.chaoxing.''com/knowledge/'
74 'cards?''courseid=' + str(courseid) + '&knowledgeid=' +
75 str(knowledgeid) + '', headers=headers).content.decode('utf8')
76 midea_id = re.findall(pattern=re.compile('mid":"(.*)","_jobid'),
77 string=mdiea_id)
78 answer = re.findall(
79 pattern=re.compile('"isRight":true,"name":"(.*)","description".*?"startTime":(.*),"endTime":0'),
80 string=requests.get(
81 'https://mooc1-2.chaoxing.com/richvideo/initdatawithviewer?&start=undefined&mid=' +
82 midea_id[0] + '',
83 headers=headers).text)
84 return answer
85
86 # 获取章节测验的网页source_code
87 @staticmethod
88 def get_questions_page_source(url, headers, knowledgeid, type, browser):
89 ids = re.findall(pattern=re.compile('courseId=(.*)&clazzid=(.*)&enc'), string=url)[0]
90 url = 'https://mooc1-2.chaoxing.com/knowledge/cards?clazzid=' + ids[1] + '&courseid=' + ids[
91 0] + '&knowledgeid=' + str(knowledgeid) + '&num=' + str(type) + ''
92 temp = requests.get(url=url, headers=headers).text
93 ids_2 = re.findall(pattern=re.compile('jobid":"(.*?)"[\s\S]*"workid":"(.*?)"[\s\S]*enc":"(.*?)"'), string=temp)
94 ids_2 = ids_2[0]
95 url_timu = 'https://mooc1-2.chaoxing.com/api/work?api=1&workId=' + ids_2[1] + '&jobid=' + ids_2[
96 0] + '&needRedirect=true&knowledgeid=' + knowledgeid + '&courseid=' + ids[0] + '&ut=s&clazzId=' + str(
97 ids[1]) + '&enc=' + str(ids_2[2])
98 browser.get(url_timu)
99 req = request.Request(url=url_timu, headers=headers)
100 return request.urlopen(req).read().decode('utf8')
101
102 # 处理获取到的问题选项
103 @staticmethod
104 def handle_options(options):
105 options = options.replace('\r', '').replace('\t', '').replace(' ', '').replace('\xa0', '')
106 options = options.split('\n')
107 num = 0
108 for i in range(options.__len__()):
109 if options[num] == '' or options[num].encode('UTF-8').isalpha():
110 options.remove(options[num])
111 else:
112 num += 1
113 return options
114
115 def get_answer_from_weichat(self, path, src, question):
116 copy(question)
117 src.click(path + "Input_box.png")
118 self.ctrl_v()
119 src.click(path + "Send.png")
120 sleep(2)
121 src.doubleClick(path + "Answer.png")
122 self.ctrl_c()
123 sleep(2)
124
125
126 class AutoErya:
127 def __init__(self):
128 self.current_url = ''
129 self.question_dict = {'A': '1',
130 'B': '2',
131 'C': '3',
132 'D': '4',
133 '是': '1',
134 '否': '2'}
135 self.tool = Tools()
136 startJVM(get_default_jvm_path(), '-ea', r'-Djava.class.path=C:\Program Files (x86)\Sikuli X\sikuli-script.jar')
137 screen = JClass('org.sikuli.script.Screen')
138 self.src = screen()
139 # sikuli图片地址
140 self.path = "C:\\Users\INnoVation\\test.sikuli\\"
141 self.headers = {
142 'User-Agent': 'User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) '
143 'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 '
144 'Safari/537.36',
145 'Cookie': ''
146 }
147
148 # 处理答题
149 def auto_answer(self, browser, knowledgeid, type):
150 sleep(2)
151 questions_source = self.tool.get_questions_page_source(browser.current_url, self.headers, knowledgeid, type,
152 browser)
153 page_source = BeautifulSoup(questions_source, 'lxml')
154 questions = page_source.find_all('div', class_='Zy_TItle clearfix')
155 options = page_source.find_all('ul', class_='Zy_ulTop')
156 First = 1
157 num = 0
158 base_xpath = '//*[@id="ZyBottom"]/div'
159 # 对每一道问题进行处理
160 for question in questions:
161 question = question.text
162 question = question.replace('\n', '')
163 question_type = 1 if re.findall(re.compile('单选题(.*)'), string=question).__len__() > 0 else 2
164 question = question[6:]
165 if question_type == 1:
166 options_ = self.tool.handle_options(options[num].text)
167 num += 1
168 if First > 0:
169 First -= 1
170 else:
171 base_xpath += '/div[3]'
172 choice_xpath = base_xpath + '/div[2]/ul' if question_type == 1 else base_xpath + '/div[2]/div/ul'
173 self.tool.get_answer_from_weichat(src=self.src, question=question, path=self.path)
174 answers = self.tool.handel_answer(question)
175 if question_type == 1:
176 for answer in answers:
177 if answer.encode('UTF-8').isalpha():
178 browser.find_element_by_xpath(
179 choice_xpath + '/li[' + self.question_dict[str(answer)]
180 + ']/label/input').click()
181 break
182 else:
183 i = 1
184 for option_ in options_:
185 if option_ == answer:
186 browser.find_element_by_xpath(
187 choice_xpath + '/li[' + str(i)
188 + ']/label/input').click()
189 i += 1
190 break
191 else:
192 for answer in answers:
193 if answer == '是':
194 browser.find_element_by_xpath(
195 choice_xpath + '/li[1]/label/input').click()
196 else:
197 browser.find_element_by_xpath(
198 choice_xpath + '/li[2]/label/input').click()
199 self.tool.send_sms()
200 input('请检查答案正确性,确认后提交答案然后请输入Y解除停滞状态')
201 browser.get(self.current_url)
202 sleep(5)
203
204 # 处理视频播放和中途弹出问题
205 def video_play(self, browser, knowledgeid):
206 sleep(3)
207 type = 2
208 # 有学习目标时type为3,反之为2(记录章节测验所在xpath)
209 if browser.find_element_by_xpath('//*[@id="dct2"]').text != '2 章节测验':
210 type = 3
211 browser.find_element_by_xpath('//*[@id="dct2"]').click()
212 if self.src.exists(self.path + 'Finish.png'):
213 browser.find_element_by_xpath('//*[@id="dct' + str(type) + '"]').click()
214 self.auto_answer(browser, knowledgeid, type - 1)
215 sleep(5)
216 self.src.click(self.path + 'Play_video.png')
217 answer = self.tool.get_answer_and_wait_time(browser.execute_script("return document.documentElement.outerHTML"),
218 self.headers, 0)[0]
219 print('开始睡觉,' + answer[1] + 'S后,答题,答案是' + str(answer[0][0]) + '')
220 sleep(int(answer[1]) + 30)
221 self.src.click(self.path + str(answer[0][0] + '.png'))
222 self.src.click(self.path + 'Confirm_Video.png')
223 sleep(2)
224 self.tool.click()
225 # 等待视频已完成图标出现
226 self.src.wait(self.path + 'Finish.png', 6000)
227 browser.find_element_by_xpath('//*[@id="dct' + str(type) + '"]').click()
228 self.auto_answer(browser, knowledgeid, type - 1)
229
230 # 处理视频播放
231 def video_index(self, browser):
232 sleep(3)
233 source_code = BeautifulSoup(browser.execute_script("return document.documentElement.outerHTML"), 'lxml')
234 items = source_code.find_all('div', class_="ncells")
235 i = 0
236 wait_play = []
237 for item in items:
238 item = str(item)
239 if i == 0:
240 if re.findall(pattern=re.compile('<span class=(.*?)orange01'), string=item) is not None:
241 i = 1
242 continue
243 if i == 1:
244 id = re.findall(pattern=re.compile('<h4.*id="(.*)" style'), string=item)
245 wait_play.append(id[0])
246 if i == 1:
247 for item in wait_play:
248 browser.find_element_by_xpath('//*[@id="' + item + '"]').click()
249 self.video_play(browser, knowledgeid=item[3:])
250
251 def index(self, browser):
252 urls = [
253 'https://mooc1-2.chaoxing.com/mycourse/studentstudy?chapterId=90513632&'
254 'courseId=90513518&clazzid=1425627&enc=f5829a7d36554fc3ae3abfaf3a633f8c',
255 'https://mooc1-2.chaoxing.com/mycourse/studentstudy?chapterId=91418036'
256 '&courseId=91417988&clazzid=1425714&enc=2dc20386d2c8bff4efc353931e841bc6',
257 'https://mooc1-2.chaoxing.com/mycourse/studentstudy?chapterId=86886734&'
258 'courseId=96873026&clazzid=1425718&enc=aeb68c76727e9b63267f5a0b1176c70f']
259 for url in urls:
260 browser.get(url)
261 self.current_url = url
262 self.video_index(browser)
263
264 # 网站登陆
265 def log_in(self):
266 browser = webdriver.Chrome()
267 browser.get('http://i.mooc.chaoxing.com/space/index')
268 browser.find_element_by_xpath('//*[@id="selectSchoolA"]').click()
269 sleep(1)
270 browser.find_element_by_xpath('//*[@id="26"]').click()
271 sleep(1)
272 browser.find_element_by_xpath('//*[@id="1639"]').click()
273 sleep(1)
274 browser.find_element_by_xpath('//*[@id="unameId"]').send_keys('')
275 browser.find_element_by_xpath('//*[@id="passwordId"]').send_keys('')
276 browser.find_element_by_xpath('//*[@id="numcode"]').click()
277 login_url = browser.current_url
278 while browser.current_url == login_url:
279 print("请输入验证码,然后点击登录。")
280 sleep(5)
281 print('登陆成功,正在跳转至播放页面,请稍等~~~')
282 self.index(browser)
283
284
285 if __name__ == '__main__':
286 erya = AutoErya()
287 erya.log_in()