I’m new to ZIG and i’m trying to make a code where I can load browser and get all the response from inside that URL and at the same time where I can visualize the page
what I currently have:
src/main.zig:
const std = @import("std");
const gtk = @cImport({
@cInclude("/usr/include/gtk-4.0/gtk/gtk.h");
});
pub fn main() !void {
gtk.gtk_init(null, null);
const window = gtk.gtk_window_new(gtk.GTK_WINDOW_TOPLEVEL);
gtk.gtk_window_set_title(gtk.GTK_WINDOW(window), "Zig Web Scraper");
gtk.gtk_window_set_default_size(gtk.GTK_WINDOW(window), 800, 600);
const webview = gtk.webkit_web_view_new();
gtk.gtk_container_add(gtk.GTK_CONTAINER(window), webview);
const target_url = "https://google.com";
gtk.webkit_web_view_load_uri(gtk.WEBKIT_WEB_VIEW(webview), target_url);
_ = gtk.g_signal_connect_data(
webview,
"load-changed",
@ptrCast(&onLoadChanged),
null,
null,
0,
);
gtk.gtk_widget_show_all(window);
gtk.gtk_main();
}
fn onLoadChanged(webview: *anyopaque, load_event: gtk.WebKitLoadEvent, _: ?*anyopaque) callconv(.C) void {
// Check if the page has finished loading
if (load_event == gtk.WEBKIT_LOAD_FINISHED) {
const js_script =
\\(function() {
\\ const headings = document.querySelectorAll("h1, h2, h3");
\\ return Array.from(headings).map(el => el.textContent).join(", ");
\\})();
;
gtk.webkit_web_view_run_javascript(
@ptrCast(webview),
js_script,
null,
@ptrCast(&onJavascriptResult),
null,
);
}
}
fn onJavascriptResult(_webview: *anyopaque, result: *gtk.GAsyncResult, _: ?*anyopaque) callconv(.C) void {
const allocator = std.heap.c_allocator;
var problem: ?*gtk.GError = null;
const js_value = gtk.webkit_web_view_run_javascript_finish(@ptrCast(_webview), result, &problem);
if (problem != null) {
std.debug.print("JavaScript Execution Failed: {s}\n", .{problem.*.message});
return;
}
if (js_value != null) {
const value_str = gtk.webkit_javascript_result_get_js_value(js_value);
const result_cstr = gtk.jsc_value_to_string(value_str);
const result_str = std.cstr.toSlice(allocator, result_cstr) catch "Failed to parse result.";
std.debug.print("Scraped Data: {s}\n", .{result_str});
gtk.g_free(result_cstr);
gtk.webkit_javascript_result_unref(js_value);
}
}
build.zig:
const std = @import("std");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "web_scraper",
.root_source_file = b.path("src/main.zig"),
.target = target,
.optimize = optimize,
});
const myflags = std.fs.File.OpenFlags{ .read = true };
const flags_file = std.fs.cwd().openFile("flags.txt", myflags) catch |err| {
std.log.err("Failed to open flags.txt: {any}", .{err});
return;
};
const allocator = std.heap.page_allocator;
const flags = flags_file.readAllAlloc(allocator) catch |err| {
std.log.err("Failed to read flags.txt: {any}", .{err});
return;
};
const tokens = std.mem.tokenize(flags, " ");
for (tokens) |flag| {
if (std.mem.startsWith(u8, flag, "-I")) {
const path = flag[2..];
exe.addIncludePath(std.Build.LazyPath{ .abs = path });
} else if (std.mem.startsWith(u8, flag, "-L")) {
const path = flag[2..];
exe.addLibraryPath(path);
} else if (std.mem.startsWith(u8, flag, "-l")) {
const lib = flag[2..];
exe.linkSystemLibrary(lib);
}
}
allocator.free(flags);
b.installArtifact(exe);
const run_cmd = b.addRunArtifact(exe);
b.step("run", "Run the web scraper").dependOn(&run_cmd.step);
}
flags.txt:
-mfpmath=sse -msse -msse2 -pthread -I/usr/include/gtk-4.0 -I/usr/include/graphene-1.0 -I/usr/lib/x86_64-linux-gnu/graphene-1.0/include -I/usr/include/webkitgtk-4.0 -I/usr/include/gtk-3.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/x86_64-linux-gnu/dbus-1.0/include -I/usr/include/gtk-3.0 -I/usr/include/gio-unix-2.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/harfbuzz -I/usr/include/pango-1.0 -I/usr/include/fribidi -I/usr/include/harfbuzz -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/uuid -I/usr/include/freetype2 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libpng16 -I/usr/include/x86_64-linux-gnu -I/usr/include/libsoup-2.4 -I/usr/include/libxml2 -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/webkitgtk-4.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -lgtk-4 -lgraphene-1.0 -lwebkit2gtk-4.0 -lgtk-3 -lgdk-3 -lpangocairo-1.0 -lpango-1.0 -lharfbuzz -latk-1.0 -lcairo-gobject -lcairo -lgdk_pixbuf-2.0 -lsoup-2.4 -Wl,--export-dynamic -lgmodule-2.0 -pthread -lgio-2.0 -ljavascriptcoregtk-4.0 -lgobject-2.0 -lglib-2.0
I tried to get help from chatgpt but it fails always it makes things even worse and gets it even more complicated each time i’m not sure if anything actually works in the code above but this is the last error:
error: no field named 'read' in struct 'fs.File.OpenFlags'
const myflags = std.fs.File.OpenFlags{ .read = true };
^~~~
/snap/zig/11625/lib/std/fs/File.zig:74:23: note: struct declared here
pub const OpenFlags = struct {