如何通过代码无需Git Bash安装指定GitHub YARA规则仓库内容?
不用Git工具获取GitHub仓库内容的实现方案
核心思路
不用Git客户端的话,有两种可靠实现方式:
- 直接下载仓库的完整ZIP归档(最简单,适合一次性获取全部内容)
- 通过GitHub REST API遍历仓库目录结构,逐个下载文件(适合按需获取或增量更新)
Python 实现
方法1:下载完整ZIP包
用requests库下载ZIP后解压:
import requests import zipfile import os # 仓库main分支的ZIP下载地址 zip_url = "https://github.com/reversinglabs/reversinglabs-yara-rules/archive/refs/heads/main.zip" save_path = "./reversinglabs-yara-rules.zip" extract_dir = "./reversinglabs-yara-rules" # 流式下载ZIP response = requests.get(zip_url, stream=True) with open(save_path, "wb") as f: for chunk in response.iter_content(chunk_size=8192): f.write(chunk) # 解压到目标目录 os.makedirs(extract_dir, exist_ok=True) with zipfile.ZipFile(save_path, "r") as zip_ref: zip_ref.extractall(extract_dir) # 可选:删除临时ZIP包 os.remove(save_path)
方法2:通过API递归下载文件
遍历仓库目录,逐个下载文件:
import requests import os API_BASE = "https://api.github.com/repos/reversinglabs/reversinglabs-yara-rules/contents" target_dir = "./reversinglabs-yara-rules" def download_file(file_url, save_path): response = requests.get(file_url) os.makedirs(os.path.dirname(save_path), exist_ok=True) with open(save_path, "wb") as f: f.write(response.content) def traverse_dir(api_path, local_path): response = requests.get(api_path) items = response.json() for item in items: if item["type"] == "file": download_file(item["download_url"], os.path.join(local_path, item["name"])) elif item["type"] == "dir": traverse_dir(item["url"], os.path.join(local_path, item["name"])) traverse_dir(API_BASE, target_dir)
注:仓库较大时建议添加请求延时,避免触发GitHub API限流。
C# 实现
方法1:下载并解压ZIP包
用HttpClient下载,ZipArchive处理解压:
using System; using System.IO; using System.IO.Compression; using System.Net.Http; class Program { static async System.Threading.Tasks.Task Main(string[] args) { string zipUrl = "https://github.com/reversinglabs/reversinglabs-yara-rules/archive/refs/heads/main.zip"; string savePath = "./reversinglabs-yara-rules.zip"; string extractDir = "./reversinglabs-yara-rules"; // 下载ZIP包 using (HttpClient client = new HttpClient()) { using (HttpResponseMessage response = await client.GetAsync(zipUrl, HttpCompletionOption.ResponseHeadersRead)) { response.EnsureSuccessStatusCode(); using (Stream stream = await response.Content.ReadAsStreamAsync()) using (FileStream fileStream = new FileStream(savePath, FileMode.Create, FileAccess.Write)) { await stream.CopyToAsync(fileStream); } } } // 解压到目标目录 Directory.CreateDirectory(extractDir); ZipFile.ExtractToDirectory(savePath, extractDir); // 删除临时ZIP包 File.Delete(savePath); } }
方法2:通过API递归下载文件
用System.Text.Json解析API返回的JSON数据:
using System; using System.Collections.Generic; using System.IO; using System.Net.Http; using System.Text.Json; using System.Threading.Tasks; class GithubRepoDownloader { private static readonly HttpClient _client = new HttpClient(); private const string ApiBase = "https://api.github.com/repos/reversinglabs/reversinglabs-yara-rules/contents"; private static string _targetDir = "./reversinglabs-yara-rules"; class GithubItem { public string type { get; set; } public string url { get; set; } public string download_url { get; set; } public string name { get; set; } } static async Task DownloadFile(string url, string localPath) { Directory.CreateDirectory(Path.GetDirectoryName(localPath)); using (var response = await _client.GetAsync(url)) { response.EnsureSuccessStatusCode(); using (var stream = await response.Content.ReadAsStreamAsync()) using (var fileStream = new FileStream(localPath, FileMode.Create)) { await stream.CopyToAsync(fileStream); } } } static async Task TraverseDirectory(string apiPath, string localPath) { using (var response = await _client.GetAsync(apiPath)) { response.EnsureSuccessStatusCode(); var json = await response.Content.ReadAsStringAsync(); var items = JsonSerializer.Deserialize<List<GithubItem>>(json); foreach (var item in items) { if (item.type == "file") { await DownloadFile(item.download_url, Path.Combine(localPath, item.name)); } else if (item.type == "dir") { await TraverseDirectory(item.url, Path.Combine(localPath, item.name)); } } } } static async Task Main(string[] args) { // GitHub API要求设置User-Agent,否则会拒绝请求 _client.DefaultRequestHeaders.UserAgent.ParseAdd("C#-Repo-Downloader"); await TraverseDirectory(ApiBase, _targetDir); } }
C/C++ 实现
方法1:跨平台下载ZIP包(依赖libcurl)
#include <stdio.h> #include <curl/curl.h> #include <stdlib.h> // 回调函数:写入下载内容到文件 size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) { return fwrite(ptr, size, nmemb, stream); } int main(void) { CURL *curl_handle; FILE *fp; const char *zip_url = "https://github.com/reversinglabs/reversinglabs-yara-rules/archive/refs/heads/main.zip"; const char *save_path = "./reversinglabs-yara-rules.zip"; curl_global_init(CURL_GLOBAL_ALL); curl_handle = curl_easy_init(); if(curl_handle) { fp = fopen(save_path, "wb"); if(!fp) { fprintf(stderr, "无法打开文件写入\n"); return 1; } curl_easy_setopt(curl_handle, CURLOPT_URL, zip_url); curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, fp); curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L); // 跟随重定向 CURLcode res = curl_easy_perform(curl_handle); if(res != CURLE_OK) { fprintf(stderr, "下载失败: %s\n", curl_easy_strerror(res)); } fclose(fp); curl_easy_cleanup(curl_handle); } curl_global_cleanup(); printf("ZIP包已下载到: %s\n", save_path); // 解压需额外依赖minizip/zlib,可自行集成实现 return 0; }
编译命令(Linux/macOS):gcc github_download.c -o github_download -lcurl
方法2:Windows原生下载(WinHTTP,无需第三方库)
#include <windows.h> #include <winhttp.h> #include <stdio.h> #pragma comment(lib, "winhttp.lib") int main() { HINTERNET hSession = WinHttpOpen(L"C-Github-Downloader", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if(!hSession) { printf("WinHttpOpen失败: %d\n", GetLastError()); return 1; } HINTERNET hConnect = WinHttpConnect(hSession, L"github.com", INTERNET_DEFAULT_HTTPS_PORT, 0); if(!hConnect) { printf("WinHttpConnect失败: %d\n", GetLastError()); WinHttpCloseHandle(hSession); return 1; } HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", L"/reversinglabs/reversinglabs-yara-rules/archive/refs/heads/main.zip", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE); if(!hRequest) { printf("WinHttpOpenRequest失败: %d\n", GetLastError()); WinHttpCloseHandle(hConnect); WinHttpCloseHandle(hSession); return 1; } BOOL bResults = WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); if(bResults) { bResults = WinHttpReceiveResponse(hRequest, NULL); if(bResults) { FILE *fp = fopen("./reversinglabs-yara-rules.zip", "wb"); if(fp) { char buffer[8192]; DWORD bytesRead; while(WinHttpReadData(hRequest, buffer, sizeof(buffer), &bytesRead) && bytesRead > 0) { fwrite(buffer, 1, bytesRead, fp); } fclose(fp); printf("ZIP包下载成功\n"); } else { printf("无法打开文件写入\n"); } } } else { printf("WinHttpSendRequest失败: %d\n", GetLastError()); } WinHttpCloseHandle(hRequest); WinHttpCloseHandle(hConnect); WinHttpCloseHandle(hSession); return 0; }
编译命令(MSVC):cl winhttp_download.c winhttp.lib
注意事项
- GitHub API对未认证用户限流为每小时60次请求,仓库文件较多时建议添加认证(请求头加入
Authorization: token YOUR_TOKEN) - 下载ZIP包适合一次性获取全部内容,API方式适合灵活控制下载范围
- C/C++解压ZIP需额外依赖minizip或zlib,可根据平台选择集成
内容的提问来源于stack exchange,提问作者Lord Touch Me
相关产品推荐
相关产品推荐

