【问题标题】:Python Multi Requests URLsPython 多请求 URL
【发布时间】:2018-09-24 09:39:05
【问题描述】:

大家好, 我是 python 新手(我刚开始不到 2 周) 所以我需要一些建议和技巧:p

获取大约 1500 个 api 请求的最快和最有效的方法是什么?

  1. 使用异步函数执行它们并返回以获取 结果 ?
  2. 将它们分成 300 个 url 的列表,并将每个 线程内的列表将在异步循环内执行它们?
  3. 执行与第二个建议相同的操作,但使用进程 而不是线程?

目前它对我有用,但执行 1400 个 api 请求需要 8 秒,但是当我尝试没有线程的单个请求时需要 9 秒 我做错了什么??!

获取一个 URL(我尝试将 Session 作为参数传递,但在达到 700 个请求时出现错误)

async def fetch_one(url):
    async with curio_http.ClientSession() as session:
        response = await session.get(url)
        content =  await response.json()
        return  content

在异步循环中获取 URL 列表

async def fetchMultiURLs(url_list):
        tasks = []
        responses = []
        for url in url_list:
            task = await curio.spawn(fetch_one(url))
            tasks.append(task)

        for task in tasks:
            content = await task.join()
            responses.append(content)
            print(content)

创建线程并在其中放入异步循环,具体取决于 URLs / X URL by Loop

例如 MultiFetch(URLS[600],200) 将创建 3 个线程,这些线程将按线程和异步方式调用 200 个请求

def MultiFetch(URLS,X):
    MyThreadsList = []
    MyThreadsResults = []
    N_Threads = (lambda x:  int (x/X) if (x % X == 0) else int(x/X)+1) (len(URLS))
    for i in range( N_Threads  ): # will iterate X = ListSize / X
              MyThreadsList.append( Thread(  target = curio.run , args = (fetchMultiURLs( (URLS[ i*X:(X*i+X)]) )  ,)    )  )
              MyThreadsList[i].start()
    for i in range( N_Threads  ):
              MyThreadsResults.append(MyThreadsList[i].join())
    return MyThreadsResults

【问题讨论】:

  • 许多线程 + 队列是我所知道的最快的。 (一小时内 300 万个 http 请求 + 扫描)
  • 非常感谢你的回答 :) 但这不是最有效的方法,因为在 Python 中,GIL 问题对这种请求的速度太慢了:p(我试过你的想法,它需要 11 秒才能完成做)

标签: python python-3.x api curl async-await


【解决方案1】:

我终于找到了解决方案 :) 获取 1400 个网址需要 2.2 秒

我使用了 3ed 建议(进程内的异步循环)

# 获取 1 个网址

async def fetch_one(url):
    async with curio_http.ClientSession() as session:
        response = await session.get(url)
        content =  await response.json()
        return  content

# 获取 X 个网址 async def fetchMultiURLs(url_list): 任务= [] 回复 = [] 对于 url_list 中的 url: 任务 = 等待 curio.spawn(fetch_one(url)) tasks.append(task)

        for task in tasks:
            content = await task.join()
            responses.append(content)
        return responses

# 我试图用 lambda 代替这个函数,但它不起作用

def RuningCurio(X):
    return curio.run(fetchMultiURLs(X))

# 根据 URL 创建进程和异步循环 / X URL by Loop

#在我的情况下(我使用 VPS)单个进程可以在不到 1 秒的时间内轻松获取 700 个链接,所以不要在这个数量的 url 下创建 multiProcesses(只需使用 fetchMultiURLs 函数)

 def MultiFetch(URLS,X):
    MyListofLists = []
    LengthURLs = len(URLS)
    N_Process = int (LengthURLs / X) if ( LengthURLs % X == 0) else int( LengthURLs / X) + 1
    for i in range( N_Process  ): # Create a list of lists (  [ [1,2,3],[4,5,6],[7,8,9] ] )
        MyListofLists.append(URLS[ i*X:(X*i+X)])
    P = Pool( N_Process) 
    return  P.map( RuningCurio ,MyListofLists)

# 我在 1.1 秒内获取 2100 个 url 我希望这个解决方案对你们有帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-19
    • 2021-09-25
    • 1970-01-01
    • 1970-01-01
    • 2019-09-30
    • 1970-01-01
    • 2021-03-28
    • 1970-01-01
    相关资源
    最近更新 更多