schedule.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import time
  2. from multiprocessing import Process
  3. import asyncio
  4. import aiohttp
  5. from aiohttp.errors import ProxyConnectionError
  6. from proxypool.db import RedisClient
  7. from proxypool.error import ResourceDepletionError
  8. from proxypool.getter import FreeProxyGetter
  9. from proxypool.setting import *
  10. from asyncio import TimeoutError
  11. class ValidityTester(object):
  12. test_api = TEST_API
  13. def __init__(self):
  14. self._raw_proxies = None
  15. self._usable_proxies = []
  16. def set_raw_proxies(self, proxies):
  17. self._raw_proxies = proxies
  18. self._conn = RedisClient()
  19. async def test_single_proxy(self, proxy):
  20. """
  21. text one proxy, if valid, put them to usable_proxies.
  22. """
  23. async with aiohttp.ClientSession() as session:
  24. try:
  25. if isinstance(proxy, bytes):
  26. proxy = proxy.decode('utf-8')
  27. real_proxy = 'http://' + proxy
  28. print('Testing', proxy)
  29. async with session.get(self.test_api, proxy=real_proxy, timeout=15) as response:
  30. if response.status == 200:
  31. self._conn.put(proxy)
  32. print('Valid proxy', proxy)
  33. except (ProxyConnectionError, TimeoutError, ValueError):
  34. print('Invalid proxy', proxy)
  35. def test(self):
  36. """
  37. aio test all proxies.
  38. """
  39. print('ValidityTester is working')
  40. try:
  41. loop = asyncio.get_event_loop()
  42. tasks = [self.test_single_proxy(proxy) for proxy in self._raw_proxies]
  43. loop.run_until_complete(asyncio.wait(tasks))
  44. except ValueError:
  45. print('Async Error')
  46. class PoolAdder(object):
  47. """
  48. add proxy to pool
  49. """
  50. def __init__(self, threshold):
  51. self._threshold = threshold
  52. self._conn = RedisClient()
  53. self._tester = ValidityTester()
  54. self._crawler = FreeProxyGetter()
  55. def is_over_threshold(self):
  56. """
  57. judge if count is overflow.
  58. """
  59. if self._conn.queue_len >= self._threshold:
  60. return True
  61. else:
  62. return False
  63. def add_to_queue(self):
  64. print('PoolAdder is working')
  65. proxy_count = 0
  66. while not self.is_over_threshold():
  67. for callback_label in range(self._crawler.__CrawlFuncCount__):
  68. callback = self._crawler.__CrawlFunc__[callback_label]
  69. raw_proxies = self._crawler.get_raw_proxies(callback)
  70. # test crawled proxies
  71. self._tester.set_raw_proxies(raw_proxies)
  72. self._tester.test()
  73. proxy_count += len(raw_proxies)
  74. if self.is_over_threshold():
  75. print('IP is enough, waiting to be used')
  76. break
  77. if proxy_count == 0:
  78. raise ResourceDepletionError
  79. class Schedule(object):
  80. @staticmethod
  81. def valid_proxy(cycle=VALID_CHECK_CYCLE):
  82. """
  83. Get half of proxies which in redis
  84. """
  85. conn = RedisClient()
  86. tester = ValidityTester()
  87. while True:
  88. print('Refreshing ip')
  89. count = int(0.5 * conn.queue_len)
  90. if count == 0:
  91. print('Waiting for adding')
  92. time.sleep(cycle)
  93. continue
  94. raw_proxies = conn.get(count)
  95. tester.set_raw_proxies(raw_proxies)
  96. tester.test()
  97. time.sleep(cycle)
  98. @staticmethod
  99. def check_pool(lower_threshold=POOL_LOWER_THRESHOLD,
  100. upper_threshold=POOL_UPPER_THRESHOLD,
  101. cycle=POOL_LEN_CHECK_CYCLE):
  102. """
  103. If the number of proxies less than lower_threshold, add proxy
  104. """
  105. conn = RedisClient()
  106. adder = PoolAdder(upper_threshold)
  107. while True:
  108. if conn.queue_len < lower_threshold:
  109. adder.add_to_queue()
  110. time.sleep(cycle)
  111. def run(self):
  112. print('Ip processing running')
  113. valid_process = Process(target=Schedule.valid_proxy)
  114. check_process = Process(target=Schedule.check_pool)
  115. valid_process.start()
  116. check_process.start()