-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathgenerator.py
107 lines (93 loc) · 3.2 KB
/
generator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
import aiohttp
import asyncio
import time
import threading
import queue
from api import Challenge
import solver
class CaptchaGenerator(object):
def __init__(self, qlimit, plimit, climit, interval, gt):
"""
A generator that will produce valid captcha.
qlimit: Maximum number of buffered solved captcha.
plimit: Maximum number of pending unsolved captcha.
climit: Maximum concurrent connection.
interval: Minimum time interval between two concurrent connection.
gt: geetest key.
"""
self.gt = gt
self.climit = climit
self.plimit = plimit
self.interval = interval
self.output = queue.Queue(qlimit)
self.lock = threading.Lock()
self._successRate = 0
self.closed = False
self.thread = threading.Thread(target=self.worker)
self.thread.start()
self.history = {}
def __iter__(self):
return self
def __next__(self):
res = self.output.get()
if res is None:
raise StopIteration()
return res
def worker(self):
self.loop = asyncio.new_event_loop()
self.loop.run_until_complete(self.executor())
self.loop.stop()
self.loop.close()
async def gen(self):
c = await Challenge(self).load()
distance = await solver.distance(c)
if distance in self.history:
answer = self.history[distance]
else:
answer = solver.motion(distance)
res = await c.validate(answer)
self.pending.release()
if res['message'] == 'success':
self.history[distance] = answer
with self.lock:
self._successRate *= 0.99
self._successRate += 0.01
res['challenge'] = c.info['challenge']
self.output.put(res)
else:
if distance in self.history:
del self.history[distance]
with self.lock:
self._successRate *= 0.99
async def executor(self):
"""
A generator that will produce valid captcha.
gt: geetest key.
qlimit: Maximum size of buffered captcha.
climit: Maximum concurrent connection.
interval: Minimum time interval between two concurrent connection.
"""
last = 0
self.pending = asyncio.Semaphore(self.plimit)
self.concurrent = asyncio.Semaphore(self.climit)
async with aiohttp.ClientSession() as session:
self.session = session
# for i in range(10):
while not self.closed:
await self.pending.acquire()
now = time.time() * 1000
if now - last < self.interval:
await asyncio.sleep((self.interval - now + last) / 1000)
last = now
asyncio.ensure_future(self.gen())
for i in range(self.climit):
await self.concurrent.acquire()
self.output.put(None)
@property
def successRate(self):
with self.lock:
return self._successRate
def close(self):
self.closed = True
if (self.output.qsize() > 0):
self.output.get()