新增多个模拟登录
This commit is contained in:
Vendored
BIN
Binary file not shown.
@@ -0,0 +1,67 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from lxml import etree
|
||||||
|
try:
|
||||||
|
import cookielib
|
||||||
|
except:
|
||||||
|
import http.cookiejar as cookielib
|
||||||
|
|
||||||
|
|
||||||
|
class GithubLogin(object):
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.headers = {
|
||||||
|
'Referer': 'https://github.com/',
|
||||||
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36',
|
||||||
|
'Host': 'github.com'
|
||||||
|
}
|
||||||
|
self.login_url ='https://github.com/login'
|
||||||
|
self.post_url = 'https://github.com/session'
|
||||||
|
self.logined_url = 'https://github.com/settings/profile'
|
||||||
|
|
||||||
|
self.session = requests.session()
|
||||||
|
self.session.cookies = cookielib.LWPCookieJar(filename='github_cookie')
|
||||||
|
|
||||||
|
def load_cookie(self):
|
||||||
|
try:
|
||||||
|
self.session.cookies.load(ignore_discard=True)
|
||||||
|
except:
|
||||||
|
print('cookie 不成功')
|
||||||
|
|
||||||
|
def get_param(self):
|
||||||
|
response = self.session.get(self.login_url, headers=self.headers)
|
||||||
|
selector = etree.HTML(response.text)
|
||||||
|
field_one = selector.xpath('//div/input[2]/@value')
|
||||||
|
print(field_one)
|
||||||
|
return field_one
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def post_param(self, email, password):
|
||||||
|
post_data = {
|
||||||
|
'commit': 'Sign in',
|
||||||
|
'utf8': '✓',
|
||||||
|
'authenticity_token': self.get_param()[0],
|
||||||
|
'login': email,
|
||||||
|
'password': password
|
||||||
|
}
|
||||||
|
response = self.session.post(self.post_url, data=post_data, headers=self.headers)
|
||||||
|
self.session.cookies.save()
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def bool_login(self):
|
||||||
|
self.load_cookie()
|
||||||
|
response = self.session.get(self.logined_url, headers=self.headers)
|
||||||
|
selector = etree.HTML(response.text)
|
||||||
|
flag = selector.xpath('//div[@class="column two-thirds"]/dl/dt/label/text()')
|
||||||
|
print(u'个人设置Profile包括: %s'%flag)
|
||||||
|
pass
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
Github = GithubLogin()
|
||||||
|
Github.post_param(email='******', password='******')
|
||||||
|
# Github.bool_login()
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
The MIT License
|
The MIT License
|
||||||
|
|
||||||
Copyright (c) 2016-2019 CriseLYJ.
|
Copyright (c) 2018 CriseLYJ.
|
||||||
|
https://github.com/CriseLYJ/awesome-python-login-model
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
@@ -9,13 +10,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
The above copyright notice and this permission notice shall be included in all
|
||||||
all copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
THE SOFTWARE
|
SOFTWARE.
|
||||||
@@ -1,36 +1,91 @@
|
|||||||
|
<h2 align="center"><code>Website_login_mode</code></h2>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<p align="center">
|
||||||
|
<img src="https://github.com/CriseLYJ/flask-video-streaming-recorder/blob/master/img/main.jpg?raw=true"
|
||||||
|
alt="Master">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<p align="center">"<i>Did you know all your doors were locked?</i>" - Riddick (The Chronicles of Riddick)</p>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<div align="center">
|
||||||
|
<sub>Created by
|
||||||
|
<a href="https://criselyj.github.io/">CriseLYJ</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
****
|
||||||
|
|
||||||
# Website_login_mode
|
# Website_login_mode
|
||||||
各大网站登陆方式,有的是通过selenium登录,有的是通过抓包直接模拟登录,希望对小白有所帮助,本项目用于研究和分享各大网站的模拟登陆方式,主要使用selenium+phantomjs或者直接登录的方式,语言采用Python
|
收集了一些各大网站登陆方式,有的是通过selenium登录,有的是通过抓包直接模拟登录,希望对小白有所帮助,本项目用于研究和分享各大网站的模拟登陆方式。
|
||||||
|
|
||||||
|
## 模拟登录一些常见的网站
|
||||||
|
主要基于以下的 Python 的第三 library
|
||||||
|
|
||||||
|
1. requests
|
||||||
|
2. selenium
|
||||||
|
3. rsa
|
||||||
|
4. phantomjs
|
||||||
|
|
||||||
|
|
||||||
## 关于
|
## About
|
||||||
|
|
||||||
由于工作需要,研究了一段时间的新浪微博登陆方式,在网上也查看了很多别人的经验,但是有相当一部分都是转载而且代码老旧,所以便有了这个repo。
|
|
||||||
|
|
||||||
模拟登陆基本采用的是直接登录或者使用selenium+webdriver的方式,有的网站直接登录难度很大,比如qq空间,如果采用selenium就相对轻松一些。
|
模拟登陆基本采用的是直接登录或者使用selenium+webdriver的方式,有的网站直接登录难度很大,比如qq空间,如果采用selenium就相对轻松一些。
|
||||||
|
|
||||||
虽然在登录的时候采用的是selenium,为了效率,我们可以在登录过后得到的cookie维护起来,然后调用requests或者scrapy等进行数据采集,这样数据采集的速度可以得到保证。
|
虽然在登录的时候采用的是selenium,为了效率,我们可以在登录过后得到的cookie维护起来,然后调用requests或者scrapy等进行数据采集,这样数据采集的速度可以得到保证。
|
||||||
|
|
||||||
下面是已经实现的目标
|
## Done
|
||||||
|
|
||||||
- [x] Facebook
|
- [x] [Facebook](https://www.facebook.com/)
|
||||||
- [x] Twitter
|
- [x] [Twitter](https://twitter.com/)
|
||||||
- [x] Weibo
|
- [x] [微博网页版](http://weibo.com)
|
||||||
- [x] 知乎
|
- [x] [知乎](http://zhihu.com)
|
||||||
- [x] QQZone
|
- [x] [QQZone](https://qzone.qq.com/)
|
||||||
- [x] CSDN
|
- [x] [CSDN](https://www.csdn.net/)
|
||||||
- [x] 淘宝
|
- [x] [淘宝](www.taobao.com)
|
||||||
- [x] Baidu
|
- [x] [Baidu](www.baidu.com)
|
||||||
- [x] 果壳
|
- [x] [果壳](https://www.guokr.com/)
|
||||||
- [x] JingDong
|
- [x] [JingDong](https://www.jd.com/)
|
||||||
- [x] 163main
|
- [x] [163mail](https://mail.163.com/)
|
||||||
- [x] 拉钩
|
- [x] [拉钩](https://www.lagou.com/)
|
||||||
|
- [x] [Bilibili](https://www.bilibili.com/)
|
||||||
|
- [x] [豆瓣](https://www.douban.com/)
|
||||||
|
- [x] [V2EX](https://www.v2ex.com/)
|
||||||
|
- [x] [Baidu2](www.baidu.com)
|
||||||
|
- [x] [猎聘网](https://www.liepin.com/)
|
||||||
|
- [x] [微信网页版](https://wx.qq.com/)
|
||||||
|
- [x] [gihub](https://github.com/)
|
||||||
|
- [x] [图虫](https://tuchong.com/)
|
||||||
|
|
||||||
|
## tips of pull request
|
||||||
|
|
||||||
## 常见问题
|
- 欢迎大家一起来 pull request
|
||||||
|
|
||||||
|
## Problems
|
||||||
|
|
||||||
- 关于验证码:本项目所用的方法都没有处理验证码,识别复杂验证码的难度就目前来说,还是比较大的。以我的心得来说,做爬虫最好的方式就是尽量规避验证码。
|
- 关于验证码:本项目所用的方法都没有处理验证码,识别复杂验证码的难度就目前来说,还是比较大的。以我的心得来说,做爬虫最好的方式就是尽量规避验证码。
|
||||||
- 代码失效:由于网站策略或者样式改变,导致代码失效,请给我提issue,如果你已经解决,可以提PR,谢谢!
|
- 代码失效:由于网站策略或者样式改变,导致代码失效,请给我提issue,如果你已经解决,可以提PR,谢谢!
|
||||||
|
|
||||||
## 其它
|
## Another
|
||||||
- 如果你有什么比较难登陆的网站,比如发现用了selenium+webdriver都还登陆不了的网站,欢迎给我提issue
|
- 如果你有什么比较难登陆的网站,比如发现用了selenium+webdriver都还登陆不了的网站,欢迎给我提issue
|
||||||
- 如果该repo对大家有帮助,给个star鼓励鼓励吧
|
- 如果该repo对大家有帮助,给个star鼓励鼓励吧
|
||||||
|
|
||||||
|
## something to add
|
||||||
|
|
||||||
|
1. 项目写了一段时间后,发现代码的风格和程序的易用性,可扩展性,代码的可读性,都存在一定的问题,所以接下来最重要的是重构代码,让大家可以更容易的做出一些自己的小功能。
|
||||||
|
2. 如果你觉得某个网站的登录很有代表性,欢迎在 issue 中提出
|
||||||
|
3. 如果网站的登录很有意思,我会在后面的更新中加入
|
||||||
|
4. 网站的登录机制有可能经常的变动,所以当现在的模拟的登录的规则不能使用的时候,请在 issue 中提出
|
||||||
|
- 如果关注量大的话,我还是会不断维护此仓库带来更多的东西,并且重构代码!
|
||||||
|
|
||||||
|
## Acknowledgement
|
||||||
|
- Thanks for all!
|
||||||
|
|
||||||
|
## Written at the end
|
||||||
|
- I need your support.
|
||||||
|
- And I think you can give me a ``star``!
|
||||||
|
|
||||||
|
|||||||
+201
@@ -0,0 +1,201 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
'''
|
||||||
|
Required
|
||||||
|
- requests (必须)
|
||||||
|
- rsa (必须)
|
||||||
|
'''
|
||||||
|
import requests
|
||||||
|
import math
|
||||||
|
import random
|
||||||
|
import rsa
|
||||||
|
# import binascii
|
||||||
|
# import os
|
||||||
|
import base64
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
1. 百度的模拟登录,请确保你的账号能在浏览器下登录不需要验证码
|
||||||
|
百度的三次登录错误后,才会出现验证码,但是还有一种情况是百度的账号异常
|
||||||
|
|
||||||
|
2. 这是一个初级的版本的,以后会对代码整理完善,并且统一代码风格
|
||||||
|
|
||||||
|
几个重要的参数
|
||||||
|
|
||||||
|
-- gid:js 代码构造 不需要 http 请求
|
||||||
|
|
||||||
|
-- token:需要 https://passport.baidu.com/v2/api/? 加上参数
|
||||||
|
但是不能使用 requests 的 params 参数 因为顺序不同的话,访问出问题
|
||||||
|
|
||||||
|
-- pubkey 和 rsakey
|
||||||
|
需要 http 请求获得
|
||||||
|
还有 RSA 的加密 以及 加密后的 base64 字符串化
|
||||||
|
|
||||||
|
-- callback 的 参数是动态变化的
|
||||||
|
|
||||||
|
post login 时候 还有 ppui_logintime 时间间隔参数
|
||||||
|
|
||||||
|
我是通过随机访问了一个贴吧的链接 查查是否有我的用户名 来判断是否登录成功的
|
||||||
|
if there are still questions you encounter, feel free to contact by email
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
# gid 在同一个登录的 session 相同
|
||||||
|
def get_gid():
|
||||||
|
gid = "xxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
|
||||||
|
gid = list(gid)
|
||||||
|
for xy in range(len(gid)):
|
||||||
|
if gid[xy] in "xy":
|
||||||
|
r = int(random.random()*16)
|
||||||
|
if gid[xy] == "x":
|
||||||
|
gid[xy] = hex(r).replace("0x", '').upper()
|
||||||
|
else:
|
||||||
|
gid[xy] = hex(r & 3 | 8).replace("0x", '').upper()
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
return ''.join(gid)
|
||||||
|
|
||||||
|
|
||||||
|
# 每次都不同
|
||||||
|
def get_callback():
|
||||||
|
loopabc = '0123456789abcdefghijklmnopqrstuvwxyz'
|
||||||
|
prefix = "bd__cbs__"
|
||||||
|
n = math.floor(random.random() * 2147483648)
|
||||||
|
a = []
|
||||||
|
while n != 0:
|
||||||
|
a.append(loopabc[n % 36])
|
||||||
|
n = n // 36
|
||||||
|
a.reverse()
|
||||||
|
callback = prefix + ''.join(a)
|
||||||
|
return callback
|
||||||
|
|
||||||
|
|
||||||
|
# 密码加密
|
||||||
|
def get_password(password_input, pubkey):
|
||||||
|
pub = rsa.PublicKey.load_pkcs1_openssl_pem(pubkey.encode("utf-8"))
|
||||||
|
password_input = password_input.encode("utf-8")
|
||||||
|
psword = rsa.encrypt(password_input, pub)
|
||||||
|
psword = base64.b64encode(psword)
|
||||||
|
return psword.decode("utf-8")
|
||||||
|
|
||||||
|
|
||||||
|
# 构造 Request headers
|
||||||
|
|
||||||
|
agent = 'Mozilla/5.0 (Windows NT 5.1; rv:33.0) Gecko/20100101 Firefox/33.0'
|
||||||
|
headers = {
|
||||||
|
'User-Agent': agent,
|
||||||
|
"Host": "passport.baidu.com",
|
||||||
|
"Referer": "https://www.baidu.com/"
|
||||||
|
}
|
||||||
|
gid = get_gid()
|
||||||
|
session = requests.session()
|
||||||
|
# 访问登录页面的初始页面,然后这次访问会话带上 cookies
|
||||||
|
session.get("https://passport.baidu.com/v2/?login", headers=headers)
|
||||||
|
|
||||||
|
|
||||||
|
# 同一个登录下 token 是唯一的
|
||||||
|
def get_token():
|
||||||
|
# 此处必须是自己构造 url 不能采用 params 的参数, params 参数的顺序是变化的
|
||||||
|
token_callback = get_callback()
|
||||||
|
global init_time
|
||||||
|
init_time = str(int(time.time() * 1000))
|
||||||
|
token_url = "https://passport.baidu.com/v2/api/?getapi&tpl=pp&apiver=v3&tt="
|
||||||
|
token_url = token_url + init_time + "&class=login&gid="
|
||||||
|
token_url = token_url + gid + "&logintype=basicLogin&callback="
|
||||||
|
token_url = token_url + token_callback
|
||||||
|
# token_params = {
|
||||||
|
# "getapi": "",
|
||||||
|
# "tpl": "pp",
|
||||||
|
# "apiver": "v3",
|
||||||
|
# "tt": str(int(time.time() * 1000)),
|
||||||
|
# "class": "login",
|
||||||
|
# "gid": gid,
|
||||||
|
# "logintype": "dialogLogin",
|
||||||
|
# "callback": get_callback()
|
||||||
|
# }
|
||||||
|
token_html = session.get(token_url, headers=headers)
|
||||||
|
token_content_all = token_html.text.replace(token_callback, "")
|
||||||
|
token_content_all = eval(token_content_all)
|
||||||
|
# print(token_content_all)
|
||||||
|
return token_content_all['data']['token']
|
||||||
|
|
||||||
|
token = (get_token())
|
||||||
|
|
||||||
|
|
||||||
|
def get_publickey(token):
|
||||||
|
publickey_callback = get_callback()
|
||||||
|
publickey_url = "https://passport.baidu.com/v2/getpublickey?token="
|
||||||
|
publickey_url = publickey_url + token + "&tpl=pp&apiver=v3&tt="
|
||||||
|
publickey_url = publickey_url + str(int(time.time() * 1000)) + "&gid="
|
||||||
|
publickey_url = publickey_url + gid + "&callback="
|
||||||
|
publickey_url = publickey_url + publickey_callback
|
||||||
|
# print(publickey_url)
|
||||||
|
|
||||||
|
headers["Referer"] = "https://passport.baidu.com/v2/?login"
|
||||||
|
publickey_html = session.get(publickey_url, headers=headers)
|
||||||
|
publickey_content_all = eval(publickey_html.text.replace(publickey_callback, ""))
|
||||||
|
|
||||||
|
return publickey_content_all['pubkey'], publickey_content_all['key']
|
||||||
|
|
||||||
|
|
||||||
|
# print(get_publickey(token))
|
||||||
|
|
||||||
|
pubkey, key = get_publickey(token)
|
||||||
|
|
||||||
|
# 随机停顿 几秒 模拟真实的浏览情况
|
||||||
|
time.sleep(random.randint(2, 5))
|
||||||
|
|
||||||
|
|
||||||
|
def login(username, password, key):
|
||||||
|
login_url = "https://passport.baidu.com/v2/api/?login"
|
||||||
|
login_time = str(int(time.time() * 1000))
|
||||||
|
login_callback = get_callback()
|
||||||
|
login_postdata = {
|
||||||
|
"staticpage": "https://passport.baidu.com/static/passpc-account/html/v3Jump.html",
|
||||||
|
"charset": "UTF-8",
|
||||||
|
"token": token,
|
||||||
|
"tpl": "pp",
|
||||||
|
"subpro": "",
|
||||||
|
"apiver": "v3",
|
||||||
|
"tt": login_time,
|
||||||
|
"codestring": "",
|
||||||
|
"safeflg": "0",
|
||||||
|
"u": "https://passport.baidu.com/",
|
||||||
|
"isPhone": "",
|
||||||
|
"detect": "1",
|
||||||
|
"gid": gid,
|
||||||
|
"quick_user": "0",
|
||||||
|
"logintype": "basicLogin",
|
||||||
|
"logLoginType": "pc_loginBasic",
|
||||||
|
"idc": "",
|
||||||
|
"loginmerge": "true",
|
||||||
|
"username": username,
|
||||||
|
"password": password,
|
||||||
|
"verifycode": "",
|
||||||
|
"mem_pass": "on",
|
||||||
|
"rsakey": key,
|
||||||
|
"crypttype": "12",
|
||||||
|
"ppui_logintime": str(int(login_time) - int(init_time)),
|
||||||
|
"countrycode": "",
|
||||||
|
"callback": login_callback,
|
||||||
|
}
|
||||||
|
|
||||||
|
login_html = session.post(login_url, data=login_postdata, headers=headers)
|
||||||
|
print(login_html.cookies)
|
||||||
|
# html_index = session.get('贴吧的任何一个帖子的地址,判断是否登录成功')
|
||||||
|
# with open("tieba.html", 'wb') as f:
|
||||||
|
# f.write(html_index.content)
|
||||||
|
# f.close()
|
||||||
|
|
||||||
|
try:
|
||||||
|
input = raw_input
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
username = input("请输入你的手机号或者邮箱\n >:")
|
||||||
|
secret = input("请输入你的密码\n >:")
|
||||||
|
login(username, get_password(secret, pubkey), key)
|
||||||
Vendored
BIN
Binary file not shown.
@@ -0,0 +1,126 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
'''
|
||||||
|
Required
|
||||||
|
- requests (必须)
|
||||||
|
- pillow (可选)
|
||||||
|
'''
|
||||||
|
|
||||||
|
import requests
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import rsa
|
||||||
|
import os.path
|
||||||
|
import binascii
|
||||||
|
import datetime
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
try:
|
||||||
|
import cookielib
|
||||||
|
except:
|
||||||
|
import http.cookiejar as cookielib
|
||||||
|
|
||||||
|
try:
|
||||||
|
from PIL import Image
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
session = requests.Session()
|
||||||
|
session.headers = {
|
||||||
|
'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:50.0) Gecko/20100101 Firefox/50.0',
|
||||||
|
'Connection': 'keep-alive',
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||||
|
}
|
||||||
|
|
||||||
|
# 使用登录cookie信息
|
||||||
|
session = requests.session()
|
||||||
|
session.cookies = cookielib.LWPCookieJar(filename='cookies')
|
||||||
|
try:
|
||||||
|
session.cookies.load(ignore_discard=True)
|
||||||
|
except:
|
||||||
|
print("Cookie 未能加载")
|
||||||
|
|
||||||
|
def rsaEncrypt(password):
|
||||||
|
url = 'http://passport.bilibili.com/login?act=getkey'
|
||||||
|
try:
|
||||||
|
getKeyRes = session.get(url)
|
||||||
|
token = json.loads(getKeyRes.content.decode('utf-8'))
|
||||||
|
pw = str(token['hash'] + password).encode('utf-8')
|
||||||
|
|
||||||
|
key = token['key']
|
||||||
|
key = rsa.PublicKey.load_pkcs1_openssl_pem(key)
|
||||||
|
|
||||||
|
pw = rsa.encrypt(pw, key)
|
||||||
|
password = binascii.b2a_base64(pw)
|
||||||
|
return password
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_vdcode():
|
||||||
|
t = str(int(time.time()*1000))
|
||||||
|
captcha_url = 'https://passport.bilibili.com/captcha.gif?r=' + t + "&type=login"
|
||||||
|
r = session.get(captcha_url)
|
||||||
|
with open('captcha.jpg', 'wb') as f:
|
||||||
|
f.write(r.content)
|
||||||
|
f.close()
|
||||||
|
# 用pillow 的 Image 显示验证码
|
||||||
|
# 如果没有安装 pillow 到源代码所在的目录去找到验证码然后手动输入
|
||||||
|
try:
|
||||||
|
im = Image.open('captcha.jpg')
|
||||||
|
im.show()
|
||||||
|
im.close()
|
||||||
|
except:
|
||||||
|
print(u'请到 %s 目录找到captcha.jpg 手动输入' % os.path.abspath('captcha.jpg'))
|
||||||
|
captcha = input("please input the captcha\n>")
|
||||||
|
return captcha
|
||||||
|
|
||||||
|
def login(user, password):
|
||||||
|
post_url = 'https://passport.bilibili.com/login/dologin'
|
||||||
|
payload = {
|
||||||
|
'act': 'login',
|
||||||
|
'gourl': '',
|
||||||
|
'keeptime': '2592000',
|
||||||
|
'userid': user,
|
||||||
|
'pwd': password,
|
||||||
|
'vdcode': get_vdcode(),
|
||||||
|
}
|
||||||
|
if payload["vdcode"] == None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
resp = session.post(post_url, data=payload)
|
||||||
|
session.cookies.save()
|
||||||
|
|
||||||
|
soup = BeautifulSoup(resp.content, 'lxml')
|
||||||
|
s = str(soup.select('center')[0])
|
||||||
|
s = s.replace('\n', '')
|
||||||
|
s = s.replace('\r', '')
|
||||||
|
s = s.replace(' ', '')
|
||||||
|
s = s.split('>')
|
||||||
|
s = s[2]
|
||||||
|
s = s.replace('<br/', '')
|
||||||
|
flash(s)
|
||||||
|
return False
|
||||||
|
except requests.exceptions.ConnectionError as e:
|
||||||
|
flash(e)
|
||||||
|
return False
|
||||||
|
except:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def isLogin():
|
||||||
|
url = 'https://account.bilibili.com/home/userInfo'
|
||||||
|
resp = session.get(url, allow_redirects=False)
|
||||||
|
if resp.status_code == 200 and resp.json()['code'] == 0:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if isLogin():
|
||||||
|
print('您已经登录')
|
||||||
|
else:
|
||||||
|
account = input('请输入你的用户名:')
|
||||||
|
password = input('请输入密码:')
|
||||||
|
login(account, rsaEncrypt(password))
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
'''
|
||||||
|
Required
|
||||||
|
- requests (必须)
|
||||||
|
- bs4 (必选)
|
||||||
|
- pillow (可选)
|
||||||
|
'''
|
||||||
|
|
||||||
|
from urllib.request import urlretrieve
|
||||||
|
import requests
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
from os import remove
|
||||||
|
try:
|
||||||
|
import cookielib
|
||||||
|
except:
|
||||||
|
import http.cookiejar as cookielib
|
||||||
|
try:
|
||||||
|
from PIL import Image
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
url = 'https://accounts.douban.com/login'
|
||||||
|
|
||||||
|
datas = {'source': 'index_nav',
|
||||||
|
'remember': 'on'}
|
||||||
|
|
||||||
|
headers = {'Host':'www.douban.com',
|
||||||
|
'Referer': 'https://www.douban.com/',
|
||||||
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0',
|
||||||
|
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
|
||||||
|
'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
|
||||||
|
'Accept-Encoding':'gzip, deflate, br'}
|
||||||
|
|
||||||
|
# 尝试使用cookie信息
|
||||||
|
session = requests.session()
|
||||||
|
session.cookies = cookielib.LWPCookieJar(filename='cookies')
|
||||||
|
try:
|
||||||
|
session.cookies.load(ignore_discard=True)
|
||||||
|
except:
|
||||||
|
print("Cookies未能加载")
|
||||||
|
#cookies加载不成功,则输入账号密码信息
|
||||||
|
datas['form_email'] = input('Please input your account:')
|
||||||
|
datas['form_password'] = input('Please input your password:')
|
||||||
|
|
||||||
|
|
||||||
|
def get_captcha():
|
||||||
|
'''
|
||||||
|
获取验证码及其ID
|
||||||
|
'''
|
||||||
|
r = requests.post(url, data=datas, headers=headers)
|
||||||
|
page = r.text
|
||||||
|
soup = BeautifulSoup(page, "html.parser")
|
||||||
|
# 利用bs4获得验证码图片地址
|
||||||
|
img_src = soup.find('img', {'id': 'captcha_image'}).get('src')
|
||||||
|
urlretrieve(img_src, 'captcha.jpg')
|
||||||
|
try:
|
||||||
|
im = Image.open('captcha.jpg')
|
||||||
|
im.show()
|
||||||
|
im.close()
|
||||||
|
except:
|
||||||
|
print('到本地目录打开captcha.jpg获取验证码')
|
||||||
|
finally:
|
||||||
|
captcha = input('please input the captcha:')
|
||||||
|
remove('captcha.jpg')
|
||||||
|
captcha_id = soup.find(
|
||||||
|
'input', {'type': 'hidden', 'name': 'captcha-id'}).get('value')
|
||||||
|
return captcha, captcha_id
|
||||||
|
|
||||||
|
|
||||||
|
def isLogin():
|
||||||
|
'''
|
||||||
|
通过查看用户个人账户信息来判断是否已经登录
|
||||||
|
'''
|
||||||
|
url = "https://www.douban.com/accounts/"
|
||||||
|
login_code = session.get(url, headers=headers,
|
||||||
|
allow_redirects=False).status_code
|
||||||
|
if login_code == 200:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def login():
|
||||||
|
captcha, captcha_id = get_captcha()
|
||||||
|
# 增加表数据
|
||||||
|
datas['captcha-solution'] = captcha
|
||||||
|
datas['captcha-id'] = captcha_id
|
||||||
|
login_page = session.post(url, data=datas, headers=headers)
|
||||||
|
page = login_page.text
|
||||||
|
soup = BeautifulSoup(page, "html.parser")
|
||||||
|
result = soup.findAll('div', attrs={'class': 'title'})
|
||||||
|
#进入豆瓣登陆后页面,打印热门内容
|
||||||
|
for item in result:
|
||||||
|
print(item.find('a').get_text())
|
||||||
|
# 保存 cookies 到文件,
|
||||||
|
# 下次可以使用 cookie 直接登录,不需要输入账号和密码
|
||||||
|
session.cookies.save()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if isLogin():
|
||||||
|
print('Login successfully')
|
||||||
|
else:
|
||||||
|
login()
|
||||||
Vendored
BIN
Binary file not shown.
@@ -0,0 +1,74 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
'''
|
||||||
|
Required
|
||||||
|
- requests
|
||||||
|
- bs4
|
||||||
|
'''
|
||||||
|
import hashlib
|
||||||
|
import requests
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
class Leipin(object):
|
||||||
|
def __init__(self, username, password):
|
||||||
|
self.username = username
|
||||||
|
self.password = password
|
||||||
|
self.headers = {
|
||||||
|
'Accept':'application/json, text/javascript, */*; q=0.01',
|
||||||
|
'Accept-Encoding':'gzip, deflate, sdch',
|
||||||
|
'Accept-Language':'zh-CN,zh;q=0.8',
|
||||||
|
'Connection':'keep-alive',
|
||||||
|
'Content-Type':'application/x-www-form-urlencoded',
|
||||||
|
'Host':'passport.liepin.com',
|
||||||
|
'User-Agent': "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
|
||||||
|
'X-Requested-With': 'XMLHttpRequest',
|
||||||
|
'Upgrade-Insecure-Requests':'1',
|
||||||
|
}
|
||||||
|
self.proxies = {
|
||||||
|
'HTTP':'http://120.198.231.88:80',
|
||||||
|
#'HTTP':'http://222.174.71.46:9999',
|
||||||
|
} # 测试所用代理
|
||||||
|
self.session = requests.session()
|
||||||
|
self.accountUrl = 'https://passport.liepin.com/h/account'
|
||||||
|
self.loginUrl = 'https://passport.liepin.com/h/login.json'
|
||||||
|
self.Dir = 'E:\\python\\authcode.jpg' #authcode folder 根据自己情况选择文件夹
|
||||||
|
|
||||||
|
def _md5(self):
|
||||||
|
md5 = hashlib.md5()
|
||||||
|
md5.update(str.encode(password))
|
||||||
|
psw = md5.hexdigest()
|
||||||
|
return psw
|
||||||
|
|
||||||
|
def _getAuthcode(self):
|
||||||
|
r = self.session.get(self.accountUrl,headers = self.headers,timeout = 10, proxies = self.proxies)
|
||||||
|
page = BeautifulSoup(r.text)
|
||||||
|
selector = page.find_all('div', class_="ui-tab-toggle hide")[0]
|
||||||
|
imageUrl = selector.select('div > img')[0]['src']
|
||||||
|
authcodeUrl = 'https://passport.liepin.com{}'.format(imageUrl)
|
||||||
|
response = self.session.get(authcodeUrl)
|
||||||
|
if response.status_code == 200:
|
||||||
|
with open(self.Dir, 'wb') as f:
|
||||||
|
f.write(response.content)
|
||||||
|
authcode = input('plz input authcode:')
|
||||||
|
return authcode
|
||||||
|
|
||||||
|
def login(self):
|
||||||
|
payload ={
|
||||||
|
'user_login':self.username,
|
||||||
|
'isMd5':1,
|
||||||
|
'user_pwd': self._md5(),
|
||||||
|
'user_kind':2, #根据你是否为正式会员而定,根据自身情况可能需要修改
|
||||||
|
'verifycode':self._getAuthcode(),
|
||||||
|
'url':'',
|
||||||
|
}
|
||||||
|
del self.headers['Upgrade-Insecure-Requests']
|
||||||
|
self.headers['Origin'] = 'https://passport.liepin.com'
|
||||||
|
self.headers['Referer']='https://passport.liepin.com/h/account'
|
||||||
|
response = self.session.post(self.loginUrl, headers=self.headers, data = payload, timeout =10, proxies = self.proxies ,allow_redirects =False)
|
||||||
|
return response.status_code, response.text
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
userName = input("plz input username:")
|
||||||
|
password = input("plz input password:")
|
||||||
|
lp = Leipin(userName,password)
|
||||||
|
print (lp.login())
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
'''
|
||||||
|
Required
|
||||||
|
- requests (必须)
|
||||||
|
'''
|
||||||
|
|
||||||
|
import rsa
|
||||||
|
import binascii
|
||||||
|
import requests
|
||||||
|
from base64 import b64decode
|
||||||
|
import sys
|
||||||
|
reload(sys)
|
||||||
|
sys.setdefaultencoding('utf8')
|
||||||
|
|
||||||
|
|
||||||
|
agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36"
|
||||||
|
|
||||||
|
#pubkey 在页面的js中: http://static.tuchong.net/js/pc/page/welcome_6e7f1cd.js
|
||||||
|
pubkey = "D8CC0180AFCC72C9F5981BDB90A27928672F1D6EA8A57AF44EFFA7DAF6EFB17DAD9F643B9F9F7A1F05ACC2FEA8DE19F023200EFEE9224104627F1E680CE8F025AF44824A45EA4DDC321672D2DEAA91DB27418CFDD776848F27A76E747D53966683EFB00F7485F3ECF68365F5C10C69969AE3D665162D2EE3A5BA109D7DF6C7A5"
|
||||||
|
session = requests.session()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_crypt_password(message):
|
||||||
|
rsaPublickey = int(pubkey, 16)
|
||||||
|
key = rsa.PublicKey(rsaPublickey, 65537)
|
||||||
|
passwd = rsa.encrypt(message, key)
|
||||||
|
passwd = binascii.b2a_hex(passwd)
|
||||||
|
return passwd
|
||||||
|
|
||||||
|
def get_captcha():
|
||||||
|
captcha_url="https://tuchong.com/rest/captcha/image"
|
||||||
|
headers={
|
||||||
|
'user-agent': agent
|
||||||
|
}
|
||||||
|
rsp=session.post(captcha_url, data=None, headers=headers).json()
|
||||||
|
captcha_id=rsp['captchaId']
|
||||||
|
captcha_base64=rsp['captchaBase64']
|
||||||
|
captcha_base64=captcha_base64.replace("data:image/png;base64,","")
|
||||||
|
with open("captcha.png",'w') as f:
|
||||||
|
f.write(b64decode(captcha_base64))
|
||||||
|
captcha=input(u'输入当前目录下 captcha.png 上的验证码:')
|
||||||
|
return captcha_id,captcha
|
||||||
|
|
||||||
|
|
||||||
|
def login(username,passwd):
|
||||||
|
login_url = 'https://tuchong.com/rest/accounts/login'
|
||||||
|
headers={
|
||||||
|
'user-agent': agent
|
||||||
|
}
|
||||||
|
|
||||||
|
passwd_crypt=get_crypt_password(passwd)
|
||||||
|
postdata = {
|
||||||
|
'account': username,
|
||||||
|
'password': passwd_crypt,
|
||||||
|
}
|
||||||
|
|
||||||
|
rsp = session.post(login_url, data=postdata, headers=headers)
|
||||||
|
rsp=rsp.json()
|
||||||
|
print(rsp)
|
||||||
|
#登录成功
|
||||||
|
if rsp.has_key('result') and rsp['result']=="SUCCESS":
|
||||||
|
print(rsp['message'])
|
||||||
|
return
|
||||||
|
|
||||||
|
#登录失败
|
||||||
|
if rsp.has_key('code') and rsp.has_key('message'):
|
||||||
|
print("response code:%d, message:%s"%(rsp['code'],rsp['message']))
|
||||||
|
if rsp['message'].find("验证码")>=0 :
|
||||||
|
print(rsp['message'])
|
||||||
|
captcha=get_captcha()
|
||||||
|
postdata={
|
||||||
|
'account': username,
|
||||||
|
'password': passwd_crypt,
|
||||||
|
'captcha_id': captcha[0],
|
||||||
|
'captcha_token': int(captcha[1])
|
||||||
|
}
|
||||||
|
rsp = session.post(login_url, data=postdata, headers=headers)
|
||||||
|
if str(rsp).find('200'):
|
||||||
|
print("登陆成功!")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
username=raw_input(u'用户名:')
|
||||||
|
passwd=raw_input(u'密码:')
|
||||||
|
login(username,passwd)
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# coding: utf-8
|
||||||
|
# v2ex.py
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
Required
|
||||||
|
- requests
|
||||||
|
- lxml
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
import requests
|
||||||
|
from io import StringIO
|
||||||
|
from lxml import etree
|
||||||
|
|
||||||
|
|
||||||
|
class V2EX:
|
||||||
|
login_url = 'https://www.v2ex.com/signin'
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, user_name, password):
|
||||||
|
self.user_name = user_name
|
||||||
|
self.password = password
|
||||||
|
|
||||||
|
session = requests.Session()
|
||||||
|
session.headers = {
|
||||||
|
'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Safari/602.1.50"
|
||||||
|
}
|
||||||
|
self.session = session
|
||||||
|
|
||||||
|
|
||||||
|
def get_login_parameters(self):
|
||||||
|
response = self.session.get(self.login_url)
|
||||||
|
|
||||||
|
parser = etree.HTMLParser()
|
||||||
|
tree = etree.parse(StringIO(response.text), parser)
|
||||||
|
elements = tree.xpath('//form[@method="post" and @action="/signin"]/table[@cellpadding="5" and @cellspacing="0" and @border="0" and @width="100%"]//tr[position()<last()]/td[2]/input')
|
||||||
|
user_name_key = elements[0].xpath('@name')[0]
|
||||||
|
password_key = elements[1].xpath('@name')[0]
|
||||||
|
once = elements[2].xpath('@value')[0]
|
||||||
|
return user_name_key, password_key, once
|
||||||
|
|
||||||
|
|
||||||
|
def login(self, user_name_key, password_key, once):
|
||||||
|
# 必须带上 referer
|
||||||
|
self.session.headers.update({'referer': self.login_url})
|
||||||
|
d = {
|
||||||
|
user_name_key: self.user_name,
|
||||||
|
password_key: self.password,
|
||||||
|
'once': once,
|
||||||
|
'next': '/'
|
||||||
|
}
|
||||||
|
response = self.session.post(self.login_url, d)
|
||||||
|
flag = False
|
||||||
|
if "条未读提醒" in response.text:
|
||||||
|
flag = True
|
||||||
|
return flag
|
||||||
|
|
||||||
|
|
||||||
|
def test_login(self):
|
||||||
|
user_name_key, password_key, once = self.get_login_parameters()
|
||||||
|
return self.login(user_name_key, password_key, once)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
v2ex = V2EX("user_name", "password")
|
||||||
|
print("login\t%r" % v2ex.test_login())
|
||||||
|
|
||||||
|
|
||||||
Vendored
BIN
Binary file not shown.
@@ -0,0 +1,279 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding:utf-8 -*-
|
||||||
|
'''
|
||||||
|
Required:必须
|
||||||
|
'''
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
import requests
|
||||||
|
import xml.dom.minidom
|
||||||
|
import json
|
||||||
|
|
||||||
|
session = requests.session()
|
||||||
|
headers = {
|
||||||
|
'User-Agent' : 'Mozilla/5.0 (Windows NT 5.1; rv:33.0) Gecko/20100101 Firefox/33.0'
|
||||||
|
}
|
||||||
|
|
||||||
|
QRImgPath = os.path.split(os.path.realpath(__file__))[0] + os.sep + 'webWeixinQr.jpg'
|
||||||
|
uuid = ''
|
||||||
|
tip = 0
|
||||||
|
base_uri = ''
|
||||||
|
redirect_uri = ''
|
||||||
|
skey = ''
|
||||||
|
wxsid = ''
|
||||||
|
wxuin = ''
|
||||||
|
pass_ticket = ''
|
||||||
|
deviceId = 'e000000000000000'
|
||||||
|
BaseRequest = {}
|
||||||
|
ContactList = []
|
||||||
|
My = []
|
||||||
|
SyncKey = ''
|
||||||
|
|
||||||
|
|
||||||
|
def getUUID():
|
||||||
|
global uuid,session
|
||||||
|
|
||||||
|
url = 'https://login.weixin.qq.com/jslogin'
|
||||||
|
params = {
|
||||||
|
'appid': 'wx782c26e4c19acffb',
|
||||||
|
'fun': 'new',
|
||||||
|
'lang': 'zh_CN',
|
||||||
|
'_': int(time.time()),
|
||||||
|
}
|
||||||
|
|
||||||
|
response = session.get(url, params=params)
|
||||||
|
data = response.content.decode('utf-8')
|
||||||
|
# print(data) >>> window.QRLogin.code = 200; window.QRLogin.uuid = "oZwt_bFfRg==";
|
||||||
|
|
||||||
|
regx = r'window.QRLogin.code = (\d+); window.QRLogin.uuid = "(\S+?)"'
|
||||||
|
pm = re.search(regx, data)
|
||||||
|
|
||||||
|
code = pm.group(1)
|
||||||
|
uuid = pm.group(2)
|
||||||
|
|
||||||
|
if code == '200':
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def showQRImage():
|
||||||
|
global tip
|
||||||
|
|
||||||
|
url = 'https://login.weixin.qq.com/qrcode/' + uuid
|
||||||
|
params = {
|
||||||
|
't': 'webwx',
|
||||||
|
'_': int(time.time()),
|
||||||
|
}
|
||||||
|
|
||||||
|
response = session.get(url, params=params)
|
||||||
|
|
||||||
|
tip = 1
|
||||||
|
|
||||||
|
with open(QRImgPath, 'wb') as f:
|
||||||
|
f.write(response.content)
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
if sys.platform.find('darwin') >= 0:
|
||||||
|
subprocess.call(['open', QRImgPath])
|
||||||
|
elif sys.platform.find('linux') >= 0:
|
||||||
|
subprocess.call(['xdg-open', QRImgPath])
|
||||||
|
else:
|
||||||
|
os.startfile(QRImgPath)
|
||||||
|
|
||||||
|
print('请使用微信扫描二维码以登录')
|
||||||
|
|
||||||
|
|
||||||
|
def waitForLogin():
|
||||||
|
global tip, base_uri, redirect_uri
|
||||||
|
|
||||||
|
url = 'https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?tip=%s&uuid=%s&_=%s' % (
|
||||||
|
tip, uuid, int(time.time()))
|
||||||
|
|
||||||
|
response = session.get(url)
|
||||||
|
data = response.content.decode('utf-8')
|
||||||
|
|
||||||
|
# print(data)
|
||||||
|
|
||||||
|
# window.code=500;
|
||||||
|
regx = r'window.code=(\d+);'
|
||||||
|
pm = re.search(regx, data)
|
||||||
|
|
||||||
|
code = pm.group(1)
|
||||||
|
|
||||||
|
if code == '201': # 已扫描
|
||||||
|
print('成功扫描,请在手机上点击确认以登录')
|
||||||
|
tip = 0
|
||||||
|
elif code == '200': # 已登录
|
||||||
|
print('正在登录...')
|
||||||
|
regx = r'window.redirect_uri="(\S+?)";'
|
||||||
|
pm = re.search(regx, data)
|
||||||
|
redirect_uri = pm.group(1) + '&fun=new'
|
||||||
|
base_uri = redirect_uri[:redirect_uri.rfind('/')]
|
||||||
|
|
||||||
|
# closeQRImage
|
||||||
|
if sys.platform.find('darwin') >= 0: # for OSX with Preview
|
||||||
|
os.system("osascript -e 'quit app \"Preview\"'")
|
||||||
|
elif code == '408': # 超时
|
||||||
|
pass
|
||||||
|
# elif code == '400' or code == '500':
|
||||||
|
|
||||||
|
return code
|
||||||
|
|
||||||
|
|
||||||
|
def login():
|
||||||
|
global skey, wxsid, wxuin, pass_ticket, BaseRequest
|
||||||
|
|
||||||
|
response = session.get(redirect_uri)
|
||||||
|
data = response.content.decode('utf-8')
|
||||||
|
|
||||||
|
# print(data)
|
||||||
|
|
||||||
|
'''
|
||||||
|
<error>
|
||||||
|
<ret>0</ret>
|
||||||
|
<message>OK</message>
|
||||||
|
<skey>xxx</skey>
|
||||||
|
<wxsid>xxx</wxsid>
|
||||||
|
<wxuin>xxx</wxuin>
|
||||||
|
<pass_ticket>xxx</pass_ticket>
|
||||||
|
<isgrayscale>1</isgrayscale>
|
||||||
|
</error>
|
||||||
|
'''
|
||||||
|
xml.dom
|
||||||
|
doc = xml.dom.minidom.parseString(data)
|
||||||
|
root = doc.documentElement
|
||||||
|
|
||||||
|
for node in root.childNodes:
|
||||||
|
if node.nodeName == 'skey':
|
||||||
|
skey = node.childNodes[0].data
|
||||||
|
elif node.nodeName == 'wxsid':
|
||||||
|
wxsid = node.childNodes[0].data
|
||||||
|
elif node.nodeName == 'wxuin':
|
||||||
|
wxuin = node.childNodes[0].data
|
||||||
|
elif node.nodeName == 'pass_ticket':
|
||||||
|
pass_ticket = node.childNodes[0].data
|
||||||
|
|
||||||
|
# print('skey: %s, wxsid: %s, wxuin: %s, pass_ticket: %s' % (skey, wxsid,
|
||||||
|
# wxuin, pass_ticket))
|
||||||
|
|
||||||
|
if not all((skey, wxsid, wxuin, pass_ticket)):
|
||||||
|
return False
|
||||||
|
|
||||||
|
BaseRequest = {
|
||||||
|
'Uin': int(wxuin),
|
||||||
|
'Sid': wxsid,
|
||||||
|
'Skey': skey,
|
||||||
|
'DeviceID': deviceId,
|
||||||
|
}
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def webwxinit():
|
||||||
|
|
||||||
|
url = base_uri + \
|
||||||
|
'/webwxinit?pass_ticket=%s&skey=%s&r=%s' % (
|
||||||
|
pass_ticket, skey, int(time.time()))
|
||||||
|
params = {
|
||||||
|
'BaseRequest': BaseRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
h = headers
|
||||||
|
h['ContentType'] = 'application/json; charset=UTF-8'
|
||||||
|
response = session.post(url, data=json.dumps(params), headers=h)
|
||||||
|
data = response.content.decode('utf-8')
|
||||||
|
#print(data)
|
||||||
|
|
||||||
|
global ContactList, My, SyncKey
|
||||||
|
|
||||||
|
dic = json.loads(data)
|
||||||
|
ContactList = dic['ContactList']
|
||||||
|
My = dic['User']
|
||||||
|
|
||||||
|
SyncKeyList = []
|
||||||
|
for item in dic['SyncKey']['List']:
|
||||||
|
SyncKeyList.append('%s_%s' % (item['Key'], item['Val']))
|
||||||
|
SyncKey = '|'.join(SyncKeyList)
|
||||||
|
|
||||||
|
ErrMsg = dic['BaseResponse']['ErrMsg']
|
||||||
|
|
||||||
|
Ret = dic['BaseResponse']['Ret']
|
||||||
|
if Ret != 0:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def webwxgetcontact():
|
||||||
|
|
||||||
|
url = base_uri + \
|
||||||
|
'/webwxgetcontact?pass_ticket=%s&skey=%s&r=%s' % (
|
||||||
|
pass_ticket, skey, int(time.time()))
|
||||||
|
|
||||||
|
h = headers
|
||||||
|
h['ContentType'] = 'application/json; charset=UTF-8'
|
||||||
|
response = session.get(url, headers=h)
|
||||||
|
data = response.content.decode('utf-8')
|
||||||
|
# print(data)
|
||||||
|
|
||||||
|
dic = json.loads(data)
|
||||||
|
MemberList = dic['MemberList']
|
||||||
|
|
||||||
|
# 倒序遍历,不然删除的时候出问题..
|
||||||
|
SpecialUsers = ["newsapp", "fmessage", "filehelper", "weibo", "qqmail", "tmessage", "qmessage", "qqsync", "floatbottle", "lbsapp", "shakeapp", "medianote", "qqfriend", "readerapp", "blogapp", "facebookapp", "masssendapp",
|
||||||
|
"meishiapp", "feedsapp", "voip", "blogappweixin", "weixin", "brandsessionholder", "weixinreminder", "wxid_novlwrv3lqwv11", "gh_22b87fa7cb3c", "officialaccounts", "notification_messages", "wxitil", "userexperience_alarm"]
|
||||||
|
for i in range(len(MemberList) - 1, -1, -1):
|
||||||
|
Member = MemberList[i]
|
||||||
|
if Member['VerifyFlag'] & 8 != 0: # 公众号/服务号
|
||||||
|
MemberList.remove(Member)
|
||||||
|
elif Member['UserName'] in SpecialUsers: # 特殊账号
|
||||||
|
MemberList.remove(Member)
|
||||||
|
elif Member['UserName'].find('@@') != -1: # 群聊
|
||||||
|
MemberList.remove(Member)
|
||||||
|
elif Member['UserName'] == My['UserName']: # 自己
|
||||||
|
MemberList.remove(Member)
|
||||||
|
|
||||||
|
return MemberList
|
||||||
|
|
||||||
|
def main():
|
||||||
|
|
||||||
|
if not getUUID():
|
||||||
|
print('获取uuid失败')
|
||||||
|
return
|
||||||
|
|
||||||
|
showQRImage()
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
while waitForLogin() != '200':
|
||||||
|
pass
|
||||||
|
|
||||||
|
os.remove(QRImgPath)
|
||||||
|
|
||||||
|
if not login():
|
||||||
|
print('登录失败')
|
||||||
|
return
|
||||||
|
#登录完成, 下面查询好友
|
||||||
|
if not webwxinit():
|
||||||
|
print('初始化失败')
|
||||||
|
return
|
||||||
|
|
||||||
|
MemberList = webwxgetcontact()
|
||||||
|
|
||||||
|
print('通讯录共%s位好友' % len(MemberList))
|
||||||
|
|
||||||
|
for x in MemberList :
|
||||||
|
sex = '未知' if x['Sex'] == 0 else '男' if x['Sex'] == 1 else '女'
|
||||||
|
print('昵称:%s, 性别:%s, 备注:%s, 签名:%s' % (x['NickName'], sex, x['RemarkName'], x['Signature']))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print('开始')
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user