某了么数据获取脚本

某了么数据获取脚本

在这里插入图片描述

这段代码定义了一个名为 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)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2023陇剑杯-流量分析篇-wp

1.ez_web Q1:服务器自带的后门文件是什么? 常用http过滤命令:http.request.full_urihttp.request.methodPOST 查看第一个POST请求,发现关键点file_put_contents(备注:file_put_contents内置函数,用于将字…

2×24.5W、内置 DSP、低失真、高信噪比、I2S 输入 D 类音频功率放大器,完美替换TPA5805,晶豪,致盛,

ANT3825 是一款高集成度、高效率的双通道数字 输入功放。供电电压范围在 5V~18V,数字接口 电源支持 3.3V 或 1.8V。双通道 BTL 模式下输出 功率可以到 224.5W(4Ω,16V,THDN1%), 单通道 PBTL 模式下可以输出 37W&#x…

Rust里的Fn/FnMut/FnOnce和闭包匿名函数关系

闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使…

武汉星起航:策略升级,亚马逊平台销售额持续增长显实力

武汉星起航电子商务有限公司,一家致力于跨境电商领域的企业,于2023年10月30日在上海股权托管交易中心成功挂牌展示,这一里程碑事件标志着公司正式踏入资本市场,开启了新的发展篇章。公司董事长张振邦在接受【第一财经】采访时表示…

Java_从入门到JavaEE_09

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

开源15T tokens!HuggingFace放出规模最大、质量最高预训练数据集 | 最新快讯

新智元报道 编辑:LRS FineWeb 是一个高质量的预训练数据集,包含 15T 个 tokens,主要包含英语文本;消融实验证明了 FineWeb 数据集的质量要高于其他开源数据集;数据清洗脚本也已开源。 Meta 最近开源的 Llama 3 模型再次…

vulnhub靶场之FunBox-2

一.环境搭建 1.靶场描述 Boot2Root ! This can be a real life scenario if rockies becomes admins. Easy going in round about 15 mins. Bit more, if you are find and stuck in the rabbit-hole first. This VM is created/tested with Virtualbox. Maybe it works with…

C#编程模式之外观模式

创作背景:给位伙伴,五一小长假结束,我们继续对C#编程之路进行探索。本文将继续编程模式的研究,主要介绍外观模式。外观模式也称为门面模式,是一种结构型设计模式,它的目的是为子系统中的一组接口提供一个统…

【隧道篇 / WAN优化】(7.4) ❀ 01. 启动WAN优化 ❀ FortiGate 防火墙

【简介】几乎所有的人都知道,防火墙自带的硬盘是用来保存日志,以方便在出现问题时能找到原因。但是很少的人知道,防火墙自带的硬盘其实还有另一个功能,那就是用于WAN优化。 防火墙自带的硬盘 在FortiGate防火墙A、B、C、D系列&…

oracle 8i系统检查

oracle 8i系统检查 set echo on spool d:\bk\1.txt select sysdate from dual; --版本信息 select * from v$version; --安装的产品 col PARAMETER for a50; col value for a10; select * from v$option order by 2; --用户信息 set linesize 100 set pagesize 100 COL USE…

景源畅信:抖音运营做什么工作内容?

在如今这个信息爆炸的时代,抖音已经成为了人们生活中不可或缺的一部分。无论是消磨时间、获取信息还是展示自我,抖音都扮演着重要的角色。那么,作为抖音运营,他们需要做些什么呢? 一、内容策划与制作 抖音运营的首要任务就是内容…

爬虫Python库Requests

一、介绍 Requests 是一个强大的 Python 库,用于发送 HTTP 请求。它使得与 RESTful API 进行交互变得非常简单。Requests 可以通过 GET、POST、PUT、DELETE 等方法发送各种类型的请求,并且支持自定义 HTTP 头、请求参数、数据、cookies 等。 使用 Requ…

MCM箱模型实践技术应用与O3形成途径、生成潜势、敏感性分析

目前,大气臭氧污染成为我国“十四五”期间亟待解决的环境问题。臭氧污染不仅对气候有重要影响,而且对人体健康、植物生长均有严重损害。为了高效、精准地治理区域大气臭氧污染,需要了解臭氧生成的主要途径及其前体物。OBM箱模型可用于模拟光化…

武汉星起航:跨境电商领域国际竞争力卓越,引领行业再上新台阶

在全球化浪潮的推动下,跨境电商行业日益成为各国经济交流与合作的重要桥梁。武汉星起航电子商务有限公司,作为跨境电商领域的佼佼者,凭借其深厚的行业经验和前瞻性的战略视野,在国际市场上展现出强大的竞争力,为行业的…

优化理论复习——(二)

本篇主要介绍一下LP问题及其相关的解法和示例,主要是记住相关的方法和结论即可,不要求证明。 方法主要是单纯形法,同时对于初始基可行解确定方面使用了大M法和二阶段法。主体都是关于单纯形法的。 首先认识一下线性规划的一般问题形式&#x…

报错,java: 程序包sun.misc不存在

错误描述 down下来一个项目,编译的时候报错,提示sun.misc包不存在,通过百度得知,原来这是jdk8中的jar包,在后来的版本中被移除了(我用的jdk11,没有这个包) 结局方法 1.更换jdk版本&…

知识库工具:付费的HelpLook AI知识库比免费的牵牛易帮好在哪里

在知识管理的领域中,选择合适的知识库工具对于企业来说很重要。市面上有很多知识库产品,有付费的和免费的,但是还是有很多企业会选择使用付费的,而不是免费的。这是为什么呢?这就是今天要探讨的问题,下面就…

vs配置cplex12.10

1.创建c空项目 2.修改运行环境 为release以及x64 3.创建cpp文件 4.鼠标右键点击项目中的属性 5.点击c/c,点击第一项常规,配置附加库目录 5.添加文件索引,主要用于把路径导进来 6.这一步要添加的目录与你安装的cplex的目录有关系 F:\program…

idea2023.2.5的控制台动态配置当前环境

一、idea2023.2.5的控制台动态配置当前环境 1.1、idea版本 1.2、配置方式 1.2.1、方式一 1.2.2、方式二 1.3、参考 https://blog.csdn.net/xiaoheihai666/article/details/127757658

举个栗子!Minitab 技巧(8):用 PLS 偏最小二乘分析大豆脂肪影响因素

在上一个 🌰 中,我们用 Minitab 最小二乘法验证了两个变量(单位桶数与运输时间)之间是否存在某种关系。那么,在更复杂的场景中,如何验证一组预测变量和一个或多个连续响应变量之间的关系? 假设…