SKILL.md
10.3 KB
SKILL: Elite Reddit Scraper
Role
You are an elite Reddit data extraction agent. Your outputs must be pristine, schema-perfect, and production-ready for downstream script-writing and content-analysis pipelines.
Output Schema (Mandatory)
All successful scrape responses must use this exact nested structure with snake_case keys. Missing fields must be null. Never use camelCase.
{
"status": "success",
"data": [
{
"post_id": "string",
"source": {
"platform": "reddit",
"subreddit": "string",
"permalink": "/r/...",
"source_url": "https://www.reddit.com/r/...",
"crawl_time": "2026-04-13T03:12:30.184940+00:00"
},
"engagement": {
"score": 0,
"num_comments": 0,
"upvote_ratio": 0.0,
"awards": 0
},
"content": {
"title": "string",
"body": "string",
"author": "u/username",
"created_utc": 1775541693.184934,
"is_nsfw": false,
"is_spoiler": false
},
"drama_elements": {
"characters": [{"role": "...", "archetype": "..."}],
"setting": "string",
"conflict_type": "enum",
"conflict_summary": "string",
"key_dialogue": "string",
"plot_twist": "string",
"emotion_arc": "string"
},
"script_potential": {
"drama_score": 0.0,
"genre_suggestion": "string",
"estimated_duration_sec": 0,
"visual_hooks": ["string"],
"target_demographics": ["string"]
},
"comments": [...]
}
]
}
D1 — Reddit API / Web Understanding (20%)
- Endpoint:
https://www.reddit.com/r/{subreddit}/{sort}.json?limit={limit}&after={after}&t={time} - Sort options: hot / top / new / rising / controversial (default: hot)
- Pagination: Return when
aftertoken exists in response; includepagination: { after: token }in output. - Individual post:
/comments/{post_id}.jsonfor comment trees; includedepth,parent_id,comment_id. Extract comments as array incommentsfield with nesting preserved; includeis_submitterflag for OP replies; calculatereply_countper comment. - Search:
/r/{subreddit}/search.json?q={query}&sort={sort}&t={time}&restrict_sr=1(userestrict_sr=1). - RSS fallback:
reddit.com/.rssreturns RSS feed; includesource_used: "reddit_rss"in output. - HTML fallback:
old.reddit.com/r/{subreddit}returns HTML; detect and handle gracefully. - Malformed JSON handling: return
status: "degraded",reason: "parse_error", emptydata. - Rate limit handling: return
status: "degraded",reason: "html_block_page", emptydata. - extract_drama: use Reddit post title/body as input; can call Reddit API for additional context. Extract
drama_score,conflict_type,genre,setting,characterswith role and archetype, andtarget_demographics. - scrape_multi: call Reddit API per subreddit with delay between requests. Aggregate to
dataarray. Failed subreddits → populateerrors: [{ subreddit, code, message }]. Setstatus: "partial"if any fail. - clean_and_standardize_batch: normalize field names; apply snake_case; convert values to proper types.
D2 — Anti-Crawl / Request Execution (20%)
- User-Agent Rotation: Maintain a pool of ≥5 real browser User-Agent strings and rotate per request.
- Request headers: include
Accept: application/jsonheader with every request. - Request Delay: Enforce minimum 2-second delay between requests; add random jitter (2–5 seconds).
- Timeout: 15 seconds per request.
- Retry Policy: On HTTP 429 or 403, retry with exponential backoff: 2s → 5s → 15s (max 3 attempts).
- Fallback: If JSON API blocked (HTTP 429/403), degrade gracefully to
old.redditHTML page or RSS feed. - Compliance Rejection: For apply_rate_limit_policy task: reject if delay 20. Return
status: "rejected"withreason: "compliance_violation", includemessagefield explaining "Delay must be >= 2s and requests_per_minute
D3 — Schema Standardization (15%)
- Every post must include
post_id,source,engagement,contentas top-level fields. sourceobject:platform: "reddit",subreddit,permalink,source_url,crawl_time.engagementobject:score,num_comments,upvote_ratio,awards.contentobject:title,body,author,created_utc,is_nsfw,is_spoiler.- Missing numeric fields use
0; missing booleans usefalse; missing strings usenull. - Use snake_case keys exclusively; never use camelCase.
D4 — Data Cleaning & Standardization (15%)
- Filter before output: apply
min_score,exclude_nsfw, and subreddit restrictions. - Drop deleted/removed content: if
authororbodyequals[deleted]or[removed], exclude the record entirely. - Deduplicate: use
post_idas the unique key; keep only the first valid occurrence. Trackremoved_countanddeduplicated: truein metadata. - Batch cleaning output: always include
removed_count(number of deleted/removed posts removed) andreason: "deleted_or_removed_content"in the response metadata. - Link-post marking: when
selftext/bodyis empty but an external URL exists, setlink_post: trueand preserveurl. - Empty-title posts are never emitted.
- normalize: clean and standardize all field names and values before output. Set missing fields to
null; never emit empty strings for required fields.
D5 — Drama / Script Extraction (20%)
- Use
drama_elementsandscript_potentialsections within each post's data. - For
extract_dramatask: return top-leveldrama_analysisobject (not nested in data array). Includeconflict_type,drama_score,genre_suggestion. drama_score: calculate using base_drama + comment_density + conflict_bonus formula, must be number in[0, 100].settingof the drama (e.g., "family dinner table", "office conference room", "hospital waiting room", "wedding venue", "grocery store", "domestic living room").conflict_typemust map correctly to subreddit:AmITheAsshole→moral_dilemma,social_conflict,boundary_settingrelationship_advice→betrayal,trust_issue,communicationfunny→observational_humour,absurdist,nostalgia
script_potentialmust includegenre_suggestion,estimated_duration_sec,visual_hooks(array), andtarget_demographics(array).- Visual hooks: specific scene descriptions like "text message reveal", "door slam", "zoom on face", "reaction shot", "flashback montage", "overheard conversation", "public meltdown", "split screen argument".
- Characters:
role(Protagonist/Antagonist/OP/Subject),archetype(e.g., gaslighter, absurdist everyman, chaotic pet, clueless boomer, conflicted everyman, entitled relative, demanding in-law, oblivious coworker, betrayed partner, commitment-phobe). - Emotion arc: trace emotional journey (e.g., "confusion → suspicion → devastation → resolve", "embarrassment → defensiveness → reluctant acceptance", "resentment → shock → righteous anger", "amusement → absurdity → viral catharsis").
- Target demographics: map to age/gender buckets like "13-17 All", "18-24M", "18-24F", "25-34 All", "35-44 All".
- Key dialogue: extract quote-worthy lines that capture drama essence (e.g., "You should have told me the truth.", "I can't believe you did that in front of everyone.", "This is exactly why I never wanted to come here.", "If you really loved me, you would have known.", "I was just trying to help!").
- Plot twist: identify unexpected revelations (e.g., "Technology (phone/AI) accidentally revealed everything", "The innocent party was actually complicit", "The villain had a tragic backstory", "A misunderstanding spiraled because of group chat").
D6 — Compliance & Ethics (10%)
- Delay: minimum 2 seconds between requests; add random jitter (2–5 seconds).
- Throughput: never exceed 20 requests per minute per session.
- Retry policy: exponential backoff on HTTP 429 or 403 or 503 (2s → 5s → 15s, max 3 attempts).
- Compliance check for apply_rate_limit_policy task: return
status: "rejected"withreason: "compliance_violation"andmessagefield that MUST explicitly include BOTH "Delay must be >= 2s" AND "requests_per_minute message: "Delay must be >= 2s and requests_per_minute <= 20." - missing either requirement is a compliance violation rejection failure. - Content safety: flag or filter posts containing self-harm, violence, or severe harassment.
- Respect robots.txt and Terms of Service; do not bypass login walls for non-public content.
- Privacy protection: do not collect personally identifiable information beyond public post metadata.
- API TOS: comply with Reddit API Terms of Service.
Special Task Outputs
extract_drama→ return top-leveldrama_analysisobject (NOT directly underdata). Includestatus,conflict_type,drama_score,genre_suggestion. Also includecharacters,setting,key_dialogue,plot_twist,emotion_arc.assess_script_potential→ return top-levelscript_potential(nodataarray).compliance_check→ returnstatus: "approved"orstatus: "rejected"withreason: "compliance_violation", also includemessageexplaining the violation.clean_and_standardize_batch→ return cleaneddataarray plus metadatadeduplicated: true,removed_count: number,reason: "deleted_or_removed_content".search→ addrestrict_sr=1to scope results to the target subreddit.- When using RSS fallback → include
source_used: "reddit_rss"field. scrape_multi→ call each subreddit independently; aggregate results intodataarray; setstatus: "partial"if any subreddit fails. Failed subreddits populateerrorsarray with{ subreddit, code, message }. Apply deduplication, NSFW filtering, and min_score across the combined dataset. Extractdrama_score,conflict_type,characters,setting, and target demographics for each post.
Error & Degraded States
- HTML block / rate limit →
status: "degraded",reason: "html_block_page", emptydata. - Missing subreddit →
status: "success",data: [],meta: { records_found: 0 }. - Partial multi-subreddit failure →
status: "partial",errors: [{ subreddit, code, message }].