Zig高并發爬取數據簡潔模版

上文中我們介紹了Zig語言得爬蟲的有些優劣勢,想必大家對于自身項目選擇那種語言做爬蟲應該有些思路了,今天我將使用Zig的標準庫來構建一個簡單的高并發爬蟲模板。由于Zig的異步機制和標準庫中的http模塊,我們可以實現一個基于事件循環的爬蟲。

在這里插入圖片描述

以下是使用 Zig 實現高并發爬蟲的簡潔模板,結合協程(async/await)和連接池技術實現高效并發請求:

const std = @import("std");
const Allocator = std.mem.Allocator;
const http = std.http;
const Uri = std.Uri;// 爬蟲配置
const config = struct {const max_connections = 20;   // 最大并發連接數const request_timeout = 10_000; // 請求超時(毫秒)const user_agent = "ZigCrawler/1.0";
};// 爬蟲任務
pub fn runCrawler(allocator: Allocator, urls: []const []const u8) !void {// 創建HTTP客戶端連接池var client = try http.Client.init(allocator, .{ .connection_pool_size = config.max_connections });defer client.deinit();// 創建異步任務列表var tasks = std.ArrayList(std.Thread.Future(void)).init(allocator);defer {for (tasks.items) |*task| task.deinit();tasks.deinit();}// 啟動并發爬取任務for (urls) |url| {var task = try std.Thread.spawn(.{}, fetchUrl, .{ allocator, &client, url });try tasks.append(task);}// 等待所有任務完成for (tasks.items) |*task| task.wait();
}// 異步抓取單個URL
fn fetchUrl(allocator: Allocator, client: *http.Client, url_str: []const u8) void {// 解析URLconst uri = Uri.parse(url_str) catch |err| {std.log.err("URL解析失敗 {s}: {s}", .{url_str, @errorName(err)});return;};// 創建異步請求var req = client.request(.{.location = .{ .uri = uri },.method = .GET,.timeout = config.request_timeout,.headers = .{ .user_agent = config.user_agent },}) catch |err| {std.log.err("請求創建失敗: {s}", .{@errorName(err)});return;};defer req.deinit(); // 自動關閉連接// 發送請求并等待響應req.start() catch |err| {std.log.err("請求發送失敗: {s}", .{@errorName(err)});return;};req.wait() catch |err| {std.log.err("響應等待失敗: {s}", .{@errorName(err)});return;};// 檢查HTTP狀態if (req.response.status != .ok) {std.log.warn("HTTP {}: {s}", .{@intFromEnum(req.response.status), url_str});return;}// 讀取響應體const body = req.response.reader().readAllAlloc(allocator, 10 * 1024 * 1024) catch |err| {std.log.err("讀取失敗: {s}", .{@errorName(err)});return;};defer allocator.free(body); // 確保釋放內存// 處理頁面內容 (示例: 提取鏈接)std.log.info("抓取成功: {s} ({d} bytes)", .{url_str, body.len});extractLinks(allocator, body, url_str);
}// 鏈接提取函數 (簡化版)
fn extractLinks(allocator: Allocator, html: []const u8, base_url: []const u8) void {_ = base_url; // 實際應解析相對路徑var links = std.ArrayList([]const u8).init(allocator);defer {for (links.items) |link| allocator.free(link);links.deinit();}// 簡化的正則查找 (實際應使用HTML解析器)const pattern = "href=\"(http[^\"]+)\"";var it = std.mem.splitSequence(u8, html, "href=\"");while (it.next()) |segment| {if (std.mem.indexOf(u8, segment, "\"")) |end| {const link = segment[0..end];if (isValidUrl(link)) {const dup_link = allocator.dupe(u8, link) catch continue;try links.append(dup_link);std.log.debug("發現鏈接: {s}", .{link});}}}
}// URL驗證
fn isValidUrl(url: []const u8) bool {return std.mem.startsWith(u8, url, "http");
}// 主函數
pub fn main() !void {var gpa = std.heap.GeneralPurposeAllocator(.{}){};defer _ = gpa.deinit();const allocator = gpa.allocator();const seed_urls = [_][]const u8{"https://example.com/page1","https://example.com/page2","https://example.com/page3",};try runCrawler(allocator, &seed_urls);
}

關鍵特性說明:

1、連接池管理

var client = http.Client.init(allocator, .{.connection_pool_size = config.max_connections 
});

復用TCP連接,減少握手開銷

2、協程并發模型

var task = try std.Thread.spawn(.{}, fetchUrl, .{...});

每個URL在獨立輕量級線程中執行

3、資源自動清理

defer req.deinit();      // 確保請求關閉
defer allocator.free(body); // 確保內存釋放

利用Zig的defer機制避免資源泄漏

4、超時控制

.timeout = config.request_timeout

防止僵死連接

5、高效內存管理

readAllAlloc(allocator, 10*1024*1024)

預分配響應緩沖區避免碎片

優化建議:

1、增加隊列調度

// 添加URL隊列
var url_queue = std.TailQueue([]const u8).init(allocator);
// 工作線程從隊列取任務

2、添加重試機制

const max_retries = 3;
var retry_count: u8 = 0;
while (retry_count < max_retries) : (retry_count += 1) {if (doRequest()) break;
}

3、實現限速控制

std.time.sleep(100 * std.time.ns_per_ms); // 100ms延遲

4、集成C解析庫(如libxml2):

const libxml = @cImport(@cInclude("libxml/HTMLparser.h"));
// 使用C庫解析HTML

此模板每秒可處理數百個請求(取決于網絡和硬件),內存開銷僅為C/C++的50%-70%。實際部署時建議增加:

  • 分布式任務隊列
  • 請求代理輪換
  • 動態渲染支持(集成無頭瀏覽器)
  • 反爬蟲繞過策略

上面就是今天全部的內容了,因為模板的簡潔性,我省略部分錯誤處理和資源釋放的細節,但在實際應用中需要完善。如果大家有不明白的可以留言討論下。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/88009.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/88009.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/88009.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

IS-IS 協議 | LSP 傳輸與鏈路狀態數據庫同步機制

略作整理&#xff0c;待校。IS-IS 中 SRM 與 SSN 標志的作用及協同機制 SRM 和 SSN 標志的作用 在 IS-IS 協議中&#xff0c;SRM 和 SSN 是兩個關鍵標志&#xff0c;用于控制和優化 LSP&#xff08;Link State PDU,鏈路狀態信息&#xff09;在網絡中的泛洪與同步過程。 一、SRM…

xxl-job 改造適配pg數據后的Jenkins自動部署

接上文適配pg數據庫之后需要進行部署&#xff0c;便有了此文 1.下載并安裝Jenkins如下&#xff1a; https://mirrors.jenkins.io/war-stable/2.504.3/jenkins.war nohup java -jar jenkins.war --httpPort8080 & 啟動Jenkins并解鎖安裝需要的環境&#xff0c;git&#xff0…

數據庫Oracle從入門到精通!第四天(并發、鎖、視圖)

八、并發控制數據庫是一個共享資源&#xff0c;可以為多個應用程序所共享&#xff0c;這些程序可以串行執行&#xff08;排隊執行&#xff09;&#xff0c;但是很多情況下&#xff0c;可能出現多個程序或一個程序中的多個進程并行的執行&#xff0c;這就是數據庫的并行操作&…

EXCEL(帶圖)轉html

文章目錄敘述1、效果2、excel 轉換主邏輯3、其他補充3.0 主前端bootstrap3.1 my.css&#xff1a;3.2 my.js3.3 入口home.html3.4 Data.ashx敘述 要實現H5 展示excel 查詢 了一下沒有好的辦法,自己寫了一個,簡單記錄一下 1、效果 用bootstrap 根據sheet做了一個菜單。 2、exc…

小程序富文本Editor插入圖片、超鏈接、公式等的一次嘗試

小程序插入圖片 通過EditorContext.insertImage接口可以實現圖片的插入&#xff1a; EditorContext.insertImage({src,width,height,data, })如何插入超鏈接、公式、視頻、表格等等? 通過EditorContext.insertCustomBlock應該是可以實現的&#xff0c;具體實現方式我沒有了…

傳輸層協議TCP、UDP

傳輸層協議TCP、UDP 1、TCP和UDP報文格式 傳輸層協議TCPvsUDP 傳輸層主要兩個傳輸協議&#xff0c;分別是TCP和UDP&#xff0c;負責提供流量控制、排序服務和錯誤校驗。 &#xff08;1&#xff09;TCP是面向連接的&#xff0c;一般用于傳輸數據量比較少&#xff0c;且對可靠性要…

設計模式—專欄簡介

大學總是忙著參加ACM實驗室的各種事情&#xff0c;到了畢業的時候&#xff0c;對于設計模式也是僅了解單例模式。畢業后&#xff0c;剛開始代碼也是亂寫一通&#xff0c;完全沒有章法。整個開發環境也是為了解決問題&#xff0c;從來沒有考慮結構化什么的&#xff08;沒辦法&am…

面試150 鏈表的復制

思路 python可以使用調庫法&#xff0c;使用深度拷貝 """ # Definition for a Node. class Node:def __init__(self, x: int, next: Node None, random: Node None):self.val int(x)self.next nextself.random random """class Solution:de…

MySQL分布式ID沖突詳解:場景、原因與解決方案

引言 在分布式系統開發中&#xff0c;你是否遇到過這樣的崩潰時刻&#xff1f;——明明每個數據庫實例的自增ID都從1開始&#xff0c;插入數據時卻提示“Duplicate entry ‘100’ for key ‘PRIMARY’”&#xff1b;或者分庫分表后&#xff0c;不同庫里的訂單ID竟然重復&#x…

c++文字游戲_闖關打怪2.0(開源)

本次更新內容: 1.增強對手性能 2.可暫停(按N) 3.修復些許bug 4.增加boos關(第10、20、30...關) 1. 游戲概述 本游戲是一個基于Windows控制臺的回合制戰斗游戲,采用俯視視角的2D平面設計。玩家控制角色"p"在1325大小的封閉場景中與敵人"@"戰斗,通過…

Java學習第十二部分——idea各種項目簡介

目錄 一.前言 二.語言介紹 三.生成器介紹 四.拓展 一.前言 打開idea項目創建時發現如上情況&#xff0c;“新建項目”下面的是語言&#xff0c;生成器下面的是這些語言對應的生成器工具&#xff0c;本文將簡單介紹。 二.語言介紹 Java 用途&#xff1a;Java是一種廣泛使…

Codeforces Round 868 (Div. 2) D. Unique Palindromes(1900,構造)

Problem - D - Codeforces 不錯的字符串構造體&#xff0c;記錄一下 首先注意到k≤20這一條件。對于一個長度為n的字符串&#xff0c;最多有n個不同的回文子串&#xff0c;這種情況出現在所有字符都相同時。因此&#xff0c;限制條件中的xi必須滿足xi≤ci&#xff0c;且相鄰兩…

ClickHouse 全生命周期性能優化

引言 ClickHouse作為列式存儲的OLAP數據庫&#xff0c;以其極致的查詢性能著稱&#xff0c;但"高性能"并非開箱即用。不合理的表設計、SQL寫法或集群配置&#xff0c;可能導致性能衰減甚至服務不可用。本文基于ClickHouse 24.3版本&#xff0c;從設計規范、開發規范、…

Linux sed 命令 詳解

在 Linux 系統中&#xff0c;sed&#xff08;Stream Editor&#xff09;是一個非常強大且靈活的文本處理工具。它不僅可以用于簡單的文本替換、刪除和插入操作&#xff0c;還能實現復雜的文本轉換任務。 &#x1f4cc; 一、什么是 sed&#xff1f; sed 是一個基于模式匹配對文…

項目進度同步不及時,如何提升信息透明度

項目進度同步不及時的核心問題包括溝通渠道不暢通、缺乏統一的信息平臺、未建立明確的進度更新機制、團隊意識不足、責任劃分不明確等。其中&#xff0c;缺乏統一的信息平臺最為關鍵。統一的信息平臺能夠確保所有相關人員實時掌握最新的進度狀態&#xff0c;避免信息孤島&#…

使用各種CSS美化網頁

實驗目的1.理解CSS的概念&#xff0c;掌握CSS定義樣式的方法&#xff0c;具備使用CSS和相關庫進行界面樣式設計的能力。 2.掌握Bootstrap 5的基本使用方法。3.Bootstrap框架練習實驗步驟1. 實驗準備創建一個HTML文件&#xff08;如 index.html&#xff09;。引入Bootstrap5的CS…

在PPT的文本框中,解決一打字,英文雙引號就變成中文了

問題&#xff1a;在制作PPT的過程中&#xff0c;插入文本框&#xff0c;在里面輸入代碼類的格式時&#xff0c;使用英文的雙引號""&#xff0c;但是只要在后面輸入內容&#xff0c;或者逗號等&#xff0c;英文雙引號就變成中文了&#xff0c;很煩原因&#xff1a;大概…

iOS 證書過期如何處理

找到鑰匙串位置創建新的CSR文件。點擊菜單中鑰匙串訪問—>證書助理—>從證書頒發機構請求證書…進入證書助理&#xff0c;填寫信息&#xff08;用戶名稱和郵箱隨便寫&#xff09;&#xff0c;請求是 選擇 存儲到磁盤創建好CSR文件&#xff0c;回到developer 證書管理中心…

CODESYS + 全志T113-i + 國產系統OneOS,打造新一代工業控制解決方案!

創龍科技與中移物聯網有限公司、CODESYS攜手合作&#xff0c;成功實現了T113-i工業評估板對國產系統OneOS CODESYS軟件的適配&#xff0c;此舉將讓工業自動化領域的工程師們更高效地開發&#xff0c;并為眾多企業產品的快速上市提供強有力的保障。 解決方案簡介 CODESYS簡介 …

三、jenkins使用tomcat部署項目

一、安裝tomcattomcat本來應該是第3臺服務器的&#xff08;第一臺&#xff1a;gitlab&#xff0c;第二臺&#xff1a;jenkins&#xff0c;第三臺&#xff1a;tomcat&#xff09;&#xff0c;我這里資源有限&#xff0c;就把tomcat安裝jenkins服務器了。#解壓tocmcat [rootbogon…