Germey
8 years ago
commit
6396b1f8d0
14 changed files with 847 additions and 0 deletions
@ -0,0 +1,59 @@ |
|||||||
|
from flask import Flask, g |
||||||
|
from cookiespool.config import * |
||||||
|
from cookiespool.db import CookiesRedisClient, AccountRedisClient |
||||||
|
|
||||||
|
__all__ = ['app'] |
||||||
|
|
||||||
|
app = Flask(__name__) |
||||||
|
|
||||||
|
|
||||||
|
@app.route('/') |
||||||
|
def index(): |
||||||
|
return '<h2>Welcome to Cookie Pool System</h2>' |
||||||
|
|
||||||
|
|
||||||
|
def get_conn(): |
||||||
|
""" |
||||||
|
获取 |
||||||
|
:return: |
||||||
|
""" |
||||||
|
for name in GENERATOR_MAP: |
||||||
|
print(name) |
||||||
|
if not hasattr(g, name): |
||||||
|
setattr(g, name + '_cookies', eval('CookiesRedisClient' + '(name="' + name + '")')) |
||||||
|
setattr(g, name + '_account', eval('AccountRedisClient' + '(name="' + name + '")')) |
||||||
|
return g |
||||||
|
|
||||||
|
|
||||||
|
@app.route('/<name>/random') |
||||||
|
def random(name): |
||||||
|
""" |
||||||
|
获取随机的Cookie, 访问地址如 /weibo/random |
||||||
|
:return: 随机Cookie |
||||||
|
""" |
||||||
|
g = get_conn() |
||||||
|
cookies = getattr(g, name + '_cookies').random() |
||||||
|
return cookies |
||||||
|
|
||||||
|
@app.route('/<name>/add/<username>/<password>') |
||||||
|
def add(name, username, password): |
||||||
|
""" |
||||||
|
添加用户, 访问地址如 /weibo/add/user/password |
||||||
|
""" |
||||||
|
g = get_conn() |
||||||
|
result = getattr(g, name + '_account').set(username, password) |
||||||
|
return result |
||||||
|
|
||||||
|
|
||||||
|
@app.route('/<name>/count') |
||||||
|
def count(name): |
||||||
|
""" |
||||||
|
获取Cookies总数 |
||||||
|
""" |
||||||
|
g = get_conn() |
||||||
|
count = getattr(g, name + '_cookies').count() |
||||||
|
return str(int) if isinstance(count, int) else count |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
app.run(host='0.0.0.0') |
@ -0,0 +1,52 @@ |
|||||||
|
# Redis数据库地址 |
||||||
|
REDIS_HOST = 'localhost' |
||||||
|
|
||||||
|
REDIS_PORT = 6379 |
||||||
|
|
||||||
|
REDIS_PASSWORD = 'foobared' |
||||||
|
|
||||||
|
REDIS_DOMAIN = '*' |
||||||
|
|
||||||
|
REDIS_NAME = '*' |
||||||
|
|
||||||
|
# 云打码相关配置到yundama.com申请注册 |
||||||
|
YUNDAMA_USERNAME = 'Germey' |
||||||
|
|
||||||
|
YUNDAMA_PASSWORD = '940629cqc' |
||||||
|
|
||||||
|
YUNDAMA_APP_ID = '3372' |
||||||
|
|
||||||
|
YUNDAMA_APP_KEY = '1b586a30bfda5c7fa71c881075ba49d0' |
||||||
|
|
||||||
|
YUNDAMA_API_URL = 'http://api.yundama.com/api.php' |
||||||
|
|
||||||
|
YUNDAMA_MAX_RETRY = 20 |
||||||
|
|
||||||
|
# 产生器默认使用的浏览器 |
||||||
|
DEFAULT_BROWSER = 'PhantomJS' |
||||||
|
|
||||||
|
# 产生器类 |
||||||
|
GENERATOR_MAP = { |
||||||
|
'weibo': 'WeiboCookiesGenerator' |
||||||
|
} |
||||||
|
|
||||||
|
# 测试类 |
||||||
|
TESTER_MAP = { |
||||||
|
'weibo': 'WeiboValidTester' |
||||||
|
} |
||||||
|
|
||||||
|
# 产生器和验证器循环周期 |
||||||
|
CYCLE = 120 |
||||||
|
|
||||||
|
# API地址和端口 |
||||||
|
API_HOST = '127.0.0.1' |
||||||
|
|
||||||
|
API_PORT = 5000 |
||||||
|
|
||||||
|
# 进程开关 |
||||||
|
# 产生器 |
||||||
|
GENERATOR_PROCESS = True |
||||||
|
# 验证器 |
||||||
|
VALID_PROCESS = False |
||||||
|
# API |
||||||
|
API_PROCESS = True |
@ -0,0 +1,210 @@ |
|||||||
|
import random |
||||||
|
import redis |
||||||
|
from cookiespool.config import * |
||||||
|
from cookiespool.error import * |
||||||
|
|
||||||
|
|
||||||
|
class RedisClient(object): |
||||||
|
def __init__(self, host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD): |
||||||
|
""" |
||||||
|
初始化Redis连接 |
||||||
|
:param host: 地址 |
||||||
|
:param port: 端口 |
||||||
|
:param password: 密码 |
||||||
|
""" |
||||||
|
if password: |
||||||
|
self._db = redis.Redis(host=host, port=port, password=password) |
||||||
|
else: |
||||||
|
self._db = redis.Redis(host=host, port=port) |
||||||
|
self.domain = REDIS_DOMAIN |
||||||
|
self.name = REDIS_NAME |
||||||
|
|
||||||
|
def _key(self, key): |
||||||
|
""" |
||||||
|
得到格式化的key |
||||||
|
:param key: 最后一个参数key |
||||||
|
:return: |
||||||
|
""" |
||||||
|
return "{domain}:{name}:{key}".format(domain=self.domain, name=self.name, key=key) |
||||||
|
|
||||||
|
def set(self, key, value): |
||||||
|
""" |
||||||
|
设置键值对 |
||||||
|
:param key: |
||||||
|
:param value: |
||||||
|
:return: |
||||||
|
""" |
||||||
|
raise NotImplementedError |
||||||
|
|
||||||
|
def get(self, key): |
||||||
|
""" |
||||||
|
根据键名获取键值 |
||||||
|
:param key: |
||||||
|
:return: |
||||||
|
""" |
||||||
|
raise NotImplementedError |
||||||
|
|
||||||
|
def delete(self, key): |
||||||
|
""" |
||||||
|
根据键名删除键值对 |
||||||
|
:param key: |
||||||
|
:return: |
||||||
|
""" |
||||||
|
raise NotImplementedError |
||||||
|
|
||||||
|
def keys(self): |
||||||
|
""" |
||||||
|
得到所有的键名 |
||||||
|
:return: |
||||||
|
""" |
||||||
|
return self._db.keys('{domain}:{name}:*'.format(domain=self.domain, name=self.name)) |
||||||
|
|
||||||
|
def flush(self): |
||||||
|
""" |
||||||
|
清空数据库, 慎用 |
||||||
|
:return: |
||||||
|
""" |
||||||
|
self._db.flushall() |
||||||
|
|
||||||
|
|
||||||
|
class CookiesRedisClient(RedisClient): |
||||||
|
def __init__(self, host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD, domain='cookies', name='default'): |
||||||
|
""" |
||||||
|
管理Cookies的对象 |
||||||
|
:param host: 地址 |
||||||
|
:param port: 端口 |
||||||
|
:param password: 密码 |
||||||
|
:param domain: 域, 如cookies, account等 |
||||||
|
:param name: 名称, 一般为站点名, 如 weibo, 默认 default |
||||||
|
""" |
||||||
|
RedisClient.__init__(self, host, port, password) |
||||||
|
self.domain = domain |
||||||
|
self.name = name |
||||||
|
|
||||||
|
def set(self, key, value): |
||||||
|
try: |
||||||
|
self._db.set(self._key(key), value) |
||||||
|
except: |
||||||
|
raise SetCookieError |
||||||
|
|
||||||
|
def get(self, key): |
||||||
|
try: |
||||||
|
return self._db.get(self._key(key)).decode('utf-8') |
||||||
|
except: |
||||||
|
return None |
||||||
|
|
||||||
|
def delete(self, key): |
||||||
|
try: |
||||||
|
print('Delete', key) |
||||||
|
return self._db.delete(self._key(key)) |
||||||
|
except: |
||||||
|
raise DeleteCookieError |
||||||
|
|
||||||
|
def random(self): |
||||||
|
""" |
||||||
|
随机得到一Cookies |
||||||
|
:return: |
||||||
|
""" |
||||||
|
try: |
||||||
|
keys = self.keys() |
||||||
|
return self._db.get(random.choice(keys)) |
||||||
|
except: |
||||||
|
raise GetRandomCookieError |
||||||
|
|
||||||
|
def all(self): |
||||||
|
""" |
||||||
|
获取所有账户, 以字典形式返回 |
||||||
|
:return: |
||||||
|
""" |
||||||
|
try: |
||||||
|
for key in self._db.keys('{domain}:{name}:*'.format(domain=self.domain, name=self.name)): |
||||||
|
group = key.decode('utf-8').split(':') |
||||||
|
if len(group) == 3: |
||||||
|
username = group[2] |
||||||
|
yield { |
||||||
|
'username': username, |
||||||
|
'cookies': self.get(username) |
||||||
|
} |
||||||
|
except Exception as e: |
||||||
|
print(e.args) |
||||||
|
raise GetAllCookieError |
||||||
|
|
||||||
|
def count(self): |
||||||
|
""" |
||||||
|
获取当前Cookies数目 |
||||||
|
:return: 数目 |
||||||
|
""" |
||||||
|
return len(self.keys()) |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class AccountRedisClient(RedisClient): |
||||||
|
def __init__(self, host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PASSWORD, domain='account', name='default'): |
||||||
|
RedisClient.__init__(self, host, port, password) |
||||||
|
self.domain = domain |
||||||
|
self.name = name |
||||||
|
|
||||||
|
def set(self, key, value): |
||||||
|
try: |
||||||
|
return self._db.set(self._key(key), value) |
||||||
|
except: |
||||||
|
raise SetAccountError |
||||||
|
|
||||||
|
def get(self, key): |
||||||
|
try: |
||||||
|
return self._db.get(self._key(key)).decode('utf-8') |
||||||
|
except: |
||||||
|
raise GetAccountError |
||||||
|
|
||||||
|
def all(self): |
||||||
|
""" |
||||||
|
获取所有账户, 以字典形式返回 |
||||||
|
:return: |
||||||
|
""" |
||||||
|
try: |
||||||
|
for key in self._db.keys('{domain}:{name}:*'.format(domain=self.domain, name=self.name)): |
||||||
|
group = key.decode('utf-8').split(':') |
||||||
|
if len(group) == 3: |
||||||
|
username = group[2] |
||||||
|
yield { |
||||||
|
'username': username, |
||||||
|
'password': self.get(username) |
||||||
|
} |
||||||
|
except Exception as e: |
||||||
|
print(e.args) |
||||||
|
raise GetAllAccountError |
||||||
|
|
||||||
|
def delete(self, key): |
||||||
|
""" |
||||||
|
通过用户名删除用户 |
||||||
|
:param key: |
||||||
|
:return: |
||||||
|
""" |
||||||
|
try: |
||||||
|
return self._db.delete(self._key(key)) |
||||||
|
except: |
||||||
|
raise DeleteAccountError |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
""" |
||||||
|
conn = CookiesRedisClient() |
||||||
|
conn.set('name', 'Mike') |
||||||
|
conn.set('name2', 'Bob') |
||||||
|
conn.set('name3', 'Amy') |
||||||
|
print(conn.get('name')) |
||||||
|
conn.delete('name') |
||||||
|
print(conn.keys()) |
||||||
|
print(conn.random()) |
||||||
|
""" |
||||||
|
# 测试 |
||||||
|
conn = AccountRedisClient(name='weibo') |
||||||
|
conn.set('14760253606', 'gmidy8470') |
||||||
|
conn.set('14760253607', 'uoyuic8427') |
||||||
|
conn.set('18459749258', 'rktfye8937') |
||||||
|
conn.set('18459748505', 'astvar3647') |
||||||
|
print(conn.get('18459748505')) |
||||||
|
print(conn.keys()) |
||||||
|
accounts = conn.all() |
||||||
|
for account in accounts: |
||||||
|
print(account) |
@ -0,0 +1,48 @@ |
|||||||
|
class CookiePoolError(Exception): |
||||||
|
def __str__(self): |
||||||
|
return repr('Cookie Pool Error') |
||||||
|
|
||||||
|
|
||||||
|
class SetCookieError(CookiePoolError): |
||||||
|
def __str__(self): |
||||||
|
return repr('Set Cookie Error') |
||||||
|
|
||||||
|
|
||||||
|
class GetCookieError(CookiePoolError): |
||||||
|
def __str__(self): |
||||||
|
return repr('Get Cookie Error') |
||||||
|
|
||||||
|
|
||||||
|
class DeleteCookieError(CookiePoolError): |
||||||
|
def __str__(self): |
||||||
|
return repr('Delete Cookie Error') |
||||||
|
|
||||||
|
|
||||||
|
class GetRandomCookieError(CookiePoolError): |
||||||
|
def __str__(self): |
||||||
|
return repr('Get Random Cookie Error') |
||||||
|
|
||||||
|
|
||||||
|
class GetAllCookieError(CookiePoolError): |
||||||
|
def __str__(self): |
||||||
|
return repr('Get All Cookie Error') |
||||||
|
|
||||||
|
|
||||||
|
class SetAccountError(CookiePoolError): |
||||||
|
def __str__(self): |
||||||
|
return repr('Set Account Error') |
||||||
|
|
||||||
|
|
||||||
|
class DeleteAccountError(CookiePoolError): |
||||||
|
def __str__(self): |
||||||
|
return repr('Delete Account Error') |
||||||
|
|
||||||
|
|
||||||
|
class GetAccountError(CookiePoolError): |
||||||
|
def __str__(self): |
||||||
|
return repr('Get Account Error') |
||||||
|
|
||||||
|
|
||||||
|
class GetAllAccountError(CookiePoolError): |
||||||
|
def __str__(self): |
||||||
|
return repr('Get All Account Error') |
@ -0,0 +1,169 @@ |
|||||||
|
import json |
||||||
|
import requests |
||||||
|
import time |
||||||
|
from selenium import webdriver |
||||||
|
from selenium.webdriver import DesiredCapabilities |
||||||
|
from selenium.common.exceptions import WebDriverException, TimeoutException |
||||||
|
from selenium.webdriver.common.by import By |
||||||
|
from selenium.webdriver.support.wait import WebDriverWait |
||||||
|
from selenium.webdriver.support.ui import WebDriverWait |
||||||
|
from selenium.webdriver.support import expected_conditions as EC |
||||||
|
from cookiespool.db import CookiesRedisClient, AccountRedisClient |
||||||
|
from cookiespool.verify import Yundama |
||||||
|
from cookiespool.config import * |
||||||
|
from requests.exceptions import ConnectionError |
||||||
|
|
||||||
|
|
||||||
|
class CookiesGenerator(object): |
||||||
|
def __init__(self, name='default', browser_type=DEFAULT_BROWSER): |
||||||
|
""" |
||||||
|
父类, 初始化一些对象 |
||||||
|
:param name: 名称 |
||||||
|
:param browser: 浏览器, 若不使用浏览器则可设置为 None |
||||||
|
""" |
||||||
|
self.name = name |
||||||
|
self.cookies_db = CookiesRedisClient(name=self.name) |
||||||
|
self.account_db = AccountRedisClient(name=self.name) |
||||||
|
self.browser_type = browser_type |
||||||
|
|
||||||
|
def _init_browser(self, browser_type): |
||||||
|
""" |
||||||
|
通过browser参数初始化全局浏览器供模拟登录使用 |
||||||
|
:param browser: 浏览器 PhantomJS/ Chrome |
||||||
|
:return: |
||||||
|
""" |
||||||
|
if browser_type == 'PhantomJS': |
||||||
|
caps = DesiredCapabilities.PHANTOMJS |
||||||
|
caps[ |
||||||
|
"phantomjs.page.settings.userAgent"] = "Mozilla/5.0 (Linux; U; Android 2.3.6; en-us; Nexus S Build/GRK39F) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1" |
||||||
|
self.browser = webdriver.PhantomJS(desired_capabilities=caps) |
||||||
|
elif browser_type == 'Chrome': |
||||||
|
self.browser = webdriver.Chrome() |
||||||
|
|
||||||
|
def new_cookies(self, username, password): |
||||||
|
raise NotImplementedError |
||||||
|
|
||||||
|
def set_cookies(self, account): |
||||||
|
""" |
||||||
|
根据账户设置新的Cookies |
||||||
|
:param account: |
||||||
|
:return: |
||||||
|
""" |
||||||
|
results = self.new_cookies(account.get('username'), account.get('password')) |
||||||
|
if results: |
||||||
|
username, cookies = results |
||||||
|
print('Saving Cookies to Redis', username, cookies) |
||||||
|
self.cookies_db.set(username, cookies) |
||||||
|
|
||||||
|
|
||||||
|
def run(self): |
||||||
|
""" |
||||||
|
运行, 得到所有账户, 然后顺次模拟登录 |
||||||
|
:return: |
||||||
|
""" |
||||||
|
accounts = self.account_db.all() |
||||||
|
cookies = self.cookies_db.all() |
||||||
|
# Account 中对应的用户 |
||||||
|
accounts = list(accounts) |
||||||
|
# Cookies中对应的用户 |
||||||
|
valid_users = [cookie.get('username') for cookie in cookies] |
||||||
|
print('Getting', len(accounts), 'accounts from Redis') |
||||||
|
if len(accounts): |
||||||
|
self._init_browser(browser_type=self.browser_type) |
||||||
|
for account in accounts: |
||||||
|
if not account.get('username') in valid_users: |
||||||
|
print('Getting Cookies of ', self.name, account.get('username'), account.get('password')) |
||||||
|
self.set_cookies(account) |
||||||
|
print('Generator Run Finished') |
||||||
|
|
||||||
|
def close(self): |
||||||
|
try: |
||||||
|
print('Closing Browser') |
||||||
|
self.browser.close() |
||||||
|
del self.browser |
||||||
|
except TypeError: |
||||||
|
print('Browser not opened') |
||||||
|
|
||||||
|
|
||||||
|
class WeiboCookiesGenerator(CookiesGenerator): |
||||||
|
def __init__(self, name='weibo', browser_type=DEFAULT_BROWSER): |
||||||
|
""" |
||||||
|
初始化操作, 微博需要声明一个云打码引用 |
||||||
|
:param name: 名称微博 |
||||||
|
:param browser: 使用的浏览器 |
||||||
|
""" |
||||||
|
CookiesGenerator.__init__(self, name, browser_type) |
||||||
|
self.name = name |
||||||
|
self.ydm = Yundama(YUNDAMA_USERNAME, YUNDAMA_PASSWORD, YUNDAMA_APP_ID, YUNDAMA_APP_KEY) |
||||||
|
|
||||||
|
def _success(self, username): |
||||||
|
wait = WebDriverWait(self.browser, 5) |
||||||
|
success = wait.until(EC.visibility_of_element_located((By.CLASS_NAME, 'me_portrait_w'))) |
||||||
|
if success: |
||||||
|
print('登录成功') |
||||||
|
self.browser.get('http://weibo.cn/') |
||||||
|
|
||||||
|
if "我的首页" in self.browser.title: |
||||||
|
print(self.browser.get_cookies()) |
||||||
|
cookies = {} |
||||||
|
for cookie in self.browser.get_cookies(): |
||||||
|
cookies[cookie["name"]] = cookie["value"] |
||||||
|
print(cookies) |
||||||
|
print('成功获取到Cookies') |
||||||
|
return (username, json.dumps(cookies)) |
||||||
|
|
||||||
|
def new_cookies(self, username, password): |
||||||
|
""" |
||||||
|
生成Cookies |
||||||
|
:param username: 用户名 |
||||||
|
:param password: 密码 |
||||||
|
:return: 用户名和Cookies |
||||||
|
""" |
||||||
|
print('Generating Cookies of', username) |
||||||
|
self.browser.delete_all_cookies() |
||||||
|
self.browser.get('http://my.sina.com.cn/profile/unlogin') |
||||||
|
wait = WebDriverWait(self.browser, 20) |
||||||
|
|
||||||
|
try: |
||||||
|
login = wait.until(EC.visibility_of_element_located((By.ID, 'hd_login'))) |
||||||
|
login.click() |
||||||
|
user = wait.until( |
||||||
|
EC.visibility_of_element_located((By.CSS_SELECTOR, '.loginformlist input[name="loginname"]'))) |
||||||
|
user.send_keys(username) |
||||||
|
psd = wait.until( |
||||||
|
EC.visibility_of_element_located((By.CSS_SELECTOR, '.loginformlist input[name="password"]'))) |
||||||
|
psd.send_keys(password) |
||||||
|
submit = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, '.login_btn'))) |
||||||
|
submit.click() |
||||||
|
try: |
||||||
|
result = self._success(username) |
||||||
|
if result: |
||||||
|
return result |
||||||
|
except TimeoutException: |
||||||
|
print('出现验证码,开始识别验证码') |
||||||
|
yzm = wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, '.loginform_yzm .yzm'))) |
||||||
|
url = yzm.get_attribute('src') |
||||||
|
cookies = self.browser.get_cookies() |
||||||
|
cookies_dict = {} |
||||||
|
for cookie in cookies: |
||||||
|
cookies_dict[cookie.get('name')] = cookie.get('value') |
||||||
|
response = requests.get(url, cookies=cookies_dict) |
||||||
|
result = self.ydm.identify(stream=response.content) |
||||||
|
if not result: |
||||||
|
print('验证码识别失败, 跳过识别') |
||||||
|
return |
||||||
|
door = wait.until( |
||||||
|
EC.visibility_of_element_located((By.CSS_SELECTOR, '.loginform_yzm input[name="door"]'))) |
||||||
|
door.send_keys(result) |
||||||
|
submit.click() |
||||||
|
result = self._success(username) |
||||||
|
if result: |
||||||
|
return result |
||||||
|
except WebDriverException as e: |
||||||
|
print(e.args) |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
generator = WeiboCookiesGenerator() |
||||||
|
generator._init_browser('Chrome') |
||||||
|
generator.new_cookies('15197170054', 'gmwkms222') |
@ -0,0 +1,24 @@ |
|||||||
|
import requests |
||||||
|
|
||||||
|
from cookiespool.db import AccountRedisClient |
||||||
|
|
||||||
|
conn = AccountRedisClient(name='weibo') |
||||||
|
|
||||||
|
def set(account, sep='----'): |
||||||
|
username, password = account.split(sep) |
||||||
|
result = conn.set(username, password) |
||||||
|
print('账号', username, '密码', password) |
||||||
|
print('录入成功' if result else '录入失败') |
||||||
|
|
||||||
|
|
||||||
|
def scan(): |
||||||
|
print('请输入账号密码组, 输入exit退出读入') |
||||||
|
while True: |
||||||
|
account = input() |
||||||
|
if account == 'exit': |
||||||
|
break |
||||||
|
set(account) |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
scan() |
@ -0,0 +1,56 @@ |
|||||||
|
import time |
||||||
|
from multiprocessing import Process |
||||||
|
from cookiespool.tester import * |
||||||
|
from cookiespool.config import * |
||||||
|
from cookiespool.api import app |
||||||
|
import os |
||||||
|
import signal |
||||||
|
|
||||||
|
|
||||||
|
class Scheduler(object): |
||||||
|
@staticmethod |
||||||
|
def valid_cookie(cycle=CYCLE): |
||||||
|
while True: |
||||||
|
print('Checking Cookies') |
||||||
|
try: |
||||||
|
for name, cls in TESTER_MAP.items(): |
||||||
|
tester = eval(cls + '()') |
||||||
|
tester.run() |
||||||
|
print('Tester Finished') |
||||||
|
del tester |
||||||
|
time.sleep(cycle) |
||||||
|
except Exception as e: |
||||||
|
print(e.args) |
||||||
|
|
||||||
|
@staticmethod |
||||||
|
def generate_cookie(cycle=CYCLE): |
||||||
|
while True: |
||||||
|
print('Generating Cookies') |
||||||
|
try: |
||||||
|
for name, cls in GENERATOR_MAP.items(): |
||||||
|
generator = eval(cls + '()') |
||||||
|
generator.run() |
||||||
|
print('Generator Finished') |
||||||
|
generator.close() |
||||||
|
print('Deleted Generator') |
||||||
|
time.sleep(cycle) |
||||||
|
except Exception as e: |
||||||
|
print(e.args) |
||||||
|
|
||||||
|
@staticmethod |
||||||
|
def api(): |
||||||
|
app.run(host=API_HOST, port=API_PORT) |
||||||
|
|
||||||
|
def run(self): |
||||||
|
if GENERATOR_PROCESS: |
||||||
|
generate_process = Process(target=Scheduler.generate_cookie) |
||||||
|
generate_process.start() |
||||||
|
|
||||||
|
if VALID_PROCESS: |
||||||
|
valid_process = Process(target=Scheduler.valid_cookie) |
||||||
|
valid_process.start() |
||||||
|
|
||||||
|
if API_PROCESS: |
||||||
|
api_process = Process(target=Scheduler.api) |
||||||
|
api_process.start() |
||||||
|
|
@ -0,0 +1,61 @@ |
|||||||
|
import json |
||||||
|
from bs4 import BeautifulSoup |
||||||
|
import requests |
||||||
|
from requests.exceptions import ConnectionError |
||||||
|
from cookiespool.db import * |
||||||
|
from cookiespool.generator import WeiboCookiesGenerator |
||||||
|
|
||||||
|
|
||||||
|
class ValidTester(object): |
||||||
|
def __init__(self, name='default'): |
||||||
|
self.name = name |
||||||
|
self.cookies_db = CookiesRedisClient(name=self.name) |
||||||
|
self.account_db = AccountRedisClient(name=self.name) |
||||||
|
|
||||||
|
def test(self, account, cookies): |
||||||
|
raise NotImplementedError |
||||||
|
|
||||||
|
def run(self): |
||||||
|
accounts = self.cookies_db.all() |
||||||
|
for account in accounts: |
||||||
|
username = account.get('username') |
||||||
|
cookies = self.cookies_db.get(username) |
||||||
|
self.test(account, cookies) |
||||||
|
|
||||||
|
|
||||||
|
class WeiboValidTester(ValidTester): |
||||||
|
def __init__(self, name='weibo'): |
||||||
|
ValidTester.__init__(self, name) |
||||||
|
|
||||||
|
def test(self, account, cookies): |
||||||
|
print('Testing Account', account.get('username')) |
||||||
|
try: |
||||||
|
cookies = json.loads(cookies) |
||||||
|
except TypeError: |
||||||
|
# Cookie 格式不正确 |
||||||
|
print('Invalid Cookies Value', account.get('username')) |
||||||
|
self.cookies_db.delete(account.get('username')) |
||||||
|
print('Deleted User', account.get('username')) |
||||||
|
return None |
||||||
|
try: |
||||||
|
response = requests.get('http://weibo.cn', cookies=cookies) |
||||||
|
if response.status_code == 200: |
||||||
|
html = response.text |
||||||
|
soup = BeautifulSoup(html, 'lxml') |
||||||
|
title = soup.title.string |
||||||
|
if title == '我的首页': |
||||||
|
print('Valid Cookies', account.get('username')) |
||||||
|
else: |
||||||
|
print('Title is', title) |
||||||
|
# Cookie已失效 |
||||||
|
print('Invalid Cookies', account.get('username')) |
||||||
|
self.cookies_db.delete(account.get('username')) |
||||||
|
print('Deleted User', account.get('username')) |
||||||
|
except ConnectionError as e: |
||||||
|
print('Error', e.args) |
||||||
|
print('Invalid Cookies', account.get('username')) |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
tester = WeiboValidTester() |
||||||
|
tester.run() |
@ -0,0 +1,137 @@ |
|||||||
|
import requests |
||||||
|
import time |
||||||
|
from requests.exceptions import ConnectionError |
||||||
|
from cookiespool.config import * |
||||||
|
|
||||||
|
|
||||||
|
class Yundama(): |
||||||
|
def __init__(self, username, password, app_id, app_key, api_url=YUNDAMA_API_URL): |
||||||
|
self.username = username |
||||||
|
self.password = password |
||||||
|
self.app_id = str(app_id) if not isinstance(app_id, str) else app_id |
||||||
|
self.app_key = app_key |
||||||
|
self.api_url = api_url |
||||||
|
|
||||||
|
def login(self): |
||||||
|
""" |
||||||
|
登录云打码账户 |
||||||
|
:return: |
||||||
|
""" |
||||||
|
try: |
||||||
|
data = {'method': 'login', 'username': self.username, 'password': self.password, 'appid': self.app_id, |
||||||
|
'appkey': self.app_key} |
||||||
|
response = requests.post(self.api_url, data=data) |
||||||
|
if response.status_code == 200: |
||||||
|
result = response.json() |
||||||
|
print(result) |
||||||
|
if 'ret' in result.keys() and result.get('ret') < 0: |
||||||
|
return self.error(result.get('ret')) |
||||||
|
else: |
||||||
|
return result |
||||||
|
return None |
||||||
|
except ConnectionError: |
||||||
|
return None |
||||||
|
|
||||||
|
def upload(self, files, timeout, code_type): |
||||||
|
""" |
||||||
|
上传验证码得到识别结果 |
||||||
|
:param files: |
||||||
|
:param timeout: |
||||||
|
:param code_type: |
||||||
|
:return: |
||||||
|
""" |
||||||
|
try: |
||||||
|
data = {'method': 'upload', 'username': self.username, 'password': self.password, 'appid': self.app_id, |
||||||
|
'appkey': self.app_key, 'codetype': str(code_type), 'timeout': str(timeout)} |
||||||
|
response = requests.post(self.api_url, data=data, files=files) |
||||||
|
if response.status_code == 200: |
||||||
|
return response.json() |
||||||
|
return None |
||||||
|
except ConnectionError: |
||||||
|
return None |
||||||
|
|
||||||
|
def retry(self, cid, try_count=1): |
||||||
|
""" |
||||||
|
临时识别不出, 传入cid重试 |
||||||
|
:param cid: 验证码ID |
||||||
|
:param try_count: 重试次数 |
||||||
|
:return: 验证码结果 |
||||||
|
""" |
||||||
|
if try_count >= YUNDAMA_MAX_RETRY: |
||||||
|
return None |
||||||
|
print('Retrying: ', cid, 'Count: ', try_count) |
||||||
|
time.sleep(2) |
||||||
|
try: |
||||||
|
data = {'method': 'result', 'cid': cid} |
||||||
|
print(data) |
||||||
|
response = requests.post(self.api_url, data=data) |
||||||
|
if response.status_code == 200: |
||||||
|
result = response.json() |
||||||
|
print(result) |
||||||
|
if 'ret' in result.keys() and result.get('ret') < 0: |
||||||
|
print(self.error(result.get('ret'))) |
||||||
|
if result.get('ret') == 0 and 'text' in result.keys(): |
||||||
|
return result.get('text') |
||||||
|
else: |
||||||
|
return self.retry(cid, try_count + 1) |
||||||
|
return None |
||||||
|
except ConnectionError: |
||||||
|
return None |
||||||
|
|
||||||
|
def identify(self, file=None, stream=None, timeout=60, code_type=5000): |
||||||
|
""" |
||||||
|
主函数 |
||||||
|
:param file: 文件名 |
||||||
|
:param stream: 文件流, 优先于文件名 |
||||||
|
:param timeout: 超时时间 |
||||||
|
:param code_type: 验证码类型 |
||||||
|
:return: 识别结果 |
||||||
|
""" |
||||||
|
if stream: |
||||||
|
files = {'file': stream} |
||||||
|
elif file: |
||||||
|
files = {'file': open(file, 'rb')} |
||||||
|
else: |
||||||
|
return None |
||||||
|
result = self.upload(files, timeout, code_type) |
||||||
|
if 'ret' in result.keys() and result.get('ret') < 0: |
||||||
|
print(self.error(result.get('ret'))) |
||||||
|
if result.get('text'): |
||||||
|
print('验证码识别成功', result.get('text')) |
||||||
|
return result.get('text') |
||||||
|
else: |
||||||
|
return self.retry(result.get('cid')) |
||||||
|
|
||||||
|
def error(self, code): |
||||||
|
""" |
||||||
|
报错原因 |
||||||
|
:param code: 错误码 |
||||||
|
:return: 错误原因 |
||||||
|
""" |
||||||
|
map = { |
||||||
|
-1001: '密码错误', |
||||||
|
-1002: '软件ID/密钥有误', |
||||||
|
-1003: '用户被封', |
||||||
|
-1004: 'IP被封', |
||||||
|
-1005: '软件被封', |
||||||
|
-1006: '登录IP与绑定的区域不匹配', |
||||||
|
-1007: '账号余额为零', |
||||||
|
-2001: '验证码类型有误', |
||||||
|
-2002: '验证码图片太大', |
||||||
|
-2003: '验证码图片损坏', |
||||||
|
-2004: '上传验证码图片失败', |
||||||
|
-3001: '验证码ID不存在 ', |
||||||
|
-3002: '验证码还在识别', |
||||||
|
-3003: '验证码识别超时', |
||||||
|
-3004: '验证码看不清', |
||||||
|
-3005: '验证码报错失败', |
||||||
|
-4001: '充值卡号不正确或已使用', |
||||||
|
-5001: '注册用户失败' |
||||||
|
} |
||||||
|
return '云打码' + map.get(code) |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
ydm = Yundama(YUNDAMA_USERNAME, YUNDAMA_PASSWORD, YUNDAMA_APP_ID, YUNDAMA_APP_KEY) |
||||||
|
result = ydm.identify(file='getimage.jpg') |
||||||
|
print(result) |
@ -0,0 +1,8 @@ |
|||||||
|
from cookiespool.scheduler import Scheduler |
||||||
|
|
||||||
|
def main(): |
||||||
|
s = Scheduler() |
||||||
|
s.run() |
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
main() |
@ -0,0 +1,17 @@ |
|||||||
|
import requests |
||||||
|
from bs4 import BeautifulSoup |
||||||
|
|
||||||
|
cookies = { |
||||||
|
'SSOLoginState': '1493555070', |
||||||
|
'SCF': 'ArrMd41qtHmW87eTIsI-sT1IjDG8oncB9A0HbSmyDw1FwO5sbI_j6_ZellQQ07ZjTXTIBrM3Y_tpKym39f1tYWs.', |
||||||
|
'SUB': '_2A250AacuDeRhGeRG6FIX9ybIzDiIHXVXDclmrDV6PUJbktBeLVfCkW18FWjD8r3ddYXy2abmqSauclujaw..', |
||||||
|
'_T_WM': '5e9c698a350ddeba1c5d77e1958af21b', 'ALF': '1496147067', 'SUHB': '0G0vWR88D2VokZ', |
||||||
|
'SUBP': '0033WrSXqPxfM725Ws9jqgMF55529P9D9W5APD86CuQDllBusA-6OZaq5JpX5o2p5NHD95QE1he7SoMRShMXWs4Dqcjci--fi-zXiK.Xi--fi-iWiKnci--ciKn4iKy2i--Xi-zRi-2Ri--4iKL2iK.4i--Ri-2NiKnf' |
||||||
|
} |
||||||
|
|
||||||
|
response = requests.get('http://weibo.cn', cookies=cookies) |
||||||
|
if response.status_code == 200: |
||||||
|
html = response.text |
||||||
|
soup = BeautifulSoup(html, 'lxml') |
||||||
|
title = soup.title.string |
||||||
|
print(title) |
Loading…
Reference in new issue