Python实例---模拟微信网页登录(day2)

第三步: 实现长轮询访问服务器---day2代码

settings.py

"""
Django settings for weixin project.

Generated by 'django-admin startproject' using Django 2.0.1.

For more information on this file, see
https://docs.djangoproject.com/en/2.0/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.0/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '*g4b=9ct3o#*1pr0o2$h+p$eb!czq!)83u933x8$(n7uj++!f%'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'App.apps.AppConfig',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'weixin.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'weixin.wsgi.application'


# Database
# https://docs.djangoproject.com/en/2.0/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/2.0/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/

STATIC_URL = '/static/'

TEMPLATE_DIRS = (os.path.join(BASE_DIR,  'templates'),)

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)




views.py

from django.shortcuts import render, redirect, HttpResponse
import re
import time
import json
import requests

# Create your views here.


QCODE = None
CURRENT_TIME = None
LOGIN_COOKIE_DICT = {}
TICKET_COOKIE_DICT = {}
TICKET_DICT = {}
TIP = 1  # 解决201后还不停pending的问题...
USER_INIT_DATA = {}
BASE_URL = "http://wx.qq.com"
BASE_SYNC_URL = "https://webpush.weixin.qq.com"

def login(request):
    # 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&_=1486951705941
    base_qode_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&={0}'
    global CURRENT_TIME  # 更改全局变量需要更改添加global
    global QCODE

    CURRENT_TIME = str(time.time())  # 时间戳【返回是float类型,转换为str类型】
    q_code_url = base_qode_url.format(CURRENT_TIME)
    response = requests.get(q_code_url)  # 获取到随记字符串,返回是个response对象
    # code: <Response [200]>
    # type(code):  <class 'requests.models.Response'>
    # code.text : window.QRLogin.code = 200; window.QRLogin.uuid = "gb8OTUPMpA==";
    print('Response对象: ', response, type(response))
    print('Response内容: ', response.text)
    code = re.findall('uuid = "(.*)"', response.text)[0]  # findall返回一个列表,注意空格
    QCODE = code
    print("随记字符:", QCODE)

    return render(request, 'login.html', {"code": QCODE})




def pooling(request):
    # https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=AY0FL0UZwA==&tip=1&r=1700853510&_=1523012536082
    # 201: 扫码,未确认
    # 200: 扫码,确认
    # 408: 等待中...

    global TIP  # 解决201后还不停pending的问题...
    ret = {'status': 408, 'data': None}
    base_login_url = "https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid={0}&tip={1}&r=-1700853510&_={2}"
    login_url = base_login_url.format(QCODE, TIP, CURRENT_TIME)
    response_login = requests.get(login_url)
    print('长轮询URL', login_url)
    print('长轮询状态码以及内容:', response_login.text)

    if 'window.code=201' in response_login.text:
        userAvatar = re.findall("userAvatar = '(.*)';", response_login.text)[0]
        ret['data'] = userAvatar
        ret['status'] = 201
        TIP = 0
    elif 'window.code=200' in response_login.text:
        global BASE_URL
        global BASE_SYNC_URL
        # 用户已经确认后获取Cookie内容
        LOGIN_COOKIE_DICT.update(response_login.cookies.get_dict())
        redirect_url = re.findall('window.redirect_uri="(.*)";', response_login.text)[0]
        if redirect_url.startswith('https://wx2.qq.com'):
            BASE_URL = 'https://wx2.qq.com'
            BASE_SYNC_URL = 'https://webpush.wx2.qq.com'
        else:
            BASE_URL = "http://wx.qq.com"
            BASE_SYNC_URL = "https://webpush.weixin.qq.com"

        # 微信正常的:https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=ATsWUC3qlrRteYUWzz_8hBMH@qrticket_0&uuid=QY2NxTcDcw==&lang=zh_CN&scan=1523018755&fun=new&version=v2&lang=zh_CN
        # 我们获取的:https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=AYTBkpgzEWsIgHOjaQK1tvSs@qrticket_0&uuid=AfxTcp1JXQ==&lang=zh_CN&scan=1523017763
        print('用户确认后获取的URL:', redirect_url)
        redirect_url += '&fun=new&version=v2&lang=zh_CN'
        print('用户确认后改装的跳转URL:', redirect_url)
        # 用户已经确认后获取票据内容
        response_ticket = requests.get(redirect_url, cookies=LOGIN_COOKIE_DICT)
        TICKET_COOKIE_DICT.update(response_ticket.cookies.get_dict())
        '''
            获取的凭据内容:  
                <error>
                    <ret>0</ret>
                    <message></message>
                    <skey>@crypt_ea9ae4c7_090ef27aeb8539e92003afd7658c8f49</skey>
                    <wxsid>dDQOkKqhrvLnFm1o</wxsid>
                    <wxuin>1289256384</wxuin>
                    <pass_ticket>YWQzZ0sOdkr1Eq%2BExvGbyfBq2mbIwksh%2BipMvTyNVUxBwnfqhXKn4wTBPMhpHh%2B%2F</pass_ticket>
                    <isgrayscale>1</isgrayscale>
                </error>
        '''
        print('获取的凭据内容: ', response_ticket.text)  # 利用这个凭据进行下一次的数据访问

        '''
        格式化输出凭据内容
            ret 0
            message None
            skey @crypt_29bab75e_996fb921b5a09570d7793598f2e213dc
            wxsid g++XySA396Bnwljx
            wxuin 1600696821
            pass_ticket fbBFzsSbFhlD1kpNMJ7f39vrBwGqZTezGU7%2FpDZS1rzAueLDfKw%2FfoWp8sT8MdP6
            isgrayscale 1
        '''

        from bs4 import BeautifulSoup
        soup = BeautifulSoup(response_ticket.text, 'html.parser')
        for tag in soup.find():  # 格式化打印XML内容
            TICKET_DICT[tag.name] = tag.string  # 字典内部元素修改不需要global,重新赋值需要global
        ret['status'] = 200  # 解决我们后台的报错问题,因为前台一直在pending获取数据根后台我们拿到的数据不一致
    return HttpResponse(json.dumps(ret))


url.py

from django.contrib import admin
from django.urls import path
from App import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', views.login),
    path('polling/', views.pooling),
]

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WeChat By FTL1012</title>
</head>
<body>
    <div style="width: 300px; margin: 0 auto ">
        <img id="qcode" style="width: 300px; height: 300px;" src="https://login.weixin.qq.com/qrcode/{{ code }}"/>
    </div>
</body>

<script src="/static/jquery-3.2.1.min.js"></script>
<script>
     $(function () {
            polling();
        });
    // 发送长轮询
    function polling() {
        $.ajax({
            url: '/polling/',
            type: "GET",
            dataType: 'json',
            success: function (args) {
                if(args.status == 408){
                    polling();
                }else if(args.status == 201){
                    // 已经扫描,但未确认; --》获取微信用户的头像信息,继续发长轮询等待确认
                    $("#qcode").attr('src', args.data);
                    polling();
                }else{
                    // 此时手机端已经确认了信息,跳转主页面
                    location.href = '/index/'
                }

            }
        })
    }

</script>
</html>

页面请求:

http://127.0.0.1:8000/login/(扫码后)

image

长轮询的状态码408

image

转载于:https://www.cnblogs.com/ftl1012/p/10372448.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python可以通过企业微信开放的接口实现消息推送功能。 首先,需要在企业微信后台注册应用并获取应用的相关参数,比如应用ID、应用密钥等。然后,使用Python的requests库发送HTTP请求来调用企业微信提供的消息推送接口。 可以使用以下代码示例通过企业微信发送文本消息: ```python import requests import json # 获取企业微信应用的相关信息 corpid = '企业ID' corpsecret = '应用密钥' agentid = '应用ID' # 获取access_token url = f'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpid}&corpsecret={corpsecret}' response = requests.get(url) access_token = json.loads(response.text)['access_token'] # 构造消息内容 message = { 'touser': '@all', # 发送给所有用户 'msgtype': 'text', # 发送文本消息 'agentid': agentid, 'text': { 'content': '这是一条测试消息' # 消息内容 } } # 发送消息 send_url = f'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={access_token}' response = requests.post(send_url, data=json.dumps(message)) result = json.loads(response.text) if result['errcode'] == 0: print('消息发送成功') else: print('消息发送失败') ``` 上述代码首先获取了access_token,然后构造了一个文本消息的消息体,包含消息内容和发送对象(这里使用@all表示发送给所有用户)。最后,通过POST请求将消息发送给企业微信。 在实际使用中,可以根据需要自定义消息内容、发送对象等相关参数。此外,企业微信还支持推送图片、文件、图文等多种类型的消息,开发者可以按需进行配置。 以上是使用Python实现通过企业微信进行消息推送的简单示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值