遍历数据库表作为参数,多线程请求接口数据

文章讲述了如何通过Python实现高效并发处理,使用线程池、网络请求库requests、数据库连接和SQLAlchemy,通过重试机制处理接口查询,并记录进度,以提高数据入库速度和控制并发量。
摘要由CSDN通过智能技术生成
title: 背景
通过用户表的用户id获取接口数据,接口只提供了根据id查询的功能
没有使用async的原因:不能控制并发量, 且速度不够快, 速度的瓶颈在于访问接口, 访问速度也不能太快

1、导入的包

import json # 处理接口返回结果
import time # 生成接口查询参数(日期)
from concurrent.futures import ThreadPoolExecutor, as_completed # 线程池
import requests # 网络请求
import pandas as pd # response数据处理
from sqlalchemy import create_engine # 连接数据库
from retry import retry # 出错重连
from tqdm import tqdm # 进度条

2、网络请求部分

url = "http://******/api/query"
params = {
    "client": "***"
}
headers = {
    "authorization": "******"
}

@retry(tries=2, delay=15) # 失败重试两次 间隔15s
def do_query(user_id):
    payload = { # 组成请求体
        "UID": user_id,
        "DATE": time.strftime('%Y-%m-%d')
    }
    response = requests.request("POST", url, json=payload, headers=headers, params=params).text # 发送请求, 获取response
    item_data = json.loads(response)["DATA"] # 将str类型的response转为json类型, 并获取DATA数据部分(jsonarray格式)
    return pd.json_normalize(item_data) # jsonarray转为dataframe

3、创建数据库连接

@retry(tries=2, delay=15)
def get_engine():
    username = ''
    password = ''
    host = ''
    port = ''
    return create_engine(f'***://{username}:{password}@{host}:{port}')

4、数据入库

def to_db(user_id):
    item_df = do_query(user_id) # 通过用户id作为参数调用do_query查询接口
    item_df['UID'] = user_id
    item_df['DATE'] = time.strftime('%Y-%m-%d') # 请求参数也需要存到库表中
    return item_df.to_sql(name='***', schema='***', if_exists='append', index=False, con=engine) # 通过df.to_sql入库

5、主程序

if __name__ == '__main__':
    engine = get_engine() # 调用方法获取数据库连接
    sql = '''
        查询查询用户id
    '''
    df = pd.read_sql(sql=sql, con=engine) # 执行查询用户id
    with (
        tqdm(total=df.shape[0], unit='row', desc='Processing') as pbar, # 定义进度条
        ThreadPoolExecutor(max_workers=20) as executor # 创建线程池, 最大20线程
    ):
        obj_list = []
        for index, row in df.iterrows(): # 遍历用户id
            obj = executor.submit(to_db, row.values[0]) # 线程调用to_db
            obj_list.append(obj) # 保存future

        for future in as_completed(obj_list): # 遍历已完成线程的future
            pbar.update(1) # 进度条+1
    print('Done!')

6、输出日志

Processing:  40%|███▉      | 4000/10000 [2:30:00<2:35:20,  1.28row/s]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值