Scraping is a collection method, not a trading signal. An advertised price is not a completed sale; a job advertisement is not a hire. Turning either into a useful forecast requires a separate measurement argument and validation.
From a response to an observation
A small collection pipeline has distinct steps:
- Fetch: request an authorised page over HTTP, checking the response status, final URL, content type and encoding. Use finite timeouts and the service's documented collection limits. Python's
urllib.requestdocumentation describes the response object, headers, status and timeout parameter. - Parse: interpret the returned HTML structure. A parser exposes tags, attributes and text; it does not know which number represents the desired economic quantity. Python's
HTMLParsercalls handlers for these elements. Downloaded HTML may omit values inserted later by browser scripts. - Extract and validate: map selected elements into named fields, then check identifiers, numerical types, currencies, units, timestamps and missing values. Retain the response snapshot where permitted, a content hash and the parser version so a surprising observation can be traced back.
- Publish a usable dataset: apply declared identity, revision and availability rules before aggregating observations into a feature.
Three returned rows, two offers
| Retrieved at, UTC | Quote identifier | Advertised price, USD/item |
|---|---|---|
| 10:01 | Q1 | 20 |
| 10:02 | Q1 | 20 |
| 10:03 | Q2 | 30 |
The row mean is USD/item. It gives Q1 twice the weight of Q2. After removing the repeated quote, the intended mean is USD/item. This is a mean of two offers, not a sales-weighted price or a consumer price index.
The following offline Python example extracts attributes from deliberately simple authored HTML. It makes no network requests. The attributes supply the schema; this parser is not a general website collector.
from html.parser import HTMLParser
from statistics import mean
class OfferParser(HTMLParser):
def __init__(self):
super().__init__()
self.rows = []
def handle_starttag(self, tag, attrs):
if tag == "offer":
fields = dict(attrs)
if fields["currency"] != "USD":
raise ValueError("expected USD")
self.rows.append((fields["quote-id"], int(fields["price"])))
html = '''<offer quote-id="Q1" price="20" currency="USD"></offer>
<offer quote-id="Q1" price="20" currency="USD"></offer>
<offer quote-id="Q2" price="30" currency="USD"></offer>'''
parser = OfferParser()
parser.feed(html)
parser.close()
unique = {}
for quote_id, price in parser.rows:
if quote_id in unique and unique[quote_id] != price:
raise ValueError("conflicting quote version")
unique[quote_id] = price
print(len(parser.rows), len(unique))
print(f"{mean(p for _, p in parser.rows):.2f} {mean(unique.values()):.2f}")
# 3 2
# 23.33 25.00The page date cannot supply the availability clock
Suppose every offer above displays a quote time of 10:00, but collection finishes at 10:03 and validation finishes at 10:04 UTC. Under a rule requiring the complete validated snapshot, the two-offer mean becomes usable at 10:04. A 10:02 decision cannot consume it. A policy using partial snapshots would need its own explicit universe and cutoff rules.
A stable selector can still collect a different quantity
Collection rules and access rights are separate checks
robots.txt. Its introduction explicitly states that those rules are not access authorisation, and its security section distinguishes them from access controls. Respect the applicable crawler rules while separately establishing the permitted access and use, including relevant terms, data licences and privacy requirements. Public visibility alone does not settle those questions.robots.txt.Sources
- Koster, Illyes, Zeller and Sassman, RFC 9309: Robots Exclusion Protocol, September 2022, §§1, 2.2–2.4 and 3.
- Python documentation,
urllib.request: opening URLs,urlopenresponse and timeout documentation. - Python documentation,
html.parser: simple HTML and XHTML parser, class overview, methods and parser example. - Federal Reserve Bank of St. Louis, FRED API real-time periods, introduction.