start project
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
"""Lightweight browser/OS classification for human traffic (Chapter 08).
|
||||
|
||||
Separate from Chapter 07's bot_identifier — that identifies automated
|
||||
crawlers via UA substring + DNS verification. This classifies ordinary
|
||||
browsers/OSes, same ordered-substring-match pattern, signatures as JSON
|
||||
data (not hardcoded), no third-party UA-parsing dependency — consistent
|
||||
with the low-footprint bias in Chapter 03.
|
||||
|
||||
Order matters within each signature list: e.g. Edge/Opera must be checked
|
||||
before Chrome (their UAs also contain "Chrome/"); iOS before macOS (iPhone
|
||||
UAs also contain "like Mac OS X"); Android before Linux (Android UAs also
|
||||
contain "Linux").
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
_DATA_DIR = Path(__file__).parent / "data"
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class UASignature:
|
||||
name: str
|
||||
ua_substrings: tuple[str, ...]
|
||||
|
||||
|
||||
def _load(filename: str) -> list[UASignature]:
|
||||
raw = json.loads((_DATA_DIR / filename).read_text())
|
||||
return [UASignature(name=e["name"], ua_substrings=tuple(e["ua_substrings"])) for e in raw]
|
||||
|
||||
|
||||
_BROWSER_SIGNATURES = _load("browser_signatures.json")
|
||||
_OS_SIGNATURES = _load("os_signatures.json")
|
||||
|
||||
|
||||
def _match(user_agent: str, signatures: list[UASignature], default: str) -> str:
|
||||
for sig in signatures:
|
||||
if any(sub in user_agent for sub in sig.ua_substrings):
|
||||
return sig.name
|
||||
return default
|
||||
|
||||
|
||||
def classify_browser(user_agent: str | None) -> str:
|
||||
if not user_agent:
|
||||
return "Unknown"
|
||||
return _match(user_agent, _BROWSER_SIGNATURES, "Other")
|
||||
|
||||
|
||||
def classify_os(user_agent: str | None) -> str:
|
||||
if not user_agent:
|
||||
return "Unknown"
|
||||
return _match(user_agent, _OS_SIGNATURES, "Other")
|
||||
Reference in New Issue
Block a user