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