How bader1919/pf-pipeline works
1. Repository purpose
This is a scheduled data pipeline for PropertyFinder Bahrain. Its main job is to scrape the marketplace daily, normalize the listings into analytics-friendly tables, detect changes over time, and publish both historical artifacts and a static dashboard.
2. Primary external boundary
The only major upstream system is PropertyFinder Bahrain itself. The scraper reaches a dynamic site and discovers subcategories at runtime, which matters because the source shape can change and the pipeline must adapt to multiple listing categories.
3. Scraping layer
The scraper/pf_scraper.py entrypoint is the acquisition layer. It collects six logical datasets mentioned in the README: residential rent/sale, commercial rent/sale, new projects, and agents. The raw outputs are stored as JSON and also archived compressed under data/raw_archive/YYYY-MM-DD/ for replay or re-cleaning.
4. Normalization layer
scraper/cleaner.py is the transformation boundary. It converts the raw scraped JSON into flat CSV snapshots with a fixed wide schema, preserving fields rather than discarding them. The README calls out 116 columns, so the cleaned layer is the canonical structured representation for downstream analysis.
5. Snapshot storage model
The repository uses three data states:
- data/latest/ for the current daily snapshot,
- data/previous/ for the prior snapshot used in comparisons,
- data/raw_archive/ for immutable raw history.
This makes the repo function as both codebase and artifact store, with Git history preserving the dataset over time.
6. Change detection and market intelligence
scraper/comparator.py compares today’s cleaned data against yesterday’s snapshot and appends deltas into data/changes/all_changes.csv, with daily slices in data/changes/YYYY-MM-DD.csv. The key signals are new, removed, and price_changed, which are the core demand-supply indicators the project is built to track.
7. Reporting and quality control
scraper/reporter.py generates summary outputs, while scraper/quality_gate.py enforces data checks before publishing. The presence of quality_report.json and quality_report.md in both latest and previous folders shows that quality is treated as a first-class release artifact, not just an internal log.
8. Dashboard publishing
scripts/update_dashboard.py feeds the static dashboard under dashboard/. The dashboard is a lightweight GitHub Pages site (dashboard/index.html) backed by dashboard/data.json, which means the visualization is static and data-driven rather than server-rendered.
9. Automation and orchestration
The pipeline is orchestrated by GitHub Actions workflows in .github/workflows/:
- daily_scrape.yml for the daily production run,
- update_dashboard.yml for refreshing the published dashboard,
- timing_study.yml for performance/timing capture.
This indicates a repo-native scheduled batch pipeline rather than a separate server or container platform.
10. Timing and observability
data/timing_study/ contains snapshots and a daily_log.jsonl, plus scraper/timing_analysis.py for analysis. This is a separate observability lane focused on understanding scrape timing and runtime behavior over days, likely to tune the daily schedule and reliability.
11. Reprocessing and backfill boundary
Because raw JSON is archived compressed, the pipeline supports backfilling or re-cleaning historical days if transformation logic changes. That is an important architectural boundary: acquisition is preserved independently from normalization, so downstream schema changes do not require re-scraping the source site.
12. Downstream consumption
The README explicitly mentions Power BI consuming data/latest/all_listings.csv through a GitHub raw URL. So the current snapshot is also an external contract for BI tools, not just an internal file. That means schema stability in all_listings.csv is a key interface.
13. Overall data flow
The end-to-end flow is: PropertyFinder site → raw scrape JSON → compressed archive → cleaned CSV snapshots → comparison/delta files → quality reports → dashboard JSON / static site, with GitHub Actions moving the pipeline forward on a schedule.
14. What to draw in an architecture diagram
The diagram should show three main zones: the external PropertyFinder source, the repo-based processing pipeline, and the publishing/consumption layer. Inside the repo, the major modules are acquisition, cleaning, comparison, quality/reporting, archival storage, and dashboard generation, with GitHub Actions as the scheduler and GitHub Pages/Power BI as the main outputs.
Main entry points: cleaner.py Cleaner · workflows GitHub Actions · raw_archive Raw JSON · latest Latest snapshot
Components 21
External source
Upstream marketplace boundary
- PropertyFinder BH · Dynamic upstream listing site discovered at runtime
Processing pipeline
Scrape, transform, compare, and validate
- Scraper · Main crawl and dataset collection flow
scraper/pf_scraper.py - Discovery · Finds categories and subcategories as the site shape changes
scraper/pf_scraper.py - Cleaner · Flattens raw listings into a fixed wide CSV schema
scraper/cleaner.py - Comparator · Computes new, removed, and price-changed listings
scraper/comparator.py - Quality gate · Checks snapshot quality before publishing
scraper/quality_gate.py - Reporter · Builds summary outputs from cleaned and changed data
scraper/reporter.py
Data stores
Snapshot, archive, and change history
- Raw JSON · Unnormalized dataset dumps for each logical listing set
data/raw_archive - Raw archive · Compressed daily raw snapshots for replay and backfill
data/raw_archive - Latest snapshot · Current daily structured outputs used as the repo contract
data/latest - Previous snapshot · Prior daily state used for diffing and rollbacks
data/previous - All listings · Unified structured table consumed by analytics and BI
data/latest/all_listings.csv - Change log · Daily and cumulative change files for market intelligence
data/changes - Quality report · JSON and markdown quality artifacts kept with snapshots
data/latest/quality_report.json
Publishing
Dashboard and downstream consumers
- Dashboard update · Builds the static dashboard payload from pipeline outputs
scripts/update_dashboard.py - Dashboard · GitHub Pages dashboard backed by JSON data
dashboard/index.html - Dashboard data · Static dashboard data bundle
dashboard/data.json - Power BI · External BI consumer of the stable latest CSV contract
Automation
Scheduled execution and refresh
- GitHub Actions · Runs daily scrape, dashboard refresh, and timing study workflows
.github/workflows
Observability
Timing and operational analysis
- Timing study · Captures runtime snapshots and daily timing logs
data/timing_study - Timing analysis · Analyzes scrape timing behavior over time
scraper/timing_analysis.py
Connections 23
- PropertyFinder BH → Discovery: dynamic pages · Source site shape is discovered at runtime
- Discovery → Scraper: category map · Discovery informs which listing branches to crawl
- Scraper → Raw JSON: collects · Writes logical datasets as raw JSON outputs
- Raw JSON → Raw archive: compresses · Archives immutable daily raw history
- Raw archive → Cleaner: replay/backfill · Historical raw data can be reprocessed later
- Raw JSON → Cleaner: normalize · Transforms scraped records into a wide schema
- Cleaner → Latest snapshot: writes · Publishes the current daily structured snapshot
- Cleaner → Previous snapshot: rolls forward · Previous snapshot is retained for comparisons
- Latest snapshot → All listings: unifies · Canonical combined CSV for downstream use
- Previous snapshot → Comparator: baseline · Yesterday's state is the comparison reference
- Latest snapshot → Comparator: compare · Today's state is diffed against the baseline
- Comparator → Change log: appends deltas · Writes daily and cumulative change artifacts
- Cleaner → Quality gate: validate · Checks the normalized snapshot before release
- Quality gate → Quality report: emits · Produces JSON and markdown quality reports
- Reporter → Quality report: summarizes · Generates reporting artifacts from pipeline outputs
- GitHub Actions → Scraper: daily scrape · Scheduled production acquisition run
- GitHub Actions → Dashboard update: refresh dashboard · Scheduled static site rebuild
- GitHub Actions → Timing study: timing run · Scheduled performance capture lane
- Dashboard update → Dashboard data: builds · Creates the JSON payload used by the site
- Dashboard data → Dashboard: drives · Static dashboard reads the generated data bundle
- Quality report → Dashboard update: quality input · Quality artifacts inform dashboard publishing
- All listings → Power BI: consumed by · Stable CSV contract is exposed to BI tools
- Timing study → Timing analysis: analyzed by · Snapshot and log artifacts feed timing analysis