V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
gzldc
V2EX  ›  Python

如何使用 Python 最快实现 1w 个 http 请求

  •  
  •   gzldc · 44 天前 · 4678 次点击
    这是一个创建于 44 天前的主题,其中的信息可能已经有所发展或是发生改变。

    本地有一个 1w 行的 txt 文件 每一行都是单独的 payload 。要求是请求同一个 url 使用每一行 payload ,如何能做到最快。不处理响应的 respon 只要最快

    补充一下:我刚接触 python 使用 aiohttp 不知道哪里有问题一秒才 10 个请求。。。

    53 条回复    2024-03-21 11:48:38 +08:00
    Puteulanus
        1
    Puteulanus  
       44 天前
    CC 攻击的脚本?
    tool2d
        2
    tool2d  
       44 天前
    异步请求可以很快,同步要等着上一条返回,肯定是慢的。
    gzldc
        3
    gzldc  
    OP
       44 天前
    @Puteulanus 不是,是一个小网站的秒杀活动
    tool2d
        4
    tool2d  
       44 天前
    又查了一下,好像 aiohttp 就是异步请求的库?那可能是服务器的问题了。
    infun
        5
    infun  
       44 天前
    好歹。。。贴代码吧
    molika
        6
    molika  
       44 天前
    asyncio.gather
    deplives
        7
    deplives  
       44 天前   ❤️ 2
    你需要一个异步 io 的库,或者随便自己写一个比如
    https://gist.github.com/deplives/4b2d09421c5d0ee4aba75c69a5b9b070

    本地实测请求 https://httpbin.org/status/200 1000 次只需要 2s
    acidsweet
        8
    acidsweet  
       44 天前
    除了网络以外,将 py 编译成 cpython 也可以提高效率应该
    gzldc
        9
    gzldc  
    OP
       44 天前 via iPhone
    @tool2d 不是我觉得是我写的代码有问题。我其实不需要 response
    gzldc
        10
    gzldc  
    OP
       44 天前 via iPhone
    @infun 我代码很烂 就是普通请求。确实特别慢
    gzldc
        11
    gzldc  
    OP
       44 天前 via iPhone
    @deplives 感谢我去看看
    ospider
        12
    ospider  
       44 天前
    想问题的方向错了,人家小网站,你这不就是 DOS 攻击么,发得越快,崩得越快
    tomczhen
        13
    tomczhen  
       44 天前
    不需要处理响应,直接用一些抓包工具重放不就好了。
    gzldc
        14
    gzldc  
    OP
       44 天前 via iPhone
    @ospider 网站响应倒都是正常的 抗击打能力不错。只是我这并发写得不行
    gzldc
        15
    gzldc  
    OP
       44 天前 via iPhone
    @tomczhen 有推荐的工具吗
    1iuh
        16
    1iuh  
       44 天前
    不响应, 代码里面做了什么 io 操作吗? 需求描述的不清楚。
    1iuh
        17
    1iuh  
       44 天前
    哦,是我搞错了, 你是要发 1W 个 http 请求。
    Maboroshii
        18
    Maboroshii  
       44 天前
    换 nodejs ! python 就别干这种活了
    None123
        19
    None123  
       44 天前
    并发快 崩的更快
    gzldc
        20
    gzldc  
    OP
       44 天前
    @Maboroshii 我觉得是我还不够了解 python
    dwzli
        21
    dwzli  
       44 天前
    我猜一下,是不是每个 request 的 futures 都分别 await 了?这样就成同步的了
    morenacl
        22
    morenacl  
       44 天前
    别小看 python ,用 gevent.map ,1w 个请求一次就发了
    gzldc
        23
    gzldc  
    OP
       44 天前
    @deplives 你这里应该是使用了底层的 socket 库来进行请求,效率确实很好 非常满足我的需求。只是有一点,我需要在请求是加上代理。类似于:
    proxies = {
    'http':f'{ip1}',
    'https':f'{ip2}',
    }
    resp = requests.get(url="127.0.0.1",proxies=proxies}')

    非常诚心的请问你这种方式可以实现吗
    liuhai233
        24
    liuhai233  
       44 天前
    Guaderxx
        26
    Guaderxx  
       44 天前
    语言只是工具嘛,不如试试 Go
    alsas
        27
    alsas  
       44 天前
    建议直接用 go 10 万都轻轻松松
    gzldc
        28
    gzldc  
    OP
       44 天前
    @alsas 方便给个例子看下吗?
    iorilu
        29
    iorilu  
       44 天前
    应该是用法不对

    用异步方式, 没啥限制的, 顶多就是发出请求没响应, 但肯定能发的出去
    sherlockwhite
        30
    sherlockwhite  
       44 天前
    用 go 写 很方便,
    sherlockwhite
        31
    sherlockwhite  
       44 天前
    @gzldc #28 直接遍历 然后 在请求的前面加一个 go 就完事,这就是 go
    sherlockwhite
        32
    sherlockwhite  
       44 天前
    你把代码发出来 我写一个看看呢
    xiyou007
        33
    xiyou007  
       44 天前
    ````
    import aiohttp
    import asyncio

    # 读取文件并将每一行的 payload 存储到列表中
    with open('payloads.txt', 'r') as file:
    payloads = [line.strip() for line in file]

    url = 'https://example.com/api' # 替换为您的目标 URL

    async def send_request(payload):
    async with aiohttp.ClientSession() as session:
    try:
    async with session.post(url, data=payload) as response:
    # 不处理响应,仅打印状态码
    print(f"Response status code: {response.status}")
    except aiohttp.ClientError as e:
    print(f"Error: {e}")

    async def main():
    tasks = [send_request(payload) for payload in payloads]
    await asyncio.gather(*tasks)

    # 运行主函数
    asyncio.run(main())
    ```
    hannochtao2
        34
    hannochtao2  
       44 天前
    参考一下,go 语言写的

    ```go
    package main

    import (
    "bufio"
    "fmt"
    "net/http"
    "net/url"
    "os"
    "strings"
    "sync"
    )

    func main() {
    file, err := os.Open("payloads.txt")
    if err != nil {
    fmt.Println("Error opening file:", err)
    return
    }
    defer file.Close()

    proxyURL, err := url.Parse("http://your-proxy-url:port")
    if err != nil {
    fmt.Println("Error parsing proxy URL:", err)
    return
    }

    transport := &http.Transport{
    Proxy: http.ProxyURL(proxyURL),
    }

    client := &http.Client{
    Transport: transport,
    }

    var wg sync.WaitGroup

    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
    wg.Add(1)
    go func(payload string) {
    defer wg.Done()
    sendRequest(client, payload)
    }(scanner.Text())
    }

    wg.Wait()
    }

    func sendRequest(client *http.Client, payload string) {
    url := "https://example.com/target"
    req, err := http.NewRequest("GET", url, strings.NewReader(payload))
    if err != nil {
    fmt.Println("Error creating request:", err)
    return
    }

    req.Header.Set("Content-Type", "application/json")

    _, err = client.Do(req)
    if err != nil {
    fmt.Println("Error sending request:", err)
    return
    }
    }
    ```
    NBNPC
        35
    NBNPC  
       44 天前
    python3.10 aiohttp 5000 次 本地 大概需要 10s

    import asyncio
    import time

    import aiohttp


    def timed(func):
    async def wrapper():
    start = time.time()
    await func()
    print(f"costs: {time.time() - start:.3f} S")

    return wrapper


    async def req(url):
    async with aiohttp.ClientSession() as session:
    async with session.get(url) as resp:
    return resp.status


    @timed
    async def main():
    tasks = [req('http://httpbin.org/status/200') for _ in range(5000)]
    result = await asyncio.gather(*tasks)
    print(len(result), ' status: ', result[-1])
    waytodelay
        36
    waytodelay  
       44 天前
    有点灰产的意思,op 可交流?
    ispinfx
        37
    ispinfx  
       44 天前 via iPhone
    请求太快把网站干死了还能秒不?
    gxt92
        38
    gxt92  
       44 天前
    locust + FastHttpUser
    NotZhang
        39
    NotZhang  
       44 天前
    go 实现

    package main

    import (
    "bufio"
    "fmt"
    "net/http"
    "os"
    "sync"
    )

    // worker 是用来发起 HTTP 请求的协程
    func worker(payloads <-chan string, wg *sync.WaitGroup) {
    defer wg.Done()
    for payload := range payloads {
    // 这里是你的 HTTP 请求逻辑
    _, err := http.Post("你的 URL", "application/json", strings.NewReader(payload))
    if err != nil {
    // 处理错误,根据需要记录或忽略
    fmt.Println("Error sending request:", err)
    continue
    }
    // 这里不处理响应体
    }
    }

    func main() {
    var wg sync.WaitGroup

    // 创建一个 channel 来传递 payload
    payloads := make(chan string, 100) // 缓冲区大小可以根据需要调整

    // 设置并发数,可以根据你的机器性能和网络条件调整
    for i := 0; i < 10; i++ {
    wg.Add(1)
    go worker(payloads, &wg)
    }

    // 打开文件
    file, err := os.Open("yourfile.txt")
    if err != nil {
    fmt.Println("Error opening file:", err)
    return
    }
    defer file.Close()

    // 读取文件中的每一行作为 payload
    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
    payloads <- scanner.Text()
    }
    close(payloads) // 关闭 channel

    // 等待所有的 worker 完成
    wg.Wait()

    if err := scanner.Err(); err != nil {
    fmt.Println("Error reading from file:", err)
    }
    }
    NotZhang
        40
    NotZhang  
       44 天前
    Python 实现

    import requests
    from concurrent.futures import ThreadPoolExecutor, as_completed
    import time

    def send_request(payload):
    """发送 HTTP POST 请求到指定的 URL"""
    try:
    response = requests.post('你的 URL', json=payload)
    # 注意:这里我们不处理响应内容
    except Exception as e:
    print(f"请求发送异常: {e}")

    def load_payloads(file_path):
    """从文件中读取每行作为单独的 payload"""
    with open(file_path, 'r') as file:
    return [line.strip() for line in file]

    def main(file_path, max_workers=20):
    """主函数:读取 payloads 并并发发送请求"""
    payloads = load_payloads(file_path)
    start_time = time.time()
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
    # 将每个 payload 提交到线程池
    future_to_payload = {executor.submit(send_request, payload): payload for payload in payloads}

    # 等待所有的请求完成(这一步是可选的,只是为了能够处理可能的异常)
    for future in as_completed(future_to_payload):
    payload = future_to_payload[future]
    try:
    future.result() # 如果请求产生异常,这里会抛出
    except Exception as exc:
    print(f'{payload} 生成了一个异常: {exc}')

    print(f"所有请求发送完毕,耗时:{time.time() - start_time:.2f}秒")

    if __name__ == "__main__":
    main("yourfile.txt")
    gzldc
        41
    gzldc  
    OP
       44 天前
    @xiyou007
    @NBNPC
    @NotZhang

    感谢 这对我帮助很大
    bequt
        42
    bequt  
       44 天前
    加代理会慢吧。
    mingwiki
        43
    mingwiki  
       44 天前
    单 ip 1w 个请求显然会被封 ip 小网站 200QPS 都不一定扛得住。
    yooomu
        44
    yooomu  
       44 天前
    不如把代码贴出来给大家看看,正常情况下使用 aio ,几万个请求都轻轻松松
    qiuhang
        45
    qiuhang  
       44 天前
    简单暴力法,nohup 尽量多启进程,十个八个的不嫌多,核心够多的话,二十三十的也不是不行
    deplives
        46
    deplives  
       43 天前
    @gzldc #23 那你得自己改造一下
    Cyron
        47
    Cyron  
       43 天前 via iPhone
    wrk 写个脚本应该挺快的😂
    HCX
        48
    HCX  
       43 天前
    wrk
    miku8miku
        49
    miku8miku  
       43 天前
    有交流群么
    milkpuff
        50
    milkpuff  
       43 天前
    一秒 10 个,应该是同步执行了,没有并发。并发参考 35 楼的写法。
    abcfyk
        51
    abcfyk  
       43 天前
    @gzldc #23 有代理需求,执行脚本的时候 用 tsock 不就行了吗
    gzldc
        52
    gzldc  
    OP
       37 天前
    @deplives 哥们的 git 库是隐藏了吗 方便再放出来一下吗
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2739 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 35ms · UTC 10:21 · PVG 18:21 · LAX 03:21 · JFK 06:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.