
Twitter Search
- 140 installs
- 638 repo stars
- Updated March 7, 2026
- sundial-org/awesome-openclaw-skills
Use twitter-search for development tasks
About
twitter-search: A skill for development. This provides functionality for development workflows.
- twitter-search
Twitter Search by the numbers
- 140 all-time installs (skills.sh)
- +2 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #2,649 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/sundial-org/awesome-openclaw-skills --skill twitter-searchAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 140 |
|---|---|
| repo stars | ★ 638 |
| Last updated | March 7, 2026 |
| Repository | sundial-org/awesome-openclaw-skills ↗ |
What it does
Use twitter-search for development tasks
Files
Twitter Search and Analysis
Overview
Search Twitter for keywords using advanced search syntax, fetch up to 1000 relevant tweets, and analyze the data to produce professional reports with insights, statistics, and actionable recommendations.
Prerequisites
API Key Required: Users must configure their Twitter API key from https://twitterapi.io
The API key can be provided in three ways: 1. Environment variable (recommended): Set TWITTER_API_KEY in your ~/.bashrc or ~/.zshrc
echo 'export TWITTER_API_KEY="your_key_here"' >> ~/.bashrc
source ~/.bashrc2. As an argument: Use --api-key YOUR_KEY with the wrapper script 3. Passed directly: As first argument to the Python script
Quick Start
Using the Wrapper Script (Recommended)
The wrapper script automatically handles environment variable loading and dependency checks:
# Basic search (uses TWITTER_API_KEY from shell config)
./scripts/run_search.sh "AI"
# With custom API key
./scripts/run_search.sh "AI" --api-key YOUR_KEY
# With options
./scripts/run_search.sh "\"Claude AI\"" --max-results 100 --format summary
# Advanced query
./scripts/run_search.sh "from:elonmusk since:2024-01-01" --query-type LatestDirect Python Script Usage
# Search for a keyword
scripts/twitter_search.py "$API_KEY" "AI"
# Search with multiple keywords
scripts/twitter_search.py "$API_KEY" "\"ChatGPT\" OR \"Claude AI\""
# Search from specific user
scripts/twitter_search.py "$API_KEY" "from:elonmusk"
# Search with date range
scripts/twitter_search.py "$API_KEY" "Bitcoin since:2024-01-01"Advanced Queries
# Complex query: AI tweets from verified users, English only
scripts/twitter_search.py "$API_KEY" "AI OR \"machine learning\" lang:en filter:verified"
# Recent crypto tweets with minimum engagement
scripts/twitter_search.py "$API_KEY" "Bitcoin min_retweets:10 lang:en"
# From specific influencers
scripts/twitter_search.py "$API_KEY" "from:elonmusk OR from:VitalikButerin since:2024-01-01"Output Format
# Full JSON with all tweets
scripts/twitter_search.py "$API_KEY" "AI" --format json
# Summary with statistics (default)
scripts/twitter_search.py "$API_KEY" "AI" --format summaryOptions
--max-results N: Maximum tweets to fetch (default: 1000)--query-type Latest|Top: Sort order (default: Top for relevance)--format json|summary: Output format (default: summary)
Workflow
1. Understand User Requirements
Clarify the analysis goal:
- What topic/keyword to search?
- Date range preference?
- Specific users to include/exclude?
- Language preference?
- Type of insights needed (trends, sentiment, influencers)?
2. Build the Search Query
Use Twitter Advanced Search syntax:
| Syntax | Example | Description |
|---|---|---|
keyword | AI | Single keyword |
"phrase" | "machine learning" | Exact phrase |
OR | AI OR ChatGPT | Either term |
from:user | from:elonmusk | From specific user |
to:user | to:elonmusk | Reply to user |
since:DATE | since:2024-01-01 | After date |
until:DATE | until:2024-12-31 | Before date |
lang:xx | lang:en | Language code |
#hashtag | #AI | Hashtag |
filter:links | filter:links | Tweets with links |
min_retweets:N | min_retweets:100 | Minimum retweets |
3. Fetch Data
Execute the search script:
scripts/twitter_search.py "$API_KEY" "YOUR_QUERY" --max-results 1000 --query-type TopImportant: Default is 1000 tweets maximum. The script automatically:
- Paginates through all available results
- Stops at 1000 tweets (API limit consideration)
- Handles errors gracefully
4. Analyze and Generate Report
After fetching data, produce a comprehensive professional report with:
Report Structure
1. Executive Summary (2-3 sentences)
- What was searched
- Key findings overview
2. Data Overview
- Total tweets analyzed
- Date range of data
- Query parameters used
3. Key Metrics
- Total engagement (likes, retweets, replies, quotes, views)
- Average engagement per tweet
- Language distribution
- Reply vs. original tweet ratio
4. Top Content Analysis
- Most retweeted tweets (with URL links to original tweets)
- Most liked tweets (with URL links to original tweets)
- Top hashtags with frequency
- Most mentioned users
- Selected tweet examples with full URL references
5. Influencer Analysis
- Top users by follower count
- Most active users
- Verified user percentage
6. Trend Insights (based on data patterns)
- Emerging themes
- Sentiment indicators
- Temporal patterns
- Conversation drivers
7. Key Takeaways
- 3-5 bullet points of core insights
- Data-backed conclusions
8. Actionable Recommendations
- Specific, implementable suggestions
- Based on the data findings
- Prioritized by impact
Analysis Guidelines
- Be data-driven: Every claim should reference actual metrics
- Provide context: Explain why metrics matter
- Identify patterns: Look for trends across the dataset
- Stay objective: Present facts, avoid speculation
- Be specific: Recommendations should be concrete and actionable
- Consider external context: Use web search for background when relevant
5. Output Format
Present the report in clear markdown with:
- Headers for each section
- Tables for structured data
- Bullet points for lists
- Bold for key metrics
- Code blocks for tweet examples
- Clickable URLs for all referenced tweets (format:
[@username](https://x.com/username/status/tweet_id))
Tweet URL Format
Always include clickable links to tweets:
| Author | Tweet | URL |
|--------|-------|-----|
| @user | Summary of tweet content | [View](https://x.com/user/status/123456) |Or inline format:
- **@username**: Tweet summary - [View Tweet](https://x.com/username/status/123456)Query Examples by Use Case
Trend Analysis
"AI" OR "artificial intelligence" lang:en min_retweets:50Competitor Monitoring
from:competitor1 OR from:competitor2 since:2024-01-01Product Launch Tracking
#ProductName OR "Product Name" lang:en filter:verifiedCrisis Monitoring
#BrandName OR "Brand Name" lang:en --query-type LatestInfluencer Discovery
#Topic lang:en min_retweets:100 min_faves:500Sentiment Analysis
"brand name" OR #BrandName lang:en --max-results 1000Resources
scripts/run_search.sh (Wrapper Script)
Convenience wrapper that handles environment variable loading and dependency checks:
- Automatically loads
TWITTER_API_KEYfrom~/.bashrcor~/.zshrc - Checks Python availability and installs missing dependencies
- Provides user-friendly error messages
- Supports all command-line options from the Python script
Usage:
./scripts/run_search.sh <query> [options]Options:
--api-key KEY: Override environment variable API key--max-results N: Maximum tweets to fetch (default: 1000)--query-type Latest|Top: Sort order (default: Top)--format json|summary: Output format (default: json)
scripts/twitter_search.py
Executable Python script that:
- Fetches tweets from Twitter API
- Handles pagination automatically
- Extracts key tweet metrics
- Calculates aggregate statistics
- Outputs structured JSON data
Usage:
scripts/twitter_search.py <api_key> <query> [options]references/twitter_api.md
Comprehensive API documentation including:
- Complete parameter reference
- Query syntax guide
- Response structure details
- Pagination instructions
- Best practices for analysis
- Error handling guide
Read this when: Building complex queries or understanding data structure.
Tips for Better Analysis
1. Use Top query type for trend analysis (more relevant results) 2. Set date filters for timely insights 3. Filter by language for accurate text analysis 4. Include minimum engagement to filter noise 5. Combine with web search to validate trends 6. Look beyond metrics - analyze content themes 7. Track hashtags to identify sub-conversations 8. Identify influencers by combining followers + engagement
Error Handling
If the script fails:
- Check API key validity
- Verify query syntax
- Ensure network connectivity
- Check rate limits (if applicable)
- Review error messages for specific issues
twitter-search-skill
Twitter API Reference
This document provides detailed reference information for the Twitter Advanced Search API.
API Endpoint
- URL:
https://api.twitterapi.io/twitter/tweet/advanced_search - Method:
GET - Documentation: https://docs.twitterapi.io/api-reference/endpoint/tweet_advanced_search
Authentication
- Header:
X-API-Key - Type: Bearer token / API key
- Required: Yes
The API key should be obtained from https://twitterapi.io
Request Parameters
Query Parameter (query)
The search query supports Twitter's advanced search syntax:
Basic Keywords
- Single word:
AI - Multiple words:
"artificial intelligence" - OR logic:
AI OR "machine learning" - AND logic:
AI "machine learning"(implicit AND)
User Filtering
- From specific user:
from:username - To specific user:
to:username - Mentioning user:
@username
Date Filtering
- Since date:
since:2024-01-01 - Until date:
until:2024-12-31 - Combined:
since:2024-01-01 until:2024-12-31
Language Filtering
- Specific language:
lang:en(English) - Language codes: en, es, fr, de, ja, zh, etc.
Content Type Filtering
- Hashtags:
#hashtag - Links:
filter:links - Replies:
filter:replies - Media:
filter:media - Verified users:
filter:verified
Engagement Filtering
- Minimum retweets:
min_retweets:10 - Minimum favorites:
min_faves:100 - Minimum replies:
min_replies:5
Complex Query Examples
# AI-related tweets from verified users in English
AI OR "machine learning" lang:en filter:verified
# Recent tweets about Bitcoin from influencers
Bitcoin from:elonmusk OR from:VitalikButerin since:2024-01-01
# Tweets with links about climate change
"climate change" filter:links lang:en
# Popular tweets about tech
tech min_retweets:100 min_faves:500Reference: https://github.com/igorbrigadir/twitter-advanced-search
Query Type (queryType)
- Values:
LatestorTop - Default:
Latest - Description:
Latest: Most recent tweets firstTop: Most relevant/popular tweets first (recommended for analysis)
Cursor (cursor)
- Type: String
- Default:
""(empty for first page) - Description: Pagination token for fetching subsequent pages
Response Format
Top-Level Structure
{
"tweets": [...], // Array of tweet objects
"has_next_page": true, // Boolean: more results available
"next_cursor": "..." // String: cursor for next page
}Tweet Object Structure
Core Fields
| Field | Type | Description |
|---|---|---|
id | string | Unique tweet identifier |
url | string | Tweet URL (e.g., https://x.com/user/status/123) |
text | string | Tweet content |
createdAt | string | Creation timestamp (e.g., "Tue Dec 10 07:00:30 +0000 2024") |
lang | string | Language code (e.g., "en", "es") |
source | string | Source app (e.g., "Twitter for iPhone") |
Engagement Metrics
| Field | Type | Description |
|---|---|---|
retweetCount | integer | Number of retweets |
replyCount | integer | Number of replies |
likeCount | integer | Number of likes |
quoteCount | integer | Number of quote tweets |
viewCount | integer | Number of views |
bookmarkCount | integer | Number of bookmarks |
Reply/Thread Fields
| Field | Type | Description |
|---|---|---|
isReply | boolean | Whether this is a reply |
inReplyToId | string | ID of the tweet being replied to |
inReplyToUserId | string | ID of the user being replied to |
inReplyToUsername | string | Username of the user being replied to |
conversationId | string | Thread/conversation identifier |
displayTextRange | array | Visible text range indices |
Author Object
| Field | Type | Description |
|---|---|---|
id | string | User ID |
userName | string | Username (handle) |
name | string | Display name |
url | string | Profile URL |
description | string | Profile bio |
location | string | User location |
followers | integer | Follower count |
following | integer | Following count |
statusesCount | integer | Total tweets posted |
favouritesCount | integer | Total likes given |
mediaCount | integer | Total media posts |
isBlueVerified | boolean | Twitter Blue verification status |
verifiedType | string | Verification type (e.g., "government") |
createdAt | string | Account creation date |
profilePicture | string | Profile image URL |
coverPicture | string | Cover image URL |
Entities Object
Hashtags (entities.hashtags)
[{
"text": "AI",
"indices": [0, 3]
}]URLs (entities.urls)
[{
"url": "https://t.co/...",
"expanded_url": "https://example.com/full-url",
"display_url": "example.com/full-url",
"indices": [10, 33]
}]Mentions (entities.user_mentions)
[{
"id_str": "123456",
"screen_name": "username",
"name": "Display Name"
}]Nested Tweets
| Field | Type | Description |
|---|---|---|
quoted_tweet | object/null | If this is a quote tweet, the quoted tweet |
retweeted_tweet | object/null | If this is a retweet, the original tweet |
Pagination
Each page returns up to 20 tweets. To fetch more:
1. Check has_next_page in the response 2. If true, use next_cursor as the cursor parameter for the next request 3. Continue until has_next_page is false or desired count is reached
Rate Limits
- The API may have rate limits (check twitterapi.io for current limits)
- Implement exponential backoff for retries if needed
- Consider caching results for repeated queries
Error Handling
HTTP Status Codes
| Code | Meaning |
|---|---|
| 200 | Success |
| 400 | Bad Request (invalid query parameters) |
| 401 | Unauthorized (invalid API key) |
| 429 | Rate limit exceeded |
| 500 | Server error |
Common Errors
- Invalid query syntax
- Missing or expired API key
- Network timeout
- Rate limiting
Best Practices for Analysis
1. Use `Top` query type for analyzing trends and popular content 2. Filter by language when doing sentiment analysis 3. Set date ranges to get relevant, timely data 4. Use `min_retweets` or `min_faves` to filter for quality content 5. Consider engagement metrics when ranking tweets by importance 6. Handle multiple languages in text analysis 7. Extract hashtags and mentions for network analysis 8. Track conversation threads using conversationId
Data Analysis Tips
Key Metrics to Track
1. Engagement rate: (likes + retweets) / followers 2. Virality: retweets and quotes 3. Discussion depth: reply count 4. Reach: view count 5. Sentiment: Analyze text content 6. Influencer identification: High follower count + high engagement
Common Analysis Patterns
1. Trend detection: Cluster by hashtags and keywords 2. Influencer analysis: Sort by follower count and engagement 3. Sentiment analysis: Use NLP on tweet text 4. Temporal analysis: Group by createdAt timestamps 5. Network analysis: Build graph from mentions and replies 6. Content analysis: Extract URLs, hashtags, and media
#!/bin/bash
#
# Twitter Search Wrapper Script
# This script handles environment variable loading and provides a convenient interface
# for running the Twitter search analysis.
#
set -e
# Script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PARENT_DIR="$(dirname "$SCRIPT_DIR")"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Function to print error and exit
error_exit() {
echo -e "${RED}Error: $1${NC}" >&2
exit 1
}
# Function to print warning
warn() {
echo -e "${YELLOW}Warning: $1${NC}" >&2
}
# Check if TWITTER_API_KEY is set
if [[ -z "$TWITTER_API_KEY" ]]; then
# Try to source .bashrc to get the API key
if [[ -f "$HOME/.bashrc" ]]; then
# Source .bashrc and extract TWITTER_API_KEY
eval "$(grep -E '^export TWITTER_API_KEY=' "$HOME/.bashrc" 2>/dev/null || true)"
fi
# Still not set? Try .zshrc
if [[ -z "$TWITTER_API_KEY" && -f "$HOME/.zshrc" ]]; then
eval "$(grep -E '^export TWITTER_API_KEY=' "$HOME/.zshrc" 2>/dev/null || true)"
fi
# If still not set, show error
if [[ -z "$TWITTER_API_KEY" ]]; then
error_exit "TWITTER_API_KEY is not set. Please set it in your shell config or pass as --api-key argument.
Get your API key from: https://twitterapi.io
To set it permanently:
echo 'export TWITTER_API_KEY=\"your_key_here\"' >> ~/.bashrc
source ~/.bashrc"
fi
warn "TWITTER_API_KEY loaded from shell config file"
fi
# Check Python is available
if ! command -v python3 &> /dev/null; then
error_exit "python3 is not installed. Please install Python 3."
fi
# Check if requests module is available
if ! python3 -c "import requests" 2>/dev/null; then
warn "requests module not found. Attempting to install..."
pip3 install requests --user
fi
# Default values
MAX_RESULTS=${MAX_RESULTS:-1000}
QUERY_TYPE=${QUERY_TYPE:-Top}
FORMAT=${FORMAT:-json}
# Parse command line arguments
QUERY=""
API_KEY=""
while [[ $# -gt 0 ]]; do
case $1 in
--api-key)
API_KEY="$2"
shift 2
;;
--max-results)
MAX_RESULTS="$2"
shift 2
;;
--query-type)
QUERY_TYPE="$2"
shift 2
;;
--format)
FORMAT="$2"
shift 2
;;
-*)
error_exit "Unknown option: $1"
;;
*)
if [[ -z "$QUERY" ]]; then
QUERY="$1"
else
error_exit "Too many arguments. Only one query is allowed."
fi
shift
;;
esac
done
# Use provided API key or environment variable
if [[ -n "$API_KEY" ]]; then
TWITTER_API_KEY="$API_KEY"
fi
# Validate query
if [[ -z "$QUERY" ]]; then
error_exit "No query specified. Usage: $0 \"your search query\" [options]
Examples:
$0 \"AI\"
$0 \"from:elonmusk\"
$0 \"Claude OR ChatGPT\" --max-results 100
$0 \"Bitcoin\" --query-type Latest --format summary"
fi
# Display mask for API key (show only first 8 chars)
API_KEY_MASK="${TWITTER_API_KEY:0:8}..."
echo -e "${GREEN}Twitter Search Analysis${NC}" >&2
echo "Query: $QUERY" >&2
echo "Max Results: $MAX_RESULTS" >&2
echo "Query Type: $QUERY_TYPE" >&2
echo "API Key: $API_KEY_MASK" >&2
echo "---" >&2
# Run the Python script
python3 "$SCRIPT_DIR/twitter_search.py" "$TWITTER_API_KEY" "$QUERY" \
--max-results "$MAX_RESULTS" \
--query-type "$QUERY_TYPE" \
--format "$FORMAT"
#!/usr/bin/env python3
"""
Twitter Advanced Search Script for Claude Code Skill
This script fetches tweets from the Twitter API using advanced search,
and returns the data in a structured format for analysis.
Requirements:
- requests library (pip install requests)
Usage:
python twitter_search.py <api_key> <query> [--max-results MAX_RESULTS]
Environment variable:
TWITTER_API_KEY - Alternatively, set this environment variable
API Documentation:
https://docs.twitterapi.io/api-reference/endpoint/tweet_advanced_search
Query Syntax:
Basic: "keyword"
Multiple keywords: "AI" OR "ChatGPT"
From user: from:username
Since date: since:2024-01-01
Complex: "AI" OR "ChatGPT" from:elonmusk since:2024-01-01
More examples: https://github.com/igorbrigadir/twitter-advanced-search
"""
import argparse
import json
import os
import sys
from typing import Dict, List, Any, Optional
from datetime import datetime
try:
import requests
except ImportError:
print("Error: 'requests' library is required. Install it with: pip install requests")
sys.exit(1)
# Constants
API_BASE_URL = "https://api.twitterapi.io/twitter/tweet/advanced_search"
DEFAULT_MAX_RESULTS = 1000
RESULTS_PER_PAGE = 20
class TwitterSearchError(Exception):
"""Custom exception for Twitter search errors."""
pass
def get_api_key(api_key_arg: Optional[str]) -> str:
"""
Get API key from argument or environment variable.
Args:
api_key_arg: API key passed as argument
Returns:
The API key to use
Raises:
TwitterSearchError: If no API key is provided
"""
api_key = api_key_arg or os.environ.get("TWITTER_API_KEY")
if not api_key:
raise TwitterSearchError(
"API key is required. Provide it as an argument or set TWITTER_API_KEY environment variable."
)
return api_key
def fetch_tweets(api_key: str, query: str, query_type: str = "Top", cursor: str = "") -> Dict[str, Any]:
"""
Fetch a single page of tweets from the Twitter API.
Args:
api_key: Twitter API key
query: Search query string
query_type: Query type ("Latest" or "Top")
cursor: Pagination cursor (empty string for first page)
Returns:
JSON response from the API
Raises:
TwitterSearchError: If the API request fails
"""
headers = {
"X-API-Key": api_key,
"Content-Type": "application/json"
}
params = {
"query": query,
"queryType": query_type,
"cursor": cursor
}
try:
response = requests.get(API_BASE_URL, headers=headers, params=params, timeout=30)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
raise TwitterSearchError(f"API request failed: {str(e)}")
def fetch_all_tweets(api_key: str, query: str, max_results: int = DEFAULT_MAX_RESULTS,
query_type: str = "Top") -> List[Dict[str, Any]]:
"""
Fetch all tweets up to max_results using pagination.
Args:
api_key: Twitter API key
query: Search query string
max_results: Maximum number of results to fetch
query_type: Query type ("Latest" or "Top")
Returns:
List of tweet objects
Raises:
TwitterSearchError: If fetching tweets fails
"""
all_tweets = []
cursor = ""
page_count = 0
max_pages = (max_results + RESULTS_PER_PAGE - 1) // RESULTS_PER_PAGE
while len(all_tweets) < max_results:
try:
data = fetch_tweets(api_key, query, query_type, cursor)
page_count += 1
# Extract tweets from response
tweets = data.get("tweets", [])
if not tweets:
break
all_tweets.extend(tweets)
# Check if we've reached max_results
if len(all_tweets) >= max_results:
all_tweets = all_tweets[:max_results]
break
# Check if there's a next page
has_next = data.get("has_next_page", False)
if not has_next:
break
cursor = data.get("next_cursor", "")
# Safety check to prevent infinite loops
if page_count >= max_pages + 5:
print(f"Warning: Reached maximum page limit ({page_count} pages)", file=sys.stderr)
break
except TwitterSearchError as e:
print(f"Warning: Failed to fetch page {page_count + 1}: {str(e)}", file=sys.stderr)
break
return all_tweets
def extract_tweet_summary(tweet: Dict[str, Any]) -> Dict[str, Any]:
"""
Extract key information from a tweet for summary output.
Args:
tweet: Raw tweet object from API
Returns:
Simplified tweet summary dictionary
"""
author = tweet.get("author", {})
return {
"id": tweet.get("id"),
"url": tweet.get("url"),
"text": tweet.get("text"),
"created_at": tweet.get("createdAt"),
"lang": tweet.get("lang"),
"metrics": {
"retweets": tweet.get("retweetCount", 0),
"replies": tweet.get("replyCount", 0),
"likes": tweet.get("likeCount", 0),
"quotes": tweet.get("quoteCount", 0),
"views": tweet.get("viewCount", 0),
"bookmarks": tweet.get("bookmarkCount", 0)
},
"author": {
"username": author.get("userName"),
"name": author.get("name"),
"followers": author.get("followers", 0),
"verified": author.get("isBlueVerified", False)
},
"hashtags": [h.get("text") for h in tweet.get("entities", {}).get("hashtags", [])],
"mentions": [m.get("screen_name") for m in tweet.get("entities", {}).get("user_mentions", [])],
"is_reply": tweet.get("isReply", False),
"conversation_id": tweet.get("conversationId")
}
def calculate_statistics(tweets: List[Dict[str, Any]]) -> Dict[str, Any]:
"""
Calculate aggregate statistics from tweets.
Args:
tweets: List of tweet summary objects
Returns:
Dictionary with various statistics
"""
if not tweets:
return {}
total_likes = sum(t.get("metrics", {}).get("likes", 0) for t in tweets)
total_retweets = sum(t.get("metrics", {}).get("retweets", 0) for t in tweets)
total_replies = sum(t.get("metrics", {}).get("replies", 0) for t in tweets)
total_quotes = sum(t.get("metrics", {}).get("quotes", 0) for t in tweets)
total_views = sum(t.get("metrics", {}).get("views", 0) for t in tweets)
# Language distribution
languages = {}
for t in tweets:
lang = t.get("lang", "unknown")
if not lang:
lang = "unknown"
languages[lang] = languages.get(lang, 0) + 1
# Top hashtags
all_hashtags = []
for t in tweets:
all_hashtags.extend(t.get("hashtags", []))
hashtag_counts = {}
for tag in all_hashtags:
hashtag_counts[tag] = hashtag_counts.get(tag, 0) + 1
# Top mentioned users
all_mentions = []
for t in tweets:
all_mentions.extend(t.get("mentions", []))
mention_counts = {}
for mention in all_mentions:
mention_counts[mention] = mention_counts.get(mention, 0) + 1
# Reply vs original tweets
reply_count = sum(1 for t in tweets if t.get("is_reply", False))
# Most influential authors (by followers)
authors = {}
for t in tweets:
username = t.get("author", {}).get("username")
if username:
if username not in authors:
authors[username] = {
"name": t.get("author", {}).get("name"),
"followers": t.get("author", {}).get("followers", 0),
"verified": t.get("author", {}).get("verified", False),
"tweet_count": 0
}
authors[username]["tweet_count"] += 1
return {
"total_tweets": len(tweets),
"total_engagement": {
"likes": total_likes,
"retweets": total_retweets,
"replies": total_replies,
"quotes": total_quotes,
"views": total_views
},
"averages": {
"likes_per_tweet": round(total_likes / len(tweets), 2),
"retweets_per_tweet": round(total_retweets / len(tweets), 2),
"replies_per_tweet": round(total_replies / len(tweets), 2)
},
"language_distribution": dict(sorted(languages.items(), key=lambda x: x[1], reverse=True)[:10]),
"top_hashtags": dict(sorted(hashtag_counts.items(), key=lambda x: x[1], reverse=True)[:20]),
"top_mentions": dict(sorted(mention_counts.items(), key=lambda x: x[1], reverse=True)[:20]),
"reply_ratio": round(reply_count / len(tweets) * 100, 2),
"top_authors_by_followers": sorted(
[{"username": k, **v} for k, v in authors.items()],
key=lambda x: x["followers"],
reverse=True
)[:10],
"most_active_authors": sorted(
[{"username": k, **v} for k, v in authors.items()],
key=lambda x: x["tweet_count"],
reverse=True
)[:10]
}
def main():
"""Main entry point for the script."""
parser = argparse.ArgumentParser(
description="Search Twitter using advanced search and analyze results"
)
parser.add_argument("api_key", nargs="?", help="Twitter API key (or set TWITTER_API_KEY env var)")
parser.add_argument("query", help="Search query (e.g., 'AI' OR 'ChatGPT' from:elonmusk)")
parser.add_argument("--max-results", type=int, default=DEFAULT_MAX_RESULTS,
help=f"Maximum results to fetch (default: {DEFAULT_MAX_RESULTS})")
parser.add_argument("--query-type", choices=["Latest", "Top"], default="Top",
help="Query type (default: Top)")
parser.add_argument("--format", choices=["json", "summary"], default="summary",
help="Output format (default: summary)")
args = parser.parse_args()
try:
# Get API key
api_key = get_api_key(args.api_key)
# Fetch tweets
print(f"Searching for: {args.query}", file=sys.stderr)
print(f"Query type: {args.query_type}", file=sys.stderr)
print(f"Max results: {args.max_results}", file=sys.stderr)
print(file=sys.stderr)
raw_tweets = fetch_all_tweets(api_key, args.query, args.max_results, args.query_type)
if not raw_tweets:
print("No tweets found.", file=sys.stderr)
sys.exit(0)
print(f"Fetched {len(raw_tweets)} tweets.", file=sys.stderr)
# Process tweets
tweet_summaries = [extract_tweet_summary(t) for t in raw_tweets]
statistics = calculate_statistics(tweet_summaries)
# Output results
result = {
"query": args.query,
"query_type": args.query_type,
"fetched_at": datetime.utcnow().isoformat() + "Z",
"total_tweets": len(tweet_summaries),
"statistics": statistics,
"tweets": tweet_summaries if args.format == "json" else []
}
print(json.dumps(result, ensure_ascii=False, indent=2))
except TwitterSearchError as e:
print(f"Error: {str(e)}", file=sys.stderr)
sys.exit(1)
except KeyboardInterrupt:
print("\nInterrupted by user", file=sys.stderr)
sys.exit(1)
except Exception as e:
print(f"Unexpected error: {str(e)}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()