Browser Execution Observer
Library core untuk ekstraksi data lewat browser Chrome (CDP). Satu mesin yang sama dipakai untuk banyak sosial media: platform baru cukup dideskripsikan (URL, pola API, mapping field), tanpa menulis ulang sesi browser, scroll, capture, maupun parser.
Instalasi
pip install beo-mcdp
# opsional: pip install "beo-mcdp[kafka]" / "beo-mcdp[patchright]"
Cara kerja
- Browser membuka halaman (
Endpoint.url). - Library mendengarkan response API yang dipanggil halaman (
Endpoint.api_match). - JSON-nya diubah jadi list dict oleh
parser(biasanyaFieldMapper), di-dedupe lewatkey, lalu halaman di-scroll sampailimit/data habis.
Menambah platform baru
from cdp_scraper import (Endpoint, F, FieldMapper, Platform, Scraper,
const, make_scroller, register_platform, end_when_falsy)
parser = FieldMapper(
items="data.posts", # path ke list item
fields={
"id": ("id", "str", ""), # (path, transform, default)
"url": F(template="https://site.com/{author.handle}/{id}"),
"likes": ("stats.likes", "int", 0),
"tags": "tags[].name", # semua elemen
"posted": F("created", transform="iso_utc"),
"platform": const("site"),
},
)
site = Platform(
name="site", # juga jadi label log: [site] ...
cdp={"cdp_url": "http://localhost:9223"}, # opsional: Chrome/slot terpisah per platform
overlay_selectors=('div.popup-close',), # popup yang ditutup otomatis
login_url_hints=("/login",), # deteksi browser belum login
endpoints=[Endpoint(
"search", url="https://site.com/search?q={keyword}", api_match="api/search",
parser=parser, params=("keyword",), label="keyword", limit=20, max_limit=50,
end=end_when_falsy("has_more"),
scroll=make_scroller(wheel=2500, click_pattern="load more"),
)],
)
register_platform(site)
result = await Scraper("site").run("search", {"keyword": "kopi"}, limit=30) # satu query
results = await Scraper("site").run_many("search", [{"keyword": "a"}, {"keyword": "b"}])
run() melempar exception (PageCrashed, BrowserBusy, ValueError untuk parameter salah).
run_many() memakai satu tab untuk banyak query dan menjadikan error per-item status="error".
Contoh lengkap TikTok dan X/Twitter ada di examples/.
Mapping parsing (FieldMapper)
| Sintaks path | Arti |
|---|---|
a.b.c |
nilai bersarang |
a[0].b, a[-1] |
indeks |
a[].b |
semua elemen (hasil list) |
a[type=1].b |
elemen yang cocok filter (hasil list) |
Bentuk spec field: "path" · ("path", "transform", default) · F(path | any_of=[...] | template=... | fn=..., default=, transform=, required=) · const(x) · callable(record).
Opsi FieldMapper: item_path (sub-path record di tiap item), where / record_where
({path: nilai | EXISTS | callable} atau callable), unwrap (membuka pembungkus), items boleh
list path atau callable.
Transform bawaan: int float str bool url lower upper strip clean_text username hashtag iso_utc date_id join first count unique drop_empty dan each:<transform> untuk list. Argumen format tanggal:
iso_utc:%a %b %d %H:%M:%S %z %Y. Tambah sendiri: register_transform("nama", fn).
Jika logika terlalu rumit untuk mapping, gunakan F(fn=...) atau parser Python biasa
(parser= menerima callable apa pun yang mengembalikan list dict).
Hook & aksi halaman
prepare (setelah halaman terbuka) dan scroll (tiap putaran) adalah fungsi async def (page).
Bawaan: make_scroller(...), make_wait_for(selector), close_overlays(page, selectors).
Endpoint.capture_options meneruskan kwargs tambahan ke capture (poll_interval, settle, dst).
Konfigurasi browser
from cdp_scraper import CDPConfig, setup_cdp
setup_cdp(cdp_url="http://localhost:9222", max_sessions=2, lock_timeout=60) # default global
cfg = CDPConfig.from_env("TWITTER_") # TWITTER_CDP_URL, TWITTER_MAX_CONCURRENT_SESSIONS, ...
Setiap request memakai tab baru sendiri (ditutup saat selesai) dan dibatasi max_sessions
bersamaan per konfigurasi. Konfigurasi yang sama berbagi slot; cdp_url berbeda = slot berbeda.
Screenshot debug disimpan di CDPConfig.debug_dir (default folder kerja); matikan dengan
debug_screenshots=False.
Logging
Format seragam [job] Status message: detail, job = nama platform:
[2026-11-10 08:19:38] [INFO] [site] Success message: Capture api/search selesai: 20 data
Library hanya memakai logger cdp_scraper (tanpa handler). Aktifkan dengan setup_logging()
atau injeksi logger sendiri: setup_cdp(custom_logger=...). get_logger("kafka").error("...")
untuk log aplikasi dengan format yang sama.
Kafka / Redpanda
from cdp_scraper import RedpandaProducer, publish_chunks
producer = RedpandaProducer() # KAFKA_BOOTSTRAP_SERVERS; koneksi dibuat saat dipakai
if producer.available:
stats = publish_chunks(producer, "topic-x", keywords, chunk_size=2,
build_payload=lambda chunk: {"keywords": chunk})
# {"berhasil": n, "gagal": n}
Kontrak sumber data (keyword/akun) ada di cdp_scraper.utils.database (KeywordSource,
AccountSource); implementasinya milik aplikasi.
Pengujian
python -m unittest discover -s tests -t .
Tes memakai browser palsu, jadi tidak butuh Chrome/Kafka.
Perubahan dari 0.1.x (breaking)
- Konfigurasi sekarang
CDPConfig(immutable, per platform);setup_cdp(...)tetap ada. Variabel modulconfig.CDP_URLdst dihapus. get_session_slotsdanPW_ENGINEdihapus; pakaiCDPSessionManager/manager.engine.BrowserBusy(subclassTimeoutError) menggantikanTimeoutErrorpolos.helpers.close_login_modal(page, selectors)kini wajib diberi selector (tidak ada lagi selector TikTok bawaan).utils: tidak lagi mengimpor Flask;extract_challenges(khusus TikTok) dihapus;calculate_engagement_ratemenerimainteraction_keys/view_key(default sama dengan perilaku lama).utils.databasekini berupa Protocol;utils.redpanda_clienttidak lagi membuat producer saat import (gunakancdp_scraper.messaging).
Metadata
Release files for beo-mcdp 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| beo_mcdp-0.2.1.tar.gz | 26.5 kB | Without provenance | Details for beo_mcdp-0.2.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| beo_mcdp-0.2.1-py3-none-any.whl | Python 3 | none | any | Details for beo_mcdp-0.2.1-py3-none-any.whl |
Total release size: 55.7 kB
Release files / beo_mcdp-0.2.1.tar.gz
| Download URL | beo_mcdp-0.2.1.tar.gz |
|---|---|
| Size | 26.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5f7769526855e1ce9311e0aef545ed389fa79fcb26c7acebacd4b6dee9c84cbe
|
|
BLAKE2b-256 checksum How to use checksums |
1768612fda7b75e70e352767dd21b84a1d5a0515a69bb0f3e14839c14e49cb2c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.10.12
|
Release files / beo_mcdp-0.2.1-py3-none-any.whl
| Download URL | beo_mcdp-0.2.1-py3-none-any.whl |
|---|---|
| Size | 29.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
71fe3edf3238833f8b03e91b18ec8842f7aefce258fffa83e17a85f9ce2c5a45
|
|
BLAKE2b-256 checksum How to use checksums |
b3d1dd41a43f3412d3e65208c2f2bc9e44656a3580432f641ccdcf82e21beb69
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.10.12
|
Security for beo-mcdp 0.2.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.