├── .gitignore ├── README.md ├── cookiespool ├── __init__.py ├── api.py ├── config.py ├── db.py ├── generator.py ├── importer.py ├── scheduler.py └── tester.py ├── importer.py ├── login ├── __init__.py └── weibo │ ├── __init__.py │ ├── cookies.py │ └── templates │ ├── 1234.png │ ├── 1243.png │ ├── 1324.png │ ├── 1342.png │ ├── 1423.png │ ├── 1432.png │ ├── 2134.png │ ├── 2143.png │ ├── 2314.png │ ├── 2341.png │ ├── 2413.png │ ├── 2431.png │ ├── 3124.png │ ├── 3142.png │ ├── 3214.png │ ├── 3241.png │ ├── 3412.png │ ├── 3421.png │ ├── 4123.png │ ├── 4132.png │ ├── 4213.png │ ├── 4231.png │ ├── 4312.png │ └── 4321.png ├── requirements.txt └── run.py /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | *.pyc 3 | ghostdriver.log -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CookiesPool 2 | 3 | 可扩展的Cookies池,目前对接了新浪微博,[m.weibo.cn](https://m.weibo.cn),可自行扩展其他站点 4 | 5 | 6 | ## 安装 7 | 8 | ``` 9 | pip3 install -r requirements.txt 10 | ``` 11 | 12 | ## 基础配置 13 | 14 | ### 接口基本配置 15 | 16 | ```python 17 | # Redis数据库地址 18 | REDIS_HOST = 'localhost' 19 | 20 | # Redis端口 21 | REDIS_PORT = 6379 22 | 23 | # Redis密码,如无填None 24 | REDIS_PASSWORD = 'foobared' 25 | 26 | # 产生器使用的浏览器 27 | BROWSER_TYPE = 'Chrome' 28 | 29 | # 产生器类,如扩展其他站点,请在此配置 30 | GENERATOR_MAP = { 31 | 'weibo': 'WeiboCookiesGenerator' 32 | } 33 | 34 | # 测试类,如扩展其他站点,请在此配置 35 | TESTER_MAP = { 36 | 'weibo': 'WeiboValidTester' 37 | } 38 | 39 | # 检测器检测接口 40 | TEST_URL_MAP = { 41 | 'weibo': 'https://m.weibo.cn/api/container/getIndex?uid=1804544030&type=uid&page=1&containerid=1076031804544030' 42 | } 43 | 44 | # 产生器和验证器循环周期 45 | CYCLE = 120 46 | 47 | # API地址和端口 48 | API_HOST = '0.0.0.0' 49 | API_PORT = 5000 50 | 51 | ``` 52 | 53 | ### 进程开关 54 | 55 | 在config.py修改 56 | 57 | ```python 58 | # 产生器开关,模拟登录添加Cookies 59 | GENERATOR_PROCESS = True 60 | # 验证器开关,循环检测数据库中Cookies是否可用,不可用删除 61 | VALID_PROCESS = True 62 | # API接口服务 63 | API_PROCESS = True 64 | ``` 65 | 66 | 67 | ## 账号购买 68 | 69 | 账号可在淘宝购买 70 | 71 | 72 | ## 导入账号 73 | 74 | ``` 75 | python3 importer.py 76 | ``` 77 | 78 | ``` 79 | 请输入账号密码组, 输入exit退出读入 80 | 18459748505----astvar3647 81 | 14760253606----gmidy8470 82 | 14760253607----uoyuic8427 83 | 18459749258----rktfye8937 84 | 账号 18459748505 密码 astvar3647 85 | 录入成功 86 | 账号 14760253606 密码 gmidy8470 87 | 录入成功 88 | 账号 14760253607 密码 uoyuic8427 89 | 录入成功 90 | 账号 18459749258 密码 rktfye8937 91 | 录入成功 92 | exit 93 | ``` 94 | 95 | 96 | ## 运行 97 | 98 | 请先导入一部分账号之后再运行,运行命令: 99 | 100 | ``` 101 | python3 run.py 102 | ``` 103 | 104 | ## 运行效果 105 | 106 | 三个进程全部开启: 107 | 108 | 109 | ``` 110 | API接口开始运行 111 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) 112 | Cookies生成进程开始运行 113 | Cookies检测进程开始运行 114 | 正在生成Cookies 账号 14747223314 密码 asdf1129 115 | 正在测试Cookies 用户名 14747219309 116 | Cookies有效 14747219309 117 | 正在测试Cookies 用户名 14740626332 118 | Cookies有效 14740626332 119 | 正在测试Cookies 用户名 14740691419 120 | Cookies有效 14740691419 121 | 正在测试Cookies 用户名 14740618009 122 | Cookies有效 14740618009 123 | 正在测试Cookies 用户名 14747222472 124 | Cookies有效 14747222472 125 | Cookies检测完成 126 | 验证码位置 420 580 384 544 127 | 成功匹配 128 | 拖动顺序 [1, 4, 2, 3] 129 | 成功获取到Cookies {'SUHB': '08J77UIj4w5n_T', 'SCF': 'AimcUCUVvHjswSBmTswKh0g4kNj4K7_U9k57YzxbqFt4SFBhXq3Lx4YSNO9VuBV841BMHFIaH4ipnfqZnK7W6Qs.', 'SSOLoginState': '1501439488', '_T_WM': '99b7d656220aeb9207b5db97743adc02', 'M_WEIBOCN_PARAMS': 'uicode%3D20000174', 'SUB': '_2A250elZQDeRhGeBM6VAR8ifEzTuIHXVXhXoYrDV6PUJbkdBeLXTxkW17ZoYhhJ92N_RGCjmHpfv9TB8OJQ..'} 130 | 成功保存Cookies 131 | ``` 132 | -------------------------------------------------------------------------------- /cookiespool/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/cookiespool/__init__.py -------------------------------------------------------------------------------- /cookiespool/api.py: -------------------------------------------------------------------------------- 1 | import json 2 | from flask import Flask, g 3 | from cookiespool.config import * 4 | from cookiespool.db import * 5 | 6 | __all__ = ['app'] 7 | 8 | app = Flask(__name__) 9 | 10 | @app.route('/') 11 | def index(): 12 | return '

Welcome to Cookie Pool System

' 13 | 14 | 15 | def get_conn(): 16 | """ 17 | 获取 18 | :return: 19 | """ 20 | for website in GENERATOR_MAP: 21 | print(website) 22 | if not hasattr(g, website): 23 | setattr(g, website + '_cookies', eval('RedisClient' + '("cookies", "' + website + '")')) 24 | setattr(g, website + '_accounts', eval('RedisClient' + '("accounts", "' + website + '")')) 25 | return g 26 | 27 | 28 | @app.route('//random') 29 | def random(website): 30 | """ 31 | 获取随机的Cookie, 访问地址如 /weibo/random 32 | :return: 随机Cookie 33 | """ 34 | g = get_conn() 35 | cookies = getattr(g, website + '_cookies').random() 36 | return cookies 37 | 38 | 39 | @app.route('//add//') 40 | def add(website, username, password): 41 | """ 42 | 添加用户, 访问地址如 /weibo/add/user/password 43 | :param website: 站点 44 | :param username: 用户名 45 | :param password: 密码 46 | :return: 47 | """ 48 | g = get_conn() 49 | print(username, password) 50 | getattr(g, website + '_accounts').set(username, password) 51 | return json.dumps({'status': '1'}) 52 | 53 | 54 | @app.route('//count') 55 | def count(website): 56 | """ 57 | 获取Cookies总数 58 | """ 59 | g = get_conn() 60 | count = getattr(g, website + '_cookies').count() 61 | return json.dumps({'status': '1', 'count': count}) 62 | 63 | 64 | if __name__ == '__main__': 65 | app.run(host='0.0.0.0') 66 | -------------------------------------------------------------------------------- /cookiespool/config.py: -------------------------------------------------------------------------------- 1 | # Redis数据库地址 2 | REDIS_HOST = 'localhost' 3 | 4 | # Redis端口 5 | REDIS_PORT = 6379 6 | 7 | # Redis密码,如无填None 8 | REDIS_PASSWORD = 'foobared' 9 | 10 | # 产生器使用的浏览器 11 | BROWSER_TYPE = 'Chrome' 12 | 13 | # 产生器类,如扩展其他站点,请在此配置 14 | GENERATOR_MAP = { 15 | 'weibo': 'WeiboCookiesGenerator' 16 | } 17 | 18 | # 测试类,如扩展其他站点,请在此配置 19 | TESTER_MAP = { 20 | 'weibo': 'WeiboValidTester' 21 | } 22 | 23 | TEST_URL_MAP = { 24 | 'weibo': 'https://m.weibo.cn/' 25 | } 26 | 27 | # 产生器和验证器循环周期 28 | CYCLE = 120 29 | 30 | # API地址和端口 31 | API_HOST = '0.0.0.0' 32 | API_PORT = 5000 33 | 34 | # 产生器开关,模拟登录添加Cookies 35 | GENERATOR_PROCESS = False 36 | # 验证器开关,循环检测数据库中Cookies是否可用,不可用删除 37 | VALID_PROCESS = False 38 | # API接口服务 39 | API_PROCESS = True 40 | -------------------------------------------------------------------------------- /cookiespool/db.py: -------------------------------------------------------------------------------- 1 | import random 2 | import redis 3 | from cookiespool.config import * 4 | 5 | 6 | class RedisClient(object): 7 | def __init__(self, type, website, host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD): 8 | """ 9 | 初始化Redis连接 10 | :param host: 地址 11 | :param port: 端口 12 | :param password: 密码 13 | """ 14 | self.db = redis.StrictRedis(host=host, port=port, password=password, decode_responses=True) 15 | self.type = type 16 | self.website = website 17 | 18 | def name(self): 19 | """ 20 | 获取Hash的名称 21 | :return: Hash名称 22 | """ 23 | return "{type}:{website}".format(type=self.type, website=self.website) 24 | 25 | def set(self, username, value): 26 | """ 27 | 设置键值对 28 | :param username: 用户名 29 | :param value: 密码或Cookies 30 | :return: 31 | """ 32 | return self.db.hset(self.name(), username, value) 33 | 34 | def get(self, username): 35 | """ 36 | 根据键名获取键值 37 | :param username: 用户名 38 | :return: 39 | """ 40 | return self.db.hget(self.name(), username) 41 | 42 | def delete(self, username): 43 | """ 44 | 根据键名删除键值对 45 | :param username: 用户名 46 | :return: 删除结果 47 | """ 48 | return self.db.hdel(self.name(), username) 49 | 50 | def count(self): 51 | """ 52 | 获取数目 53 | :return: 数目 54 | """ 55 | return self.db.hlen(self.name()) 56 | 57 | def random(self): 58 | """ 59 | 随机得到键值,用于随机Cookies获取 60 | :return: 随机Cookies 61 | """ 62 | return random.choice(self.db.hvals(self.name())) 63 | 64 | def usernames(self): 65 | """ 66 | 获取所有账户信息 67 | :return: 所有用户名 68 | """ 69 | return self.db.hkeys(self.name()) 70 | 71 | def all(self): 72 | """ 73 | 获取所有键值对 74 | :return: 用户名和密码或Cookies的映射表 75 | """ 76 | return self.db.hgetall(self.name()) 77 | 78 | 79 | if __name__ == '__main__': 80 | conn = RedisClient('accounts', 'weibo') 81 | result = conn.set('hell2o', 'sss3s') 82 | print(result) 83 | -------------------------------------------------------------------------------- /cookiespool/generator.py: -------------------------------------------------------------------------------- 1 | import json 2 | from selenium import webdriver 3 | from selenium.webdriver import DesiredCapabilities 4 | from cookiespool.config import * 5 | from cookiespool.db import RedisClient 6 | from login.weibo.cookies import WeiboCookies 7 | 8 | 9 | class CookiesGenerator(object): 10 | def __init__(self, website='default'): 11 | """ 12 | 父类, 初始化一些对象 13 | :param website: 名称 14 | :param browser: 浏览器, 若不使用浏览器则可设置为 None 15 | """ 16 | self.website = website 17 | self.cookies_db = RedisClient('cookies', self.website) 18 | self.accounts_db = RedisClient('accounts', self.website) 19 | self.init_browser() 20 | 21 | def __del__(self): 22 | self.close() 23 | 24 | def init_browser(self): 25 | """ 26 | 通过browser参数初始化全局浏览器供模拟登录使用 27 | :return: 28 | """ 29 | if BROWSER_TYPE == 'PhantomJS': 30 | caps = DesiredCapabilities.PHANTOMJS 31 | caps[ 32 | "phantomjs.page.settings.userAgent"] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36' 33 | self.browser = webdriver.PhantomJS(desired_capabilities=caps) 34 | self.browser.set_window_size(1400, 500) 35 | elif BROWSER_TYPE == 'Chrome': 36 | self.browser = webdriver.Chrome() 37 | 38 | def new_cookies(self, username, password): 39 | """ 40 | 新生成Cookies,子类需要重写 41 | :param username: 用户名 42 | :param password: 密码 43 | :return: 44 | """ 45 | raise NotImplementedError 46 | 47 | def process_cookies(self, cookies): 48 | """ 49 | 处理Cookies 50 | :param cookies: 51 | :return: 52 | """ 53 | dict = {} 54 | for cookie in cookies: 55 | dict[cookie['name']] = cookie['value'] 56 | return dict 57 | 58 | def run(self): 59 | """ 60 | 运行, 得到所有账户, 然后顺次模拟登录 61 | :return: 62 | """ 63 | accounts_usernames = self.accounts_db.usernames() 64 | cookies_usernames = self.cookies_db.usernames() 65 | 66 | for username in accounts_usernames: 67 | if not username in cookies_usernames: 68 | password = self.accounts_db.get(username) 69 | print('正在生成Cookies', '账号', username, '密码', password) 70 | result = self.new_cookies(username, password) 71 | # 成功获取 72 | if result.get('status') == 1: 73 | cookies = self.process_cookies(result.get('content')) 74 | print('成功获取到Cookies', cookies) 75 | if self.cookies_db.set(username, json.dumps(cookies)): 76 | print('成功保存Cookies') 77 | # 密码错误,移除账号 78 | elif result.get('status') == 2: 79 | print(result.get('content')) 80 | if self.accounts_db.delete(username): 81 | print('成功删除账号') 82 | else: 83 | print(result.get('content')) 84 | else: 85 | print('所有账号都已经成功获取Cookies') 86 | 87 | def close(self): 88 | """ 89 | 关闭 90 | :return: 91 | """ 92 | try: 93 | print('Closing Browser') 94 | self.browser.close() 95 | del self.browser 96 | except TypeError: 97 | print('Browser not opened') 98 | 99 | 100 | class WeiboCookiesGenerator(CookiesGenerator): 101 | def __init__(self, website='weibo'): 102 | """ 103 | 初始化操作 104 | :param website: 站点名称 105 | :param browser: 使用的浏览器 106 | """ 107 | CookiesGenerator.__init__(self, website) 108 | self.website = website 109 | 110 | def new_cookies(self, username, password): 111 | """ 112 | 生成Cookies 113 | :param username: 用户名 114 | :param password: 密码 115 | :return: 用户名和Cookies 116 | """ 117 | return WeiboCookies(username, password, self.browser).main() 118 | 119 | 120 | if __name__ == '__main__': 121 | generator = WeiboCookiesGenerator() 122 | generator.run() 123 | -------------------------------------------------------------------------------- /cookiespool/importer.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | from cookiespool.db import RedisClient 4 | 5 | conn = RedisClient('accounts', 'weibo') 6 | 7 | def set(account, sep='----'): 8 | username, password = account.split(sep) 9 | result = conn.set(username, password) 10 | print('账号', username, '密码', password) 11 | print('录入成功' if result else '录入失败') 12 | 13 | 14 | def scan(): 15 | print('请输入账号密码组, 输入exit退出读入') 16 | while True: 17 | account = input() 18 | if account == 'exit': 19 | break 20 | set(account) 21 | 22 | 23 | if __name__ == '__main__': 24 | scan() -------------------------------------------------------------------------------- /cookiespool/scheduler.py: -------------------------------------------------------------------------------- 1 | import time 2 | from multiprocessing import Process 3 | 4 | from cookiespool.api import app 5 | from cookiespool.config import * 6 | from cookiespool.generator import * 7 | from cookiespool.tester import * 8 | 9 | 10 | class Scheduler(object): 11 | @staticmethod 12 | def valid_cookie(cycle=CYCLE): 13 | while True: 14 | print('Cookies检测进程开始运行') 15 | try: 16 | for website, cls in TESTER_MAP.items(): 17 | tester = eval(cls + '(website="' + website + '")') 18 | tester.run() 19 | print('Cookies检测完成') 20 | del tester 21 | time.sleep(cycle) 22 | except Exception as e: 23 | print(e.args) 24 | 25 | @staticmethod 26 | def generate_cookie(cycle=CYCLE): 27 | while True: 28 | print('Cookies生成进程开始运行') 29 | try: 30 | for website, cls in GENERATOR_MAP.items(): 31 | generator = eval(cls + '(website="' + website + '")') 32 | generator.run() 33 | print('Cookies生成完成') 34 | generator.close() 35 | time.sleep(cycle) 36 | except Exception as e: 37 | print(e.args) 38 | 39 | @staticmethod 40 | def api(): 41 | print('API接口开始运行') 42 | app.run(host=API_HOST, port=API_PORT) 43 | 44 | def run(self): 45 | if API_PROCESS: 46 | api_process = Process(target=Scheduler.api) 47 | api_process.start() 48 | 49 | if GENERATOR_PROCESS: 50 | generate_process = Process(target=Scheduler.generate_cookie) 51 | generate_process.start() 52 | 53 | if VALID_PROCESS: 54 | valid_process = Process(target=Scheduler.valid_cookie) 55 | valid_process.start() 56 | -------------------------------------------------------------------------------- /cookiespool/tester.py: -------------------------------------------------------------------------------- 1 | import json 2 | import requests 3 | from requests.exceptions import ConnectionError 4 | from cookiespool.db import * 5 | 6 | 7 | class ValidTester(object): 8 | def __init__(self, website='default'): 9 | self.website = website 10 | self.cookies_db = RedisClient('cookies', self.website) 11 | self.accounts_db = RedisClient('accounts', self.website) 12 | 13 | def test(self, username, cookies): 14 | raise NotImplementedError 15 | 16 | def run(self): 17 | cookies_groups = self.cookies_db.all() 18 | for username, cookies in cookies_groups.items(): 19 | self.test(username, cookies) 20 | 21 | 22 | class WeiboValidTester(ValidTester): 23 | def __init__(self, website='weibo'): 24 | ValidTester.__init__(self, website) 25 | 26 | def test(self, username, cookies): 27 | print('正在测试Cookies', '用户名', username) 28 | try: 29 | cookies = json.loads(cookies) 30 | except TypeError: 31 | print('Cookies不合法', username) 32 | self.cookies_db.delete(username) 33 | print('删除Cookies', username) 34 | return 35 | try: 36 | test_url = TEST_URL_MAP[self.website] 37 | response = requests.get(test_url, cookies=cookies, timeout=5, allow_redirects=False) 38 | if response.status_code == 200: 39 | print('Cookies有效', username) 40 | else: 41 | print(response.status_code, response.headers) 42 | print('Cookies失效', username) 43 | self.cookies_db.delete(username) 44 | print('删除Cookies', username) 45 | except ConnectionError as e: 46 | print('发生异常', e.args) 47 | 48 | if __name__ == '__main__': 49 | WeiboValidTester().run() -------------------------------------------------------------------------------- /importer.py: -------------------------------------------------------------------------------- 1 | from cookiespool.importer import scan 2 | 3 | if __name__ == '__main__': 4 | scan() -------------------------------------------------------------------------------- /login/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/__init__.py -------------------------------------------------------------------------------- /login/weibo/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/__init__.py -------------------------------------------------------------------------------- /login/weibo/cookies.py: -------------------------------------------------------------------------------- 1 | import time 2 | from io import BytesIO 3 | from PIL import Image 4 | from selenium.common.exceptions import TimeoutException 5 | from selenium.webdriver import ActionChains 6 | from selenium.webdriver.common.by import By 7 | from selenium.webdriver.support.ui import WebDriverWait 8 | from selenium.webdriver.support import expected_conditions as EC 9 | from os import listdir 10 | from os.path import abspath, dirname 11 | 12 | TEMPLATES_FOLDER = dirname(abspath(__file__)) + '/templates/' 13 | 14 | 15 | class WeiboCookies(): 16 | def __init__(self, username, password, browser): 17 | self.url = 'https://passport.weibo.cn/signin/login?entry=mweibo&r=https://m.weibo.cn/' 18 | self.browser = browser 19 | self.wait = WebDriverWait(self.browser, 20) 20 | self.username = username 21 | self.password = password 22 | 23 | def open(self): 24 | """ 25 | 打开网页输入用户名密码并点击 26 | :return: None 27 | """ 28 | self.browser.delete_all_cookies() 29 | self.browser.get(self.url) 30 | username = self.wait.until(EC.presence_of_element_located((By.ID, 'loginName'))) 31 | password = self.wait.until(EC.presence_of_element_located((By.ID, 'loginPassword'))) 32 | submit = self.wait.until(EC.element_to_be_clickable((By.ID, 'loginAction'))) 33 | username.send_keys(self.username) 34 | password.send_keys(self.password) 35 | time.sleep(1) 36 | submit.click() 37 | 38 | def password_error(self): 39 | """ 40 | 判断是否密码错误 41 | :return: 42 | """ 43 | try: 44 | return WebDriverWait(self.browser, 5).until( 45 | EC.text_to_be_present_in_element((By.ID, 'errorMsg'), '用户名或密码错误')) 46 | except TimeoutException: 47 | return False 48 | 49 | def login_successfully(self): 50 | """ 51 | 判断是否登录成功 52 | :return: 53 | """ 54 | try: 55 | return bool( 56 | WebDriverWait(self.browser, 5).until(EC.presence_of_element_located((By.CLASS_NAME, 'lite-iconf-profile')))) 57 | except TimeoutException: 58 | return False 59 | 60 | def get_position(self): 61 | """ 62 | 获取验证码位置 63 | :return: 验证码位置元组 64 | """ 65 | try: 66 | img = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'patt-shadow'))) 67 | except TimeoutException: 68 | print('未出现验证码') 69 | self.open() 70 | time.sleep(2) 71 | location = img.location 72 | size = img.size 73 | top, bottom, left, right = location['y'], location['y'] + size['height'], location['x'], location['x'] + size[ 74 | 'width'] 75 | return (top, bottom, left, right) 76 | 77 | def get_screenshot(self): 78 | """ 79 | 获取网页截图 80 | :return: 截图对象 81 | """ 82 | screenshot = self.browser.get_screenshot_as_png() 83 | screenshot = Image.open(BytesIO(screenshot)) 84 | return screenshot 85 | 86 | def get_image(self, name='captcha.png'): 87 | """ 88 | 获取验证码图片 89 | :return: 图片对象 90 | """ 91 | top, bottom, left, right = self.get_position() 92 | print('验证码位置', top, bottom, left, right) 93 | screenshot = self.get_screenshot() 94 | captcha = screenshot.crop((left, top, right, bottom)) 95 | return captcha 96 | 97 | def is_pixel_equal(self, image1, image2, x, y): 98 | """ 99 | 判断两个像素是否相同 100 | :param image1: 图片1 101 | :param image2: 图片2 102 | :param x: 位置x 103 | :param y: 位置y 104 | :return: 像素是否相同 105 | """ 106 | # 取两个图片的像素点 107 | pixel1 = image1.load()[x, y] 108 | pixel2 = image2.load()[x, y] 109 | threshold = 20 110 | if abs(pixel1[0] - pixel2[0]) < threshold and abs(pixel1[1] - pixel2[1]) < threshold and abs( 111 | pixel1[2] - pixel2[2]) < threshold: 112 | return True 113 | else: 114 | return False 115 | 116 | def same_image(self, image, template): 117 | """ 118 | 识别相似验证码 119 | :param image: 待识别验证码 120 | :param template: 模板 121 | :return: 122 | """ 123 | # 相似度阈值 124 | threshold = 0.99 125 | count = 0 126 | for x in range(image.width): 127 | for y in range(image.height): 128 | # 判断像素是否相同 129 | if self.is_pixel_equal(image, template, x, y): 130 | count += 1 131 | result = float(count) / (image.width * image.height) 132 | if result > threshold: 133 | print('成功匹配') 134 | return True 135 | return False 136 | 137 | def detect_image(self, image): 138 | """ 139 | 匹配图片 140 | :param image: 图片 141 | :return: 拖动顺序 142 | """ 143 | for template_name in listdir(TEMPLATES_FOLDER): 144 | print('正在匹配', template_name) 145 | template = Image.open(TEMPLATES_FOLDER + template_name) 146 | if self.same_image(image, template): 147 | # 返回顺序 148 | numbers = [int(number) for number in list(template_name.split('.')[0])] 149 | print('拖动顺序', numbers) 150 | return numbers 151 | 152 | def move(self, numbers): 153 | """ 154 | 根据顺序拖动 155 | :param numbers: 156 | :return: 157 | """ 158 | # 获得四个按点 159 | try: 160 | circles = self.browser.find_elements_by_css_selector('.patt-wrap .patt-circ') 161 | dx = dy = 0 162 | for index in range(4): 163 | circle = circles[numbers[index] - 1] 164 | # 如果是第一次循环 165 | if index == 0: 166 | # 点击第一个按点 167 | ActionChains(self.browser) \ 168 | .move_to_element_with_offset(circle, circle.size['width'] / 2, circle.size['height'] / 2) \ 169 | .click_and_hold().perform() 170 | else: 171 | # 小幅移动次数 172 | times = 30 173 | # 拖动 174 | for i in range(times): 175 | ActionChains(self.browser).move_by_offset(dx / times, dy / times).perform() 176 | time.sleep(1 / times) 177 | # 如果是最后一次循环 178 | if index == 3: 179 | # 松开鼠标 180 | ActionChains(self.browser).release().perform() 181 | else: 182 | # 计算下一次偏移 183 | dx = circles[numbers[index + 1] - 1].location['x'] - circle.location['x'] 184 | dy = circles[numbers[index + 1] - 1].location['y'] - circle.location['y'] 185 | except: 186 | return False 187 | 188 | def get_cookies(self): 189 | """ 190 | 获取Cookies 191 | :return: 192 | """ 193 | return self.browser.get_cookies() 194 | 195 | def main(self): 196 | """ 197 | 破解入口 198 | :return: 199 | """ 200 | self.open() 201 | if self.password_error(): 202 | return { 203 | 'status': 2, 204 | 'content': '用户名或密码错误' 205 | } 206 | # 如果不需要验证码直接登录成功 207 | if self.login_successfully(): 208 | cookies = self.get_cookies() 209 | return { 210 | 'status': 1, 211 | 'content': cookies 212 | } 213 | # 获取验证码图片 214 | image = self.get_image('captcha.png') 215 | numbers = self.detect_image(image) 216 | self.move(numbers) 217 | if self.login_successfully(): 218 | cookies = self.get_cookies() 219 | return { 220 | 'status': 1, 221 | 'content': cookies 222 | } 223 | else: 224 | return { 225 | 'status': 3, 226 | 'content': '登录失败' 227 | } 228 | 229 | 230 | if __name__ == '__main__': 231 | result = WeiboCookies('14773427930', 'x6pybpakq1').main() 232 | print(result) 233 | -------------------------------------------------------------------------------- /login/weibo/templates/1234.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/1234.png -------------------------------------------------------------------------------- /login/weibo/templates/1243.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/1243.png -------------------------------------------------------------------------------- /login/weibo/templates/1324.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/1324.png -------------------------------------------------------------------------------- /login/weibo/templates/1342.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/1342.png -------------------------------------------------------------------------------- /login/weibo/templates/1423.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/1423.png -------------------------------------------------------------------------------- /login/weibo/templates/1432.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/1432.png -------------------------------------------------------------------------------- /login/weibo/templates/2134.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/2134.png -------------------------------------------------------------------------------- /login/weibo/templates/2143.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/2143.png -------------------------------------------------------------------------------- /login/weibo/templates/2314.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/2314.png -------------------------------------------------------------------------------- /login/weibo/templates/2341.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/2341.png -------------------------------------------------------------------------------- /login/weibo/templates/2413.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/2413.png -------------------------------------------------------------------------------- /login/weibo/templates/2431.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/2431.png -------------------------------------------------------------------------------- /login/weibo/templates/3124.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/3124.png -------------------------------------------------------------------------------- /login/weibo/templates/3142.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/3142.png -------------------------------------------------------------------------------- /login/weibo/templates/3214.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/3214.png -------------------------------------------------------------------------------- /login/weibo/templates/3241.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/3241.png -------------------------------------------------------------------------------- /login/weibo/templates/3412.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/3412.png -------------------------------------------------------------------------------- /login/weibo/templates/3421.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/3421.png -------------------------------------------------------------------------------- /login/weibo/templates/4123.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/4123.png -------------------------------------------------------------------------------- /login/weibo/templates/4132.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/4132.png -------------------------------------------------------------------------------- /login/weibo/templates/4213.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/4213.png -------------------------------------------------------------------------------- /login/weibo/templates/4231.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/4231.png -------------------------------------------------------------------------------- /login/weibo/templates/4312.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/4312.png -------------------------------------------------------------------------------- /login/weibo/templates/4321.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Python3WebSpider/CookiesPool/e724f8d19b17970e79f1a8b942ae943b6fcf12c2/login/weibo/templates/4321.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | requests>=2.13.0 2 | selenium>=3.4.0 3 | redis>=2.10.5 4 | Flask>=0.12.1 -------------------------------------------------------------------------------- /run.py: -------------------------------------------------------------------------------- 1 | from cookiespool.scheduler import Scheduler 2 | 3 | def main(): 4 | s = Scheduler() 5 | s.run() 6 | 7 | if __name__ == '__main__': 8 | main() --------------------------------------------------------------------------------