首页 > 解决方案 > 在间隔很小并一次请求大量数据的情况下提高循环的速度

问题描述

因此,下面的代码假设穿过加拿大并获取 Circle K 的位置。
我要走 0.0001,因为事实上,像多伦多这样的城市在商店中变得密集,并且在检查 lat&lng 时下降到 4 sig。
当我运行代码时,我注意到一次检查 0.0001 需要很长时间才能以一种方式检查大约 42 的范围。
此外,当我运行代码时,我将背靠背地获得相同的位置,因为在少数商店的区域差异为 0.0001 不会导致发现任何新商店。
重复和慢磨的结合是我要问是否有人对如何加快这个过程有一些建议。
我正在考虑将 : &page=100 添加到 url 的末尾,但这无济于事,因为代码只是将它视为第 100 页的内容输出,其中不包含之前的 99 页。
有没有办法一次输出 0-whatever 页面之间的页面?
我也包含了当前代码,以防我忽略了简单的修复。

因此,目标是一次请求更多数据并更快地扫描整个加拿大。

我的代码:

import requests
import json
import numpy as np
import csv 

lat_lng = [(lat,long) for lat,long in zip(np.arange(42,84,0.01),np.arange(-142,-52,0.01))] 

for latitude,longitude in lat_lng:
  url = f"https://www.circlek.com/stores_new.php?lat={latitude}&lng={longitude}&services=&region=global"
  payload={}
  headers = {
    'Connection': 'keep-alive',
    'sec-ch-ua': '" Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"',
    'Accept': '*/*',
    'X-Requested-With': 'XMLHttpRequest',
    'sec-ch-ua-mobile': '?0',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36',
    'Sec-Fetch-Site': 'same-origin',
    'Sec-Fetch-Mode': 'cors',
    'Sec-Fetch-Dest': 'empty',
    'Referer': 'https://www.circlek.com/store-locator?Canada&lat=43.6529&lng=-79.3849',
    'Accept-Language': 'en-GB,en-US;q=0.9,en;q=0.8',
    'dnt': '1'
  }

  response = requests.request("GET", url, headers=headers, data=payload)

  print(response.json())

当我添加页面时,网址的外观也如何:https ://www.circlek.com/stores_new.php?lat={latitude}&lng={longitude}&services=®ion=global&page=1

我觉得找到一种方法来抓取多个页面是可行的方法,但没有真正的方法。

提前致谢!

标签: pythonweb-scrapingpython-requestspagination

解决方案


问题是,你一个接一个地做 4200 请求。我已经重写了您的程序以异步执行它,这大大加快了它的速度。您必须安装该httpx库才能使其正常工作。这是修改后的代码:

import json
import numpy as np
import csv
import httpx
import asyncio

async def print_data():
    lat_lng = [
        (lat, long) for lat, long in zip(np.arange(42, 84, 0.01), np.arange(-142, -52, 0.01))
    ]
    urls = [
        f"https://www.circlek.com/stores_new.php?lat={la}&lng={lo}&services=&region=global"
        for la, lo in lat_lng
    ][:100] # Only the first 100 urls are requested here!!
    headers = {
        "Connection": "keep-alive",
        "sec-ch-ua": '" Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"',
        "Accept": "*/*",
        "X-Requested-With": "XMLHttpRequest",
        "sec-ch-ua-mobile": "?0",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36",
        "Sec-Fetch-Site": "same-origin",
        "Sec-Fetch-Mode": "cors",
        "Sec-Fetch-Dest": "empty",
        "Referer": "https://www.circlek.com/store-locator?Canada&lat=43.6529&lng=-79.3849",
        "Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8",
        "dnt": "1",
    }
    async with httpx.AsyncClient() as c:
        tasks = (c.get(url, headers=headers) for url in urls)
        resp = await asyncio.gather(*tasks)
    for r in resp:
        print(r.json())


if __name__ == "__main__":
    asyncio.run(print_data())

在我的示例中,我只请求了前 100 个 url,因为服务器不会在短时间内响应那么多请求。(阅读速率限制,如果你不知道的话)。因此,您仍然必须实施某种限制,以减少您每秒发送的请求。(也许分批做几百个,然后在它们之间睡一会儿)。


推荐阅读