Flaskhtml
Flask是一個使用 Python 編寫的輕量級 Web 應用框架。其 WSGI 工具箱採用 Werkzeug ,模板引擎則使用 Jinja2 。Flask使用 BSD 受權。
Flask也被稱爲 「microframework」 ,由於它使用簡單的核心,用 extension 增長其餘功能。Flask沒有默認使用的數據庫、窗體驗證工具。python
簡單安裝web
pip3 install flask
簡單的實例數據庫
1 from flask import Flask 2 app = Flask(__name__) 3 4 @app.route("/") 5 def hello(): 6 return "Hello Flask!" 7 8 if __name__ == "__main__": 9 app.run()
Flask路由系統json
Flask中使用 app.route 裝飾器,把裝飾器的函數註冊到路由。flask
route(url, method)微信
@app.route('/', method=['GET'])
Flask session和重定向cookie
flask 有一個 session 對象。容許你在不一樣請求間存儲特定用戶的信息。它是在 Cookies 的基礎上實現的,而且對 Cookies 進行密鑰簽名要使用會話但在這個以前須要設置一個密鑰。session
from flask import Flask, render_template, request, redirect, session, url_for # 先實例化一個Flask對象 app = Flask(__name__) app.debug = True USERS = { 1: {"name": "Ojia", "age": 19, "性別": "nan"}, 2: {"name": "夜市街", "age": 19, "性別": "nan"}, 3: {"name": "夜市街1", "age": 19, "性別": "nan"}, } app.secret_key = 'siuljskdjfs' @app.route("/detail/<int:nid>", methods=["GET"]) def detail(nid): user = session.get("user_info") if not user: return redirect("/login") info = USERS.get(nid) return render_template("detail.html", info=info) @app.route('/index', methods=["GET"]) def index(): user = session.get("user_info") if not user: url = url_for("l1") return redirect("l1") return render_template("index.html", user_dict=USERS) @app.route('/login', methods=["GET", "POST"], endpoint="l1") # --> s = app.route("/") 2.s(hello_world) def login(): if request.method == "GET": return render_template("login.html") else: # request.query_string user = request.form.get("user") pwd = request.form.get("pwd") if user == "me" and pwd == "998": session["user_info"] = user return redirect("http://www.baidu.com") return render_template("login.html", error="用戶名或者密碼錯誤") if __name__ == "__main__": app.run()
在此次基於Flask微信中app
以前從未接觸Flask,在做業前惡補了一段時間的Flask
簡單來講,Flask是一個短小精悍的武器,可擴展性比較強,Flask有個上下文管理的,頗有用。
在此次做業中,我對爬蟲有了更深的認識,我將總結一下此次的關鍵位置
獲取UUID,method=「Get」
qcode_url = "https://login.wx.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=zh_CN&_=時間戳*1000
返回結果
window.QRLogin.code = 200; window.QRLogin.uuid = "xxx"
re正則獲取uuid,保存下來
檢測是否已經掃碼登陸,method=「Get」
check_url = "https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=上面獲取的uuid&tip=0&r=-1106230517&_=時間戳"
返回結果
window.code=xxx;
xxx:
408 登錄超時
201 掃描成功
200 確認登陸
if "code=201" in ret.text:
# 掃碼成功
src = re.findall("userAvatar = '(.*)';", ret.text)[0]
elif "code=200" in ret.text:
# 確認登陸
redirct_url = re.findall('redirect_uri="(.*)";', ret.text)[0]
關鍵來了:在 redirct_url 後面須要找到隱藏的後綴:&fun=new&version=v2
拼接獲得新連接後從新發Get請求,解析和保存返回的結果和cookies
1 <error> 2 <ret>0</ret> 3 <message>OK</message> 4 <skey>xxx</skey> 5 <wxsid>xxx</wxsid> 6 <wxuin>xxx</wxuin> 7 <pass_ticket>xxx</pass_ticket> 8 <isgrayscale>1</isgrayscale> 9 </error>
首頁用戶初始化,method = "POST"
init_url = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=-1240095087&lang=zh_CN&pass_ticket={0}".format(ticket_dict.get("pass_ticket"))
pass_ticket在上面分返回結果能夠解析獲得
data_dict = { "BaseRequest": { "DeviceID": "e965263748707552", "Sid": ticket_dict.get("wxsid"), "Skey": ticket_dict.get("skey"), "Uin": ticket_dict.get("wxuin") }
同上方式所得
返回結果
1 { 2 "BaseResponse": { 3 "Ret": 0, 4 "ErrMsg": "" 5 }, 6 "Count": 11, 7 "ContactList": [...], 8 "SyncKey": { 9 "Count": 4, 10 "List": [ 11 { 12 "Key": 1, 13 "Val": 635705559 14 }, 15 ... 16 ] 17 }, 18 "User": { 19 "Uin": xxx, 20 "UserName": xxx, 21 "NickName": xxx, 22 "HeadImgUrl": xxx, 23 "RemarkName": "", 24 "PYInitial": "", 25 "PYQuanPin": "", 26 "RemarkPYInitial": "", 27 "RemarkPYQuanPin": "", 28 "HideInputBarFlag": 0, 29 "StarFriend": 0, 30 "Sex": 1, 31 "Signature": "Apt-get install B", 32 "AppAccountFlag": 0, 33 "VerifyFlag": 0, 34 "ContactFlag": 0, 35 "WebWxPluginSwitch": 0, 36 "HeadImgFlag": 1, 37 "SnsFlag": 17 38 }, 39 "ChatSet": xxx, 40 "SKey": xxx, 41 "ClientVersion": 369297683, 42 "SystemTime": 1453124908, 43 "GrayScale": 1, 44 "InviteStartCount": 40, 45 "MPSubscribeMsgCount": 2, 46 "MPSubscribeMsgList": [...], 47 "ClickReportInterval": 600000 48 }
這一步中獲取 SyncKey
, User
後面的消息監聽用。
獲取用戶頭像,menthod = 「GET」,帶上cookie和頭部信息
1 head_url = "https://wx2.qq.com"+current_user['HeadImgUrl']
獲取用戶列表 menthod = "POST",帶上cookies
1 user_list_url = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?lang=zh_CN&r={0}&seq=0&skey={1}".format(ctime, skey)
發送消息,menthod = 「POST」,帶上頭部信息,須要json格式化一下
1 msg_url = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?lang=zh_CN&pass_ticket={0}".format( 2 ticket_dict["pass_ticket"])
頭部信息
1 data_dict = { 2 'BaseRequest': { 3 "DeviceID": "e965263748707552", 4 "Sid": ticket_dict.get("wxsid"), 5 "Skey": ticket_dict.get("skey"), 6 "Uin": ticket_dict.get("wxuin"), 7 }, 8 'Msg': { 9 'ClientMsgId': ctime, 10 'LocalID': ctime, 11 'FromUserName': from_user, 12 'ToUserName': to, 13 'Content': content, 14 "Type": 1 15 }, 16 'Scene': 0 17 }
接收信息 GET請求方式,製做心跳包實時
1 sync_url = "https://webpush2.weixin.qq.com/cgi-bin/mmwebwx-bin/synccheck"
頭部信息
1 sync_dict = { 2 "r": ctime, 3 "skey": ticket_dict.get("skey"), 4 "sid": ticket_dict.get("wxsid"), 5 "uin": ticket_dict.get("wxuin"), 6 "deviceid": "e363838562855462", # **** 7 "synckey": sync_data_str 8 }
當有新信息到來時,頭部信息和鏈接,發送POST 請求
1 fetch_msg_url = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid={0}&skey={1}&pass_ticket={2}" \ 2 .format(ticket_dict.get("wxsid"), ticket_dict.get("skey"), ticket_dict.get("pass_ticket")) 3 form_data = { 4 'BaseRequest': { 5 'DeviceID': 'e965263748707552', # **** 6 'Sid': ticket_dict.get("wxsid"), 7 'Skey': ticket_dict.get("skey"), 8 'Uin': ticket_dict.get("wxuin") 9 }, 10 'SyncKey': USER_INIT_DATA['SyncKey'], 11 'rr': str(time.time()) 12 }
最後提取關鍵信息
1 { 2 'BaseResponse': {'ErrMsg': '', 'Ret': 0}, 3 'SyncKey': { 4 'Count': 7, 5 'List': [ 6 {'Val': 636214192, 'Key': 1}, 7 ... 8 ] 9 }, 10 'ContinueFlag': 0, 11 'AddMsgCount': 1, 12 'AddMsgList': [ 13 { 14 'FromUserName': '', 15 'PlayLength': 0, 16 'RecommendInfo': {...}, 17 'Content': "", 18 'StatusNotifyUserName': '', 19 'StatusNotifyCode': 5, 20 'Status': 3, 21 'VoiceLength': 0, 22 'ToUserName': '', 23 'ForwardFlag': 0, 24 'AppMsgType': 0, 25 'AppInfo': {'Type': 0, 'AppID': ''}, 26 'Url': '', 27 'ImgStatus': 1, 28 'MsgType': 51, 29 'ImgHeight': 0, 30 'MediaId': '', 31 'FileName': '', 32 'FileSize': '', 33 ... 34 }, 35 ... 36 ], 37 'ModChatRoomMemberCount': 0, 38 'ModContactList': [], 39 'DelContactList': [], 40 'ModChatRoomMemberList': [], 41 'DelContactCount': 0, 42 ... 43 }
在這個項目中,須要注意cookie的變化和在html配置長輪尋實時監控
over。