robots.txt
robots.txt read as Google does: whether an agent may fetch a path, its crawl delay and sitemaps; and your own site's robots.txt written.
Version 1.0.0 · 5 functions · 1 crate
Functions
What use robots.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use robots_allowed, robots_check from robots (Quillo 0.6).
robots_allowed(robots_txt: str, user_agent: str, url: str) → boolor an errorWhether user_agent (your crawler's name, such as "QuilloBot") may fetch url (a full URL or a path) under these robots.txt rules: the longest matching rule wins, Allow on a tie, * and $ understood.
robots_check(robots_txt: str, user_agent: str, urls: list) → listor an errorMany URLs checked at once: [{ url, allowed }], in order. At most 100,000.
robots_info(robots_txt: str, user_agent: str) → anyor an errorWhat the file says beyond the rules: { crawl_delay, sitemaps }, the delay in seconds between requests for this agent (null when none is set).
robots_url(page_url: str) → stror an errorWhere a page's robots.txt is: https://example.com/robots.txt for any URL of that site.
robots_write(groups: list, sitemaps: list) → stror an errorA robots.txt for your own site: groups is [{ agents: ["*"], allow: ["/"], disallow: ["/admin", "/cart"], crawl_delay: 2 }], sitemaps the sitemaps' full URLs.
Get it
$ quillo install robots # robots.qwer into this folder$ quillo install robots --example # and its example, robots.qweOr with curl:
$ curl -O https://quillolang.org/plugins/files/robots.qwer$ curl -O https://quillolang.org/plugins/files/robots.qweThen, in your program, all of it or only what you call:
use robots.qweruse robots_allowed, robots_check from robots // Quillo 0.6: only theseIt uses this crate, which cargo fetches the first time the plugin is built:
texting_robots = "0.2"Example
// A link checker's politeness, and the site's own robots.txt: what a crawler may fetch under a// site's rules (here a sample file; a real crawler gets it with http.get(robots_url(page))).//// quillo run robots.qwe then open http://localhost:8080/may?path=/shop/cartuse "robots.qwer"let RULES = `User-agent: *Disallow: /admin/Disallow: /shop/cartDisallow: /*.pdf$Allow: /admin/public/User-agent: QuilloBotDisallow: /drafts/Crawl-delay: 2Sitemap: https://shop.example.com/sitemap.xml`route GET /may ? { path: str, agent: str = "SomeBot" } = { path, agent, allowed: robots_allowed(RULES, agent, path)? }route GET /crawl = { checks: robots_check(RULES, "SomeBot", ["/shop/shoes", "/shop/cart", "/admin/settings", "/admin/public/logo.png", "/files/price-list.pdf", "/files/price-list.pdf?v=2"])? | map((c) => `${c.allowed ? "fetch" : "skip "} ${c.url}`), quillobot: robots_info(RULES, "QuilloBot")?, robots_of: robots_url("https://shop.example.com/shop/shoes?color=red")?,}route GET /robots.txt = respond(200, robots_write([{ agents: ["*"], allow: ["/"], disallow: ["/admin", "/cart"] }, { agents: ["GPTBot", "CCBot"], disallow: ["/"] }], ["https://shop.example.com/sitemap.xml"])?, { "content-type": "text/plain" })$ quillo run robots.qwe$ curl 'localhost:8080/may?path=/shop/cart'$ curl 'localhost:8080/crawl'$ curl 'localhost:8080/robots.txt'Source
//! robots.txt read as Google does: whether a user agent may fetch a path, its crawl delay and the sitemaps listed, for crawlers, link checkers and preview fetchers; and your own site's robots.txt written.//! version: 1.0.0//!//! [dependencies]//! texting_robots = "0.2"use serde_json::{json, Value};const MAX_TXT: usize = 500 * 1024;fn robot(txt: &str, agent: &str) -> Result<texting_robots::Robot, String> { // Google reads the first 500 KiB of a robots.txt; so does this. let mut end = txt.len().min(MAX_TXT); while !txt.is_char_boundary(end) { end -= 1; } texting_robots::Robot::new(agent, txt[..end].as_bytes()).map_err(|e| format!("robots.txt: {}", e))}/// Whether `user_agent` (your crawler's name, such as "QuilloBot") may fetch `url` (a full URL or a path) under these robots.txt rules: the longest matching rule wins, Allow on a tie, `*` and `$` understood.pub fn robots_allowed(robots_txt: &str, user_agent: &str, url: &str) -> Result<bool, String> { Ok(robot(robots_txt, user_agent)?.allowed(url))}/// Many URLs checked at once: `[{ url, allowed }]`, in order. At most 100,000.pub fn robots_check(robots_txt: &str, user_agent: &str, urls: Vec<String>) -> Result<Vec<Value>, String> { if urls.len() > 100_000 { return Err("at most 100,000 URLs at once".into()); } let r = robot(robots_txt, user_agent)?; Ok(urls.iter().map(|u| json!({ "url": u, "allowed": r.allowed(u) })).collect())}/// What the file says beyond the rules: `{ crawl_delay, sitemaps }`, the delay in seconds between requests for this agent (null when none is set).pub fn robots_info(robots_txt: &str, user_agent: &str) -> Result<Value, String> { let r = robot(robots_txt, user_agent)?; Ok(json!({ "crawl_delay": r.delay.map(|d| d as f64), "sitemaps": r.sitemaps }))}/// Where a page's robots.txt is: `https://example.com/robots.txt` for any URL of that site.pub fn robots_url(page_url: &str) -> Result<String, String> { texting_robots::get_robots_url(page_url).map_err(|e| format!("{}: {:?}", page_url, e))}/// A robots.txt for your own site: `groups` is `[{ agents: ["*"], allow: ["/"], disallow: ["/admin", "/cart"], crawl_delay: 2 }]`, `sitemaps` the sitemaps' full URLs.pub fn robots_write(groups: Vec<serde_json::Value>, sitemaps: Vec<String>) -> Result<String, String> { let mut out = String::new(); let list = |g: &Value, k: &str| -> Vec<String> { g.get(k).and_then(Value::as_array).map(|a| a.iter().filter_map(Value::as_str).map(|s| s.replace(['\n', '\r'], "")).collect()).unwrap_or_default() }; for g in &groups { let agents = list(g, "agents"); if agents.is_empty() { return Err("each group names its `agents` (\"*\" for all)".into()); } for a in &agents { out.push_str(&format!("User-agent: {}\n", a)); } for p in list(g, "allow") { out.push_str(&format!("Allow: {}\n", p)); } for p in list(g, "disallow") { out.push_str(&format!("Disallow: {}\n", p)); } if let Some(d) = g.get("crawl_delay").and_then(Value::as_f64) { out.push_str(&format!("Crawl-delay: {}\n", d)); } out.push('\n'); } for s in sitemaps { out.push_str(&format!("Sitemap: {}\n", s.replace(['\n', '\r'], ""))); } Ok(out)}Related
bots.qwer · 1.0.0Crawlers told apart by User-Agent: search engines, AI training and answer bots, link previews, SEO tools, monitors and libraries, with their owner; a claimed Googlebot checked by reverse and forward DNS; and robots.txt that blocks chosen categories.6 views · 11 downloadsSitemaps sitemap_read.qwer · 1.0.0Sitemaps and sitemap indexes read from XML, .xml.gz or text: URLs with lastmod, changefreq, priority and images; and a sitemap written for your pages.7 views · 8 downloadsStructured data structured_data.qwer · 1.0.0JSON-LD, microdata, Open Graph and Twitter tags read out of HTML; schema.org JSON-LD written for products, articles, breadcrumbs and FAQs; and items checked for what Google's rich results need.7 views · 8 downloadsScrape pages scrape.qwer · 1.0.0CSS selectors over HTML, a page's link preview (title, description, image) and its text without scripts.6 views · 7 downloadsURL tools url_tools.qwer · 1.0.0URLs by the rules browsers use: parts and query as a map, relative links resolved, a normal form for comparing, tracking parameters stripped, query values set.7 views · 6 downloadsWeb app manifest pwa_manifest.qwer · 1.0.0Installable web apps: the manifest written with sensible defaults and checked against what browsers need for Install, the icon set (maskable, Apple's and favicons) made from one image, and the head tags.7 views · 6 downloadsThread 0 posts
On robots.txt: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.