某了么数据获取脚本

news2024/9/22 13:34:24

某了么数据获取脚本

在这里插入图片描述

这段代码定义了一个名为 ElemeH5 的类,继承自 Base 类,用于处理与饿了么平台的API交互。该类包括了多种方法来进行网络请求、数据处理和API接口的动态生成。以下是对主要组成部分的详细解析:

类属性定义:

  • func_template:字符串,用作动态生成函数的模板。

  • appKey 和 secret:API使用的密钥和安全码。

  • platform 和 sandbox:用于定义API请求的平台和是否是沙箱环境。

  • domain:API请求的基础域名。

构造函数 (init):

初始化基类并设置函数模板。

方法定义:

  • onekeylogin():

发起POST请求到指定的URL,尝试一键登录功能。

  • h5_token和 umidToken (使用 @property 装饰器):

这两个属性方法分别用来获取会话中的token和生成umidToken,umidToken是根据当前时间和随机数生成的。

  • sign():

生成请求的签名,采用MD5加密方法,确保请求的安全性。

  • _execute():

执行实际的HTTP请求。根据传入的请求参数,进行GET或POST请求,并处理返回结果。

  • render_template():

用于根据传入的参数动态生成函数的字符串。

  • urlCreateFunc():

动态解析API链接并生成相应的函数,增强了代码的灵活性和可维护性。该方法还将生成的函数代码追加到当前文件。

  • createTypes():

动态创建类型定义,用于强类型语言的接口定义,便于后续维护和类型检查。

  • searchPoiNearby() 和 reverseGeoCoding():

特定的业务方法,用于调用地理位置相关的API,如搜索附近的地点和进行地理位置逆编码。

-MtopVenusShopresourceserviceGetshopresource() 和 `MtopAlscWamaiStoreDetailBusinessTabPhone():

这两个方法分别封装了对特定API的调用,包括参数的准备、请求的发起和响应的处理。

总结:

这个类是一个高度封装的API客户端,利用面向对象的方法管理饿了么平台的多个API接口。通过动态函数生成和类型定义,极大地提高了代码的可维护性和可扩展性。此外,它还包括了错误处理和日志记录功能,这有助于问题追踪和调试。整体上,这是一个典型的用于商业API交互的工具类设计。


from ..types import taobao, eleme
from ..base import Base
from pathlib import Path
import re
from urllib.parse import urlparse, parse_qsl, quote
from typing import Any, Dict, List
import json
from collections import OrderedDict
import time
import random
import hashlib
import datetime

class ElemeH5(Base):

    func_template: str
    appKey: str = '12574478'
    secret: str = ''
    platform: str = ''
    sandbox: bool = False
    domain: str = 'https://waimai-guide.ele.me'

    def __init__(self) -> None:
        super().__init__()

        self.func_template = ''
    def onekeylogin(self):
        res = self.post('https://www.cmpassport.com/h5/onekeylogin/getNewTelecomPhonescrip?_bx-v=2.5.3',json={
            'businessType': '8',
            'encrypted': '',
            'reqdata': '',
        })
    @property
    def h5_token(self):
        token = self.cookies.get('_m_h5_tk', domain='', default='')
        if not token is None and len(token) > 32:
            return token[0:32]

        self.logger.error('从cookie获取的token为空')
        return ''

    @property
    def umidToken(self):
        '''获取umidToken'''
        return 'C' + str(int(time.time() * 1000)) + \
            ''.join(str(random.choice(range(10))) for _ in range(11)) + \
            str(int(time.time() * 1000)) + \
            ''.join(str(random.choice(range(10))) for _ in range(3))

    def sign(self, token: str, t: str, appkey: str, data: str, binary: bool = False):
        '''sign签名加密方式采用淘宝H5网页的加密流程
        data传递使用的是字符串,一是为了少加密一次,二是为了直接说明这个要转成json字符串,还需要去掉空格'''

        sign_func = 'digest' if binary else 'hexdigest'
        sign_str = f'{token}&{t}&{appkey}&{data}'
        self.logger.debug('sign签名字符串:{signStr}',signStr=sign_str)
        return getattr(hashlib.md5(sign_str.encode('utf-8')),sign_func)()

    def _execute(self, request_options: Any):
        '''解析请求参数并将参数进行加密'''
        method = request_options.get('method')
        if method.upper() == 'GET':
            payload = request_options.get('params')
        else:
            payload = request_options.get('data')

        if payload is None:
            raise Exception('提交的数据不能为None')

        timestamp = str(int(datetime.datetime.now().timestamp() * 1000))
        appKey = payload.get('appKey', self.appKey)
        payload.update({
            't': timestamp,
            'type': 'json',
            'dataType': 'json',
        })
        payloadData = payload.get('data', {})
        dataStr = json.dumps(payloadData, separators=(',', ':'))
        payload.update({
            'sign': self.sign(self.h5_token, timestamp, appKey, dataStr),
            'data': dataStr
        })
        self.logger.debug('{method}请求:{payload}', payload=payload, method=method.upper())
        res = self.request(**request_options)
        resj: taobao.ApiRes = res.json()

        if res.status_code != 200:
            self.logger.error('API请求失败:{rtxt}', rtxt=res.text)
        else:
            ret = resj.get('ret')
            retMsg = ret[0]
            if 'SUCCESS' not in retMsg.upper():
                self.logger.error('API请求失败:{ret}', ret=ret)

        return (resj, res)

    def render_template(self, kwargs: Any):
        return self.func_template.format(**kwargs)

    def urlCreateFunc(self, api: str, method: str = 'get', func_name: str | None = None, desc: str = '', formdata: Any = {}):
        '''解析API链接为函数'''
        urlObj = urlparse(api)

        queryParams = dict(parse_qsl(urlObj.query))
        [platform, service_name, version, SV] = urlObj.path.strip('/').split('/')

        func_name = func_name if func_name else ''.join([i.capitalize() for i in service_name.split('.')])
        if hasattr(self, func_name):
            return

        for key in queryParams:
            val = queryParams[key]
            if len(re.findall(r'\{.*?\}|\[.*?\]', val)) > 0:
                queryParams[key] = json.loads(val)

        with open(__file__, 'a+', encoding='utf-8') as f:
            funcStr = self.render_template({
                'payload': queryParams,
                'hostname': urlObj.hostname,
                'scheme': urlObj.scheme,
                'path': urlObj.path,
                'params': urlObj.params,
                'func_name': func_name,
                'service_name': service_name,
                'platform': platform,
                'version': version,
                'desc': desc if desc else f'{service_name}函数',
                'method': method,
                'formdata': formdata,
            })
            f.write(funcStr)

    def createTypes(self, typeName: str, data: Dict[str, Any]):
        '''创建类型'''
        if not data:
            return

        formatter = '''

class {typeName}(TypedDict):
{fieldStr}
'''
        fieldStr = ''
        for key in data:
            val = data[key]
            if type(val) is str:
                fieldStr += f'    {key}: str\n'
            elif type(val) is list:
                fieldStr += f'    {key}: List'
            elif type(val) is dict:
                fieldStr += f'    {key}: Dict'
            elif type(val) is int:
                fieldStr += f'    {key}: int'
            elif type(val) is float:
                fieldStr += f'    {key}: float'
            elif type(val) is bool:
                fieldStr += f'    {key}: bool'
            else:
                fieldStr += f'    {key}: Any'

        nowFile = Path(__file__)
        typeFile = nowFile.parent.parent.joinpath('types/taobao.py')
        with open(typeFile, 'a+', encoding='utf-8') as f:
            typeStr = formatter.format(**{
                'typeName': typeName,
                'fieldStr': fieldStr,
            })
            f.write(typeStr)

    def searchPoiNearby(self, keyword: str, latitude: float, longitue: float, offset: int = 0, limit: int = 20):
        '''搜索附近地址'''
        url = 'https://h5.ele.me/restapi/bgs/poi/search_poi_nearby'
        res = self.get(url, params={
            'keyword': quote(keyword),
            'offset': offset,
            'limit': limit,
            'latitude': latitude,
            'longitude': longitue,
        })
        resj: List[eleme.SearchPoiNearbyRes] = res.json()
        return resj

    def reverseGeoCoding(self, longitude: float, latitude: float):
        '''重新定位'''
        url = 'https://h5.ele.me/restapi/bgs/poi/reverse_geo_coding'
        res = self.get(url,params={
            'latitude': latitude,
            'longitude': longitude
        })
        resj: eleme.reverseGeoCodingRes = res.json()
        return resj


    def MtopVenusShopresourceserviceGetshopresource(self, data: Any = {}):
        """mtop.venus.shopresourceservice.getshopresource函数"""

        method = 'get'
        params = {'jsv': '2.7.1', 'appKey': '12574478', 't': '1701086935133', 'sign': '21f5d98752b48dcb5e1a2d59eacb6529', 'api': 'mtop.venus.ShopResourceService.getShopResource', 'v': '1.4', 'type': 'originaljson', 'dataType': 'json', 'ecode': '1', 'SV': '5.0', 'data': {'lat': 30.452488, 'lng': 114.319347, 'from': 'native', 'bizChannel': 'mobile.default.default', 'deviceId': '500B511F28CE4C29996AC6EC4EDCA549|1701086828893', 'livingShowChannel': 'other', 'channel': 'PC', 'subChannel': 'ELE_APP', 'store_id': '1102570163', 'ele_id': 'E14249670395629855804', 'itemId': '', 'scentExtend': '{"businessComeFrom":""}'}, 'bx_et': 'dxvJc1wTGq0k4LyJbzhmY30xbsomsLKrMU-_KwbuOELvzGCBZemyMpLGu6AuE62dAeYRKa6hFwZplH1WK07hpvLVueCE4wbCJexBZmDiI3-PL9_KSADgxFBFd8rH-Jxy49WQmyGMG3yp7A4VU9PjobZ_QdJhVfI_sbXxGKsRwNehkJeKxgCR53_YurWNfdvOWeaGWMVSDmFUT_sqdoAHc'}
        url = 'https://waimai-guide.ele.me/h5/mtop.venus.shopresourceservice.getshopresource/1.4/5.0/'
        if data:
            params['data'].update(data)

        request_options = OrderedDict()
        request_options.setdefault('method', method)
        request_options.setdefault('url', url)
        if method.upper() == 'GET':
            request_options.setdefault('params', params)
        else:
            request_options.setdefault('data', params)

        return self._execute(request_options)

    def MtopAlscWamaiStoreDetailBusinessTabPhone(self, data: Any = {}):
        """mtop.alsc.wamai.store.detail.business.tab.phone函数"""

        method = 'POST'
        params = {''}
        url = 'https://waimai-guide.ele.me/h5/mtop.alsc.wamai.store.detail.business.tab.phone/1.0/5.0/'
        payload = params.get('data', {'eleStoreId': 'E6480404258831972301'})
        if data:
            payload.update(data)

        request_options = OrderedDict()
        request_options.setdefault('method', method)
        request_options.setdefault('url', url)
        request_options.setdefault('params', params)
        if method.upper() == 'POST':
            request_options.setdefault('data', payload)

        return self._execute(request_options)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1645633.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MQ如何保证可靠性

📝个人主页:五敷有你 🔥系列专栏:MQ ⛺️稳中求进,晒太阳 消息到达MQ以后,如果MQ不能及时保存,也会导致消息丢失,所以MQ的可靠性也非常重要。 2.数据持久化 为了提高性能&a…

【C语言】文件操作(万字解读超详细解析)

最好的时光,在路上;最好的生活,在别处。独自上路去看看这个世界,你终将与最好的自己相遇。💓💓💓 目录 • ✨说在前面 🍋知识点一:什么是文件? • 🌰1.程序…

[渗透利器]某大佬公开自用红队渗透工具

前言 看到群里大佬发的文章,公开了自用的工具,前来拜膜一下。 使用方式 该工具首先需要初始化数据库,Windows推荐使用PHP Study,搭建更方便。 修改默认root密码后新建数据库,账号密码随便填,公网环境注意…

表空间的概述

目录 表空间的属性 表空间的类型 永久性表空间(PermanentTablespace) 临时表空间(Temp Tablespace ) 撤销表空间(Undo Tablespace) 大文件表空间(BigfileTablespace) 表空间的状态 联机状态(Online) 读写状态(Read Write) 只读状态(Read) 脱机状态(Offline) Oracle从…

[ 项目 ] tcmalloc简化版—高并发内存池

目录 前言 基本介绍 高并发 内存池 定长内存池 基本介绍 框架设计 具体实现 性能测试 整体框架介绍 申请内存过程 threadcache 1.基本介绍 2.具体实现 centralcache 1.基本介绍 2.具体实现 pagecache 1.基本介绍 2.具体实现 申请内存连通 释放内存过…

百科词条创建机构有哪些?

在互联网时代,百度百科作为我国最大的中文百科全书,已经成为人们获取知识、查询信息的重要途径。随着百度百科影响力的不断扩大,越来越多的人和企业试图通过创建企业词条来提升自身知名度,企业和个人为了在百度百科上占据一席之地…

Java_从入门到JavaEE_09

一、构造方法/构造器 含义:和new一起是创建对象的功能 特点: 与类名相同的方法没有返回项 注意: 当类中没有写构造方法时,系统会默认添加无参构造(无参数的构造方法)构造方法可以重载的 有参构造好处&…

Linux 第二十章

🐶博主主页:ᰔᩚ. 一怀明月ꦿ ❤️‍🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C,linux 🔥座右铭:“不要等到什么都没有了…

Transformer详解:从放弃到入门(一)

Transformer由论文《Attention is All You Need》提出,是一种用于自然语言处理(NLP)和其他序列到序列(sequence-to-sequence)任务的深度学习模型架构,在自然语言处理领域获得了巨大的成功,在这个…

自动化运维工具---Ansible

一 Puppet Puppet是历史悠久的运维工具之一。它是一种基础架构即代码(laC)工具,使用户可以定义其基础 架构所需的状态,并使系统自动化以实现相同状态。 Puppet可监视用户的所有系统,并防止任何偏离已定义状态的情况。从简单的工作流程自动…

数据仓库基础理论(学习笔记)

数据仓库基础理论 1.数据仓库概念 2.数据仓库为何而来 3.数据仓库主要特征 4.OLTP、OLAP系统 5.数据仓库与数据库的区别 6.数据仓库与数据集市的区别 7.数据仓库分层架构 7.1为什么要分层? 8.ETL、ELT

NFS共享存储服务配置实践

一、NFS 1.NFS定义 NFS(Network File System)网络文件服务:基于TCP/IP传输的网络文件系统协议,NFS服务的实现依赖于RPC(Remote Process Call)远端过程调用:通过使用NFS协议,客户机…

ICode国际青少年编程竞赛- Python-1级训练场-变量入门

ICode国际青少年编程竞赛- Python-1级训练场-变量入门 1、 a 4 Dev.turnRight() Dev.step(a)2、 a 4 Spaceship.step(a) Dev.step(a)3、 a 4 Dev.step(a) Dev.turnLeft() Dev.step(a)4、 a 5 Dev.step(a) Spaceship.step(a) Dev.step(a)5、 a 3 Dev.step(a) Dev.tur…

C语言写的LLM训练

特斯拉前 AI 总监、OpenAI 创始团队成员 Andrej Karpathy 用 C 代码完成了 GPT-2 大模型训练过程:karpathy/llm.c: LLM training in simple, raw C/CUDA (github.com) 下载源码 git clone --recursive https://github.com/karpathy/llm.c.git下载模型 从HF-Mirro…

Burp和Proxifier抓包微信小程序

1、Burp设置代理 2、浏览器下载证书 3、安装证书 4、Proxifier设置代理 5、Proxifier设置Proxification Rule 6、Burp查看抓包数据 打开一个小程序,可以看到WeChatAppEx的流量先经过Proxifier,再经过127.0.0.1:8080到Burp

基于现有语言大模型,定制“人人AI气象”公众号天气助手

最近,月之暗面的Kimi大模型非常受欢迎,尝试用了moonshot(128K)基座模型,通过调用各种公开渠道的API,简易实现了一个天气助手,可以回答天气相关的基础概念、原理、应用等方面的问题,同时也可调用多个插件获取…

音频可视化:原生音频API为前端带来的全新可能!

音频API是一组提供给网页开发者的接口,允许他们直接在浏览器中处理音频内容。这些API使得在不依赖任何外部插件的情况下操作和控制音频成为可能。 Web Audio API 可以进行音频的播放、处理、合成以及分析等操作。借助于这些工具,开发者可以实现自定义的音…

MoonBit 开源之夏重磅来袭!12000元奖金等你来拿!

宣讲视频 MoonBit 开源之夏宣讲视频 关于我们 开源之夏 「开源之夏 (OSPP)」是中科院软件所「开源软件供应链点亮计划」指导下的系列暑期活动,旨在鼓励在校学生积极参与开源软件的开发维护,培养和发掘更多优秀的开发者,促进优秀开源软件社区…

JavaScript中Math函数与舍入

立方根 console.log(Math.sqrt(25)); //数学方式25平方根 console.log(25 ** (1 / 2)); //25的0.5次方 console.log(8 ** (1 / 3)); //8的1/3次方计算最大最小值 console.log(Math.max(1, 5, 88, 22, 132)); //返回最大值 console.log(Math.max(1, 5, 88, 22, 132)); //…

【C语言】高质量选择题

目录 题目一: 题目二: 题目三: 题目四: 题目五: 题目六: 题目七: 题目八: 题目九: 题目十: 题目十一: 题目十二: 题目十…