某了么数据获取脚本

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


![[渗透利器]某大佬公开自用红队渗透工具](https://img-blog.csdnimg.cn/img_convert/14ef6e451886efc67e2988a0e73c7834.png)

![[ 项目 ] tcmalloc简化版—高并发内存池](https://img-blog.csdnimg.cn/direct/0ad5d1a5f91f44b2b227ddef3abd3f95.png)














