update python_weibo.py, use requests

master
xianhu 2016-11-07 10:24:36 +08:00
parent 3df5ac1958
commit 9f29890855
1 changed files with 31 additions and 62 deletions

View File

@ -6,18 +6,14 @@ python_weibo.py by xianhu
import re import re
import rsa import rsa
import ssl
import time import time
import json import json
import base64 import base64
import logging import logging
import binascii import binascii
import requests
import urllib.parse import urllib.parse
# 参考PSpider项目
import spider
ssl._create_default_https_context = ssl._create_unverified_context
class WeiBoLogin(object): class WeiBoLogin(object):
""" """
@ -28,51 +24,34 @@ class WeiBoLogin(object):
""" """
constructor constructor
""" """
self.user_name = None # 登录用户名 self.user_name = None
self.pass_word = None # 登录密码 self.pass_word = None
self.user_uniqueid = None # 用户唯一ID self.user_uniqueid = None
self.user_nick = None # 用户昵称 self.user_nick = None
self.cookie_jar, self.opener = None, None self.session = requests.Session()
self.session.headers.update({"User-Agent": "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0"})
self.session.get("http://weibo.com/login.php")
return return
def login(self, user_name, pass_word, proxies=None): def login(self, user_name, pass_word):
""" """
login weibo.com, return True or False login weibo.com, return True or False
""" """
# 变量赋值初始化
self.user_name = user_name self.user_name = user_name
self.pass_word = pass_word self.pass_word = pass_word
self.user_uniqueid = None self.user_uniqueid = None
self.user_nick = None self.user_nick = None
# 构建cookie_jar和opener,这里不使用代理,同时保证整个流程中不需要关心cookie问题 # get json data
self.cookie_jar, self.opener = spider.make_cookiejar_opener(is_cookie=True, proxies=proxies)
self.opener.addheaders = spider.make_headers(
user_agent="pc",
host="weibo.com",
referer="http://weibo.com/",
accept="text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
accept_encoding="gzip, deflate",
accept_language="zh-CN,zh;q=0.8"
).items()
# (1) 打开weibo.com/login.php,先请求一些必要的cookie信息
self.opener.open("http://weibo.com/login.php")
# (2) 根据用户名获取加密后的用户名
s_user_name = self.get_username() s_user_name = self.get_username()
# (3) 利用加密后的用户名,获取其他一些数据:json格式
json_data = self.get_json_data(su_value=s_user_name) json_data = self.get_json_data(su_value=s_user_name)
if not json_data: if not json_data:
return False return False
# (4) 根据第三步得到的json数据,获取加密后的密码
s_pass_word = self.get_password(json_data["servertime"], json_data["nonce"], json_data["pubkey"]) s_pass_word = self.get_password(json_data["servertime"], json_data["nonce"], json_data["pubkey"])
# (5) 构造登录中用到的postdata # make post_data
post_dict = { post_data = {
"entry": "weibo", "entry": "weibo",
"gateway": "1", "gateway": "1",
"from": "", "from": "",
@ -93,35 +72,28 @@ class WeiBoLogin(object):
"returntype": "TEXT", "returntype": "TEXT",
} }
# (6) 判断是否需要输入验证码,如果需要,获取验证码并进行打码操作 # get captcha code
if json_data.get("showpin", None) == 1: if json_data["showpin"] == 1:
url = "http://login.sina.com.cn/cgi/pin.php?r=%d&s=0&p=%s" % (int(time.time()), json_data["pcid"]) url = "http://login.sina.com.cn/cgi/pin.php?r=%d&s=0&p=%s" % (int(time.time()), json_data["pcid"])
with open("captcha.jpeg", "wb") as file_out: with open("captcha.jpeg", "wb") as file_out:
file_out.write(self.opener.open(url).read()) file_out.write(self.session.get(url).content)
code = input("请输入验证码:") code = input("请输入验证码:")
# cid, code = self.yundama.get_captcha(self.opener.open(url).read(), "captcha.jpeg", "image/jpeg", codetype="1005") post_data["pcid"] = json_data["pcid"]
# if not code: post_data["door"] = code
# return False
post_dict["pcid"] = json_data["pcid"]
post_dict["door"] = code
# (7) 根据构造的postdata,登录微博 # login weibo.com
login_url_1 = "http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.18)&_=%d" % int(time.time()) login_url_1 = "http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.18)&_=%d" % int(time.time())
json_data_1 = json.loads(spider.get_html_content(self.opener.open(login_url_1, data=spider.make_post_data(post_dict)))) json_data_1 = self.session.post(login_url_1, data=post_data).json()
if json_data_1["retcode"] == "0": if json_data_1["retcode"] == "0":
# 登录后有一个跳转, 构造跳转链接的postdata params = {
post_dict = {
"callback": "sinaSSOController.callbackLoginStatus", "callback": "sinaSSOController.callbackLoginStatus",
"client": "ssologin.js(v1.4.18)",
"ticket": json_data_1["ticket"], "ticket": json_data_1["ticket"],
"ssosavestate": int(time.time()), "ssosavestate": int(time.time()),
"client": "ssologin.js(v1.4.18)",
"_": int(time.time()*1000), "_": int(time.time()*1000),
} }
login_url_2 = "https://passport.weibo.com/wbsso/login?" + urllib.parse.urlencode(post_dict) response = self.session.get("https://passport.weibo.com/wbsso/login", params=params)
html_data = spider.get_html_content(self.opener.open(login_url_2), charset="gbk") json_data_2 = json.loads(re.search(r"\((?P<result>.*)\)", response.text).group("result"))
json_data_2 = json.loads(re.search("\((?P<result>.*)\)", html_data).group("result"))
# 检查登录是否成功,并获取用户唯一ID,用户昵称等
if json_data_2["result"] is True: if json_data_2["result"] is True:
self.user_uniqueid = json_data_2["userinfo"]["uniqueid"] self.user_uniqueid = json_data_2["userinfo"]["uniqueid"]
self.user_nick = json_data_2["userinfo"]["displayname"] self.user_nick = json_data_2["userinfo"]["displayname"]
@ -134,7 +106,7 @@ class WeiBoLogin(object):
def get_username(self): def get_username(self):
""" """
get username, encrypt file: http://tjs.sjs.sinajs.cn/t5/register/js/page/remote/loginLayer.js get legal username
""" """
username_quote = urllib.parse.quote_plus(self.user_name) username_quote = urllib.parse.quote_plus(self.user_name)
username_base64 = base64.b64encode(username_quote.encode("utf-8")) username_base64 = base64.b64encode(username_quote.encode("utf-8"))
@ -144,7 +116,7 @@ class WeiBoLogin(object):
""" """
get the value of "servertime", "nonce", "pubkey", "rsakv" and "showpin", etc get the value of "servertime", "nonce", "pubkey", "rsakv" and "showpin", etc
""" """
post_data = urllib.parse.urlencode({ params = {
"entry": "weibo", "entry": "weibo",
"callback": "sinaSSOController.preloginCallBack", "callback": "sinaSSOController.preloginCallBack",
"rsakt": "mod", "rsakt": "mod",
@ -152,12 +124,10 @@ class WeiBoLogin(object):
"client": "ssologin.js(v1.4.18)", "client": "ssologin.js(v1.4.18)",
"su": su_value, "su": su_value,
"_": int(time.time()*1000), "_": int(time.time()*1000),
}) }
try: try:
response = self.opener.open('http://login.sina.com.cn/sso/prelogin.php?'+post_data) response = self.session.get("http://login.sina.com.cn/sso/prelogin.php", params=params)
data = spider.get_html_content(response, charset="utf-8") json_data = json.loads(re.search(r"\((?P<data>.*)\)", response.text).group("data"))
json_data = json.loads(re.search("\((?P<data>.*)\)", data).group("data"))
except Exception as excep: except Exception as excep:
json_data = {} json_data = {}
logging.error("WeiBoLogin get_json_data error: %s", excep) logging.error("WeiBoLogin get_json_data error: %s", excep)
@ -167,17 +137,16 @@ class WeiBoLogin(object):
def get_password(self, servertime, nonce, pubkey): def get_password(self, servertime, nonce, pubkey):
""" """
get legal password, encrypt file: http://tjs.sjs.sinajs.cn/t5/register/js/page/remote/loginLayer.js get legal password
""" """
string = (str(servertime) + '\t' + str(nonce) + '\n' + str(self.pass_word)).encode("utf-8") string = (str(servertime) + "\t" + str(nonce) + "\n" + str(self.pass_word)).encode("utf-8")
public_key = rsa.PublicKey(int(pubkey, 16), int("10001", 16)) public_key = rsa.PublicKey(int(pubkey, 16), int("10001", 16))
password = rsa.encrypt(string, public_key) password = rsa.encrypt(string, public_key)
password = binascii.b2a_hex(password) password = binascii.b2a_hex(password)
return password.decode() return password.decode()
if __name__ == '__main__': if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s\t%(levelname)s\t%(message)s") logging.basicConfig(level=logging.DEBUG, format="%(asctime)s\t%(levelname)s\t%(message)s")
# 测试登录,输入微博的用户名和密码
weibo = WeiBoLogin() weibo = WeiBoLogin()
weibo.login("username", "password") weibo.login("username", "password")