Polite, robots.txt-respecting scraper for public Business Standard news, with sentiment + stock mapping for Indian-market research.
Project description
business-standard-scraper-safe
A polite, robots.txt-respecting Python library that collects public Business Standard news for Indian market sentiment and swing-trading research.
This package is a data collector only. Prediction logic belongs in a separate package (e.g. swing_prediction_engine).
Features
- Sitemap + RSS ingestion, deduped by URL
robots.txtenforcement on every request- Polite client: configurable delay, retry/backoff, timeout, structured logging
- Article parsing: title, summary, body, published date
- SHA256 content-hash deduplication
- Stock-symbol mapping against an NSE master list
- Structured sentiment output:
sentiment,impact,confidence,reason - Storage: CSV snapshots + SQLite upsert (PostgreSQL-ready schema)
- CLI (
bs-scraper) and importable Python API
Install
pip install business-standard-scraper-safe
Quick start
CLI
bs-scraper --limit 100 --category markets
bs-scraper --limit 50 --category all --db data/business_standard.db
CLI flags:
| Flag | Default | Description |
|---|---|---|
--limit |
50 |
Max URLs to process |
--category |
all |
markets, companies, economy, finance, ipo, commodities, industry, technology, india, world, opinion, or all |
--db |
data/business_standard.db |
SQLite path |
--log-file |
business_standard_scraper.log |
Log path |
Python API
from bs_scraper import run, fetch_all_urls, enrich_articles, analyze, setup_logging
setup_logging()
# Full pipeline (sitemap+RSS → enrich → dedup → sentiment → stocks → CSV+SQLite)
df = run(limit=100, category="markets")
# Or use the building blocks
urls_df = fetch_all_urls(limit=200)
articles_df = enrich_articles(urls_df.head(50))
print(analyze("Reliance posts record profit and beats estimates"))
Pipeline
Sitemap + RSS
↓
Filter by robots.txt
↓
Fetch public article pages (delay + retry)
↓
Parse title / summary / body / date
↓
Deduplicate (sha256 content hash)
↓
Map stock symbols (NSE)
↓
Sentiment + impact + confidence + reason
↓
SQLite upsert + CSV snapshot
↓
Consumed by your prediction engine
Output schema
CSV files land in data/clean/business_standard_news_<timestamp>.csv.
SQLite table news_clean (primary key news_id, upserted on conflict):
| Column | Description |
|---|---|
news_id |
sha256(title + url) |
source |
business_standard |
category |
markets, companies, … |
title, summary, article_text |
parsed text |
url, published_at |
source + ISO 8601 date |
sentiment |
Bullish / Bearish / Neutral |
impact |
High / Medium / Low |
confidence |
0–95 |
reason |
short explanation of detected cues |
sentiment_score |
raw integer (positive − negative cues) |
matched_stocks |
comma-separated NSE symbols |
inserted_at |
ISO 8601 |
Sentiment payload
{
"sentiment": "Bullish",
"impact": "High",
"confidence": 82,
"reason": "Positive cues: order, growth, wins"
}
Currently Level 1 (keyword-based). Upgrade path: FinBERT → LLM sentiment → market-impact classifier. Swap the body of bs_scraper/sentiment.py::analyze to upgrade.
Stock mapping
Ships with a small NSE sample. Drop a CSV at data/stocks_master.csv with columns symbol,name to use a full universe:
symbol,name
RELIANCE.NS,Reliance Industries
TCS.NS,Tata Consultancy Services
Rules of engagement
This library deliberately does not:
- ignore
robots.txt - scrape disallowed paths (
/api/,/_next/,/static/,/assets/,/search?) - bypass paywalls, login, captcha, Cloudflare, or rate limits
- spoof browsers or rotate identities
If a path or feed is blocked, it is logged and skipped.
Project layout
business_standard_scraper_safe/
├── pyproject.toml
├── LICENSE
├── MANIFEST.in
├── README.md
├── PUBLISHING.md
├── main.py
└── bs_scraper/
├── __init__.py
├── cli.py
├── pipeline.py
├── config.py
├── http_client.py
├── robots_checker.py
├── sitemap_collector.py
├── rss_collector.py
├── html_collector.py
├── enrichment.py
├── parser.py
├── sentiment.py
├── stocks.py
├── storage.py
└── logging_setup.py
Publishing
See PUBLISHING.md. Never paste API tokens into chat, commits, or logs. Use environment variables (TWINE_USERNAME=__token__, TWINE_PASSWORD=pypi-…) or a chmod-600 ~/.pypirc.
Roadmap
- Full NSE master list at
data/stocks_master.csv - FinBERT / LLM sentiment
- Source reliability score
- FastAPI endpoints
- Scheduler (cron / APScheduler)
- Combine with Moneycontrol, ET, LiveMint
- PostgreSQL storage with
UNIQUE(news_id) ON CONFLICT DO UPDATE
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file business_standard_scraper_safe-0.1.1.tar.gz.
File metadata
- Download URL: business_standard_scraper_safe-0.1.1.tar.gz
- Upload date:
- Size: 15.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9ce30beb7b7c701d61ae40679e87cdfaf01b7e3c5f6f4e1b2650d5a293ea6162
|
|
| MD5 |
274b84d2bbe391b324cdd2e7d52fd5b2
|
|
| BLAKE2b-256 |
406a2701b29a3d98813ceb1541271125c9f375c9ca2293a44a93965100a48d7d
|
File details
Details for the file business_standard_scraper_safe-0.1.1-py3-none-any.whl.
File metadata
- Download URL: business_standard_scraper_safe-0.1.1-py3-none-any.whl
- Upload date:
- Size: 17.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ec49f6836e775aabf27ab7fbdf5b20062b797b912bcc5a0f1172256a18ee6a82
|
|
| MD5 |
cf39b9961e00a6d150152bd81f764364
|
|
| BLAKE2b-256 |
69b028449c7a4b277969765fc866551300be18e356dc34b74d16c54384f5e322
|