优化测试API结果的python代码的速度

时间:2018-09-18 23:53:28

标签: python python-3.x multithreading urllib python-3.7

我正在尝试测试一个公开的网页,该网页接受GET请求并根据GET参数返回另一个JSON文件。

API看起来像

https://www.example.com/api/page?type=check&code=[Insert string here]

我制作了一个程序来检查此API上所有可能的4个字母的字符串的结果。我的代码看起来像这样(替换了实际的URL):

import time, urllib.request

for a in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
    for b in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
        for c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
            for d in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
                a,b,c,d = "J","A","K","E"
                test = urllib.request.urlopen("https://www.example.com/api/page?type=check&code=" + a + b + c + d).read()
                if test != b'{"result":null}':
                    print(a + b + c + d)
                    f = open("codes", "a")
                    f.write(a + b + c + d + ",")
                    f.close()

此代码可以完全正常工作,并且可以正常工作。但是,有一个问题。由于程序只有在收到响应后才能继续运行,因此此方法非常慢。如果该API的ping时间为100毫秒,则每次检查将花费100毫秒。当我修改此代码以使其可以在一个实例中测试一半的结果,而在另一个实例中测试一半的结果时,我注意到速度提高了一倍。

因此,我被认为是站点的ping时间是此脚本中的限制因素。我要做的就是基本上检查每个代码,然后立即检查下一个代码,而无需等待响应。

这相当于在浏览器中打开页面数千次。由于每个页面小于一千字节,因此它可以同时加载许多标签。

我研究过使用线程来执行此操作,但是我不确定它是否相关或有用。

1 个答案:

答案 0 :(得分:1)

使用工作池,如此处所述:https://docs.python.org/3.7/library/multiprocessing.html

from multiprocessing import Pool

def test_url(code):
    ''' insert code to test URL '''
    pass

if __name__ == '__main__':
    with Pool(5) as p:
        print(p.map(test_url, [code1,code2,code3]))

请注意,网站可能会限制您提出的请求数量。

为了更具体地说明您的示例,我将其分为两个阶段:(1)生成测试代码(2)测试网址(给定一个测试代码) 。生成代码列表后,您可以使用工作池将上述验证程序应用于每个生成的代码。

要生成测试代码,可以使用itertools:

codes_to_test = [''.join(i) for i in itertools.product(string.ascii_lowercase, repeat = 5)]

您已经对如何通过给定一个测试代码来测试URL有了更好的了解,因此我假设您可以编写一个函数test_url(test_code),该函数将发出适当的URL请求并根据需要验证结果。然后您可以致电:

with Pool(5) as p:
    print(p.map(test_url, test_codes))

最重要的是,我建议两件事:首先确保test_codes不大(例如,通过获取这些生成代码的子列表),以确保您的代码正常工作;以及(2)您可以利用工作池的大小来发挥作用,而不会淹没您的计算机或API。

或者,您可以使用asyncio(https://docs.python.org/3/library/asyncio.html)将所有内容保持在单个进程中。