使用GNU Parallel优化API查询脚本未提速问题排查
哦,我一眼就看出问题所在了——你现在的调用方式完全没让GNU Parallel发挥作用!你是先让script.sh自己串行处理完所有URL,然后把它的输出传给Parallel,Parallel只是在处理输出的文本行而已,根本没参与并行请求API。这就是为什么开90个任务也没提速的核心原因。
下面是分步解决的方案:
第一步:重构脚本,让它支持单个URL处理
原来的脚本是读取整个文件循环处理,现在要改成接受单个URL作为参数,处理这个URL并输出对应的CSV行。这样Parallel才能对每个URL并行调用脚本。
改造后的脚本示例:
#!/bin/bash # 处理单个修正案URL,输出对应的CSV行 # 获取修正案的签署人API地址 sign="${1}/signataires" # 获取提案人信息 auteur(){ local url="${1}" local auteur_id local auteur_info auteur_id=$(curl -s "${url}" | jq '.signataires[] | select(.relation=="auteur") | .id') \ && auteur_info=$(curl -s "https://www.parlapi.fr/rest/an/acteurs_amendements/${auteur_id}" \ | jq -r --arg api_url "https://www.parlapi.fr/rest/an/acteurs_amendements/${auteur_id}" \ '$api_url, .amendement.id, .acteur.id, (.acteur.prenom + " " + .acteur.nom)') \ && echo "${auteur_info}" | tr '\n' ',' | sed 's/,$//' } # 获取联署人信息(优化内部串行请求) cosignataires(){ local url="${1}" # 一次性提取所有联署人ID local cosign_ids=$(curl -s "${url}" | jq -r '.signataires[] | select(.relation=="cosignataire") | .id') # 用Parallel并行请求每个联署人的信息(替代原来的串行for循环) local cosign_names=$(echo "${cosign_ids}" | parallel -j20 curl -s "https://www.parlapi.fr/rest/an/acteurs_amendements/{}" | jq -r '(.acteur.prenom + " " + .acteur.nom)') # 修正原脚本的sed错误:应该替换末尾的分号而不是逗号 echo "${cosign_names}" | tr '\n' ';' | sed 's/;$//' } # 执行逻辑,输出单行CSV auteur_clean=$(auteur "${sign}") cosign_clean=$(cosignataires "${sign}") echo "${auteur_clean},${cosign_clean}"
第二步:用Parallel正确调用改造后的脚本
现在可以让Parallel从你的URL文件中读取每行,并行调用脚本,命令如下:
parallel -j90 ./script.sh {} :::: url_amendements_15.txt > signataires_15.csv
::::表示从文件读取参数(每行一个URL)-j90控制并行任务数(注意不要超过API的100连接限制,可根据实际情况调整)- 直接把所有输出重定向到CSV文件,避免多个进程同时写文件导致内容混乱
额外提速建议
- 启用curl持久连接:给curl加上
--keepalive-time 60参数,复用TCP连接,减少握手开销,能进一步提升速度。 - 缓存重复请求:如果多个修正案有相同的议员,可以添加简单的本地缓存,把已经请求过的
acteurs_amendements/{id}结果存在本地文件里,下次直接读取缓存,避免重复API调用。示例:# 在auteur函数中加入缓存逻辑 cache_dir="./cache" mkdir -p "${cache_dir}" cache_file="${cache_dir}/${auteur_id}.json" if [ -f "${cache_file}" ]; then auteur_info=$(jq -r --arg api_url "https://www.parlapi.fr/rest/an/acteurs_amendements/${auteur_id}" '$api_url, .amendement.id, .acteur.id, (.acteur.prenom + " " + .acteur.nom)' "${cache_file}") else curl -s "https://www.parlapi.fr/rest/an/acteurs_amendements/${auteur_id}" > "${cache_file}" auteur_info=$(jq -r --arg api_url "https://www.parlapi.fr/rest/an/acteurs_amendements/${auteur_id}" '$api_url, .amendement.id, .acteur.id, (.acteur.prenom + " " + .acteur.nom)' "${cache_file}") fi - 调整并行数:90接近API的100连接上限,可能会触发限流,建议先从50开始测试,观察速度和是否有请求失败的情况。
内容的提问来源于stack exchange,提问作者maqueiouseur
相关产品推荐
相关产品推荐

