Collect Regional Product Data without Mixing Markets
Use independent Playwright contexts for market conditions, preserve configured and observed values, and avoid treating language or stock as proof of regional availability.
Changing a locale does not guarantee a currency change. A regional exit also does not establish shipping eligibility. Sites may use cookies, accounts, and their own market controls.
This tutorial records two independent browsing conditions against one public practice product. That site can legitimately return GBP in both cases. Equal results must not be changed merely to make a comparison look regional.
Prepare the input addresses
Locate the following pages in your browser, confirm their contents, and copy their full addresses. Obtain service and repository addresses from account integration settings, official setup instructions, or the repository clone menu. Do not derive real addresses from illustrative output.
BOOK_DETAIL_URL: the Books to Scrape detail address for A Light in the Attic.
Set these in the same Bash/WSL terminal used for subsequent commands:
export BOOK_DETAIL_URL='<paste-the-actual-book-detail-url>'Replace each <VARIABLE_NAME> in JSON or task parameters with the copied value before submission; JSON does not expand environment variables. Any example.16yun.cn source in an output illustration shows field structure, not a demo service deployed for this article.
Separate conditions from observations
| Field | Meaning |
|---|---|
| Requested market | The task's intended label |
| Locale and timezone | Configured browser values |
| Egress origin | Echo-observed exit, not automatic country evidence |
| Document language | Page declaration |
| Price and currency | Source-specific amount contract |
| Availability text | Stock wording, not shipping permission |
| Shipping eligibility | Null without explicit evidence |
Install and configure
Use Python 3.12:
python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install playwright
python -m playwright install chromiumCreate regions.json:
[
{"market": "US", "locale": "en-US", "timezone_id": "America/New_York", "proxy": null},
{"market": "GB", "locale": "en-GB", "timezone_id": "Europe/London", "proxy": null}
]A null proxy leaves both contexts on the local network. For actual distinct exits, substitute your own supported configuration:
{"server":"http://proxy.16yun.cn:8888","username":"replace-with-user","password":"replace-with-password"}These are placeholders, not working credentials. See Playwright context configuration.
Collect a complete observation
Create regional_product.py:
import asyncio
import os
import json
from datetime import datetime, timezone
from pathlib import Path
from playwright.async_api import async_playwright
TARGET = os.environ["BOOK_DETAIL_URL"]
async def main():
regions = json.loads(Path("regions.json").read_text(encoding="utf-8"))
records = []
async with async_playwright() as pw:
browser = await pw.chromium.launch()
try:
for config in regions:
context = await browser.new_context(
locale=config["locale"],
timezone_id=config["timezone_id"],
proxy=config.get("proxy"),
)
try:
page = await context.new_page()
echo = await page.goto("https://httpbin.org/ip")
if echo is None or echo.status != 200:
raise ValueError("无法取得出口观察")
origin = (await echo.json()).get("origin")
response = await page.goto(TARGET)
if response is None or response.status != 200:
raise ValueError("商品页面加载失败")
await page.locator(".product_main h1").wait_for()
title = (await page.locator(".product_main h1").inner_text()).strip()
fields = {}
for row in await page.locator("table.table-striped tr").all():
key = (await row.locator("th").inner_text()).strip()
fields[key] = (await row.locator("td").inner_text()).strip()
price = fields.get("Price (incl. tax)")
if not title or not price or not price.startswith("£"):
raise ValueError("练习页价格合同不符合预期")
records.append({
"requested_market": config["market"],
"configured_locale": config["locale"],
"configured_timezone": config["timezone_id"],
"proxy_configured": config.get("proxy") is not None,
"egress_origin": origin,
"navigator_language": await page.evaluate("navigator.language"),
"document_language": await page.locator("html").get_attribute("lang"),
"title": title, "upc": fields.get("UPC"),
"price_display": price, "currency": "GBP",
"availability_text": fields.get("Availability"),
"shipping_eligibility": None,
"source_url": page.url,
"observed_at": datetime.now(timezone.utc).isoformat(),
})
except Exception as error:
records.append({
"requested_market": config["market"],
"status": "failed", "error_type": type(error).__name__,
})
finally:
await context.close()
finally:
await browser.close()
Path("regional-products.json").write_text(
json.dumps(records, ensure_ascii=False, indent=2), encoding="utf-8"
)
print({"conditions_checked": len(records)})
asyncio.run(main())Run:
python regional_product.pyEach condition has a separate context and cookie state. The export records proxy presence without exposing its credentials.
Interpret equality and difference
The known practice-site contract is GBP, so a US task label does not change the stored currency. Its stock wording provides no regional delivery evidence; shipping remains null.
When observations match, verify conditions and determine whether the site actually localizes. When they differ, align currency, tax, SKU, account, and observation time before comparing money.
An egress origin is not a country classification. If country verification matters, retain a deliberate geographic observation and its source rather than a proxy nickname.
Adapt to a market-aware store
Select the site's market independently in each context and read its actual market marker. Preserve cookie setup or account conditions where they control the result.
Read explicit currency codes or source-supported labels. The example's fixed GBP is a known-site adapter, not a universal symbol parser.
Availability may depend on postal code, delivery method, and variant. Separate stock, market sale permission, and address-level shipping eligibility.
Troubleshoot
Locale changes but price does not: inspect market and account rules.
Both exits match: null proxies make that expected; configured nodes may also share egress.
Login state leaks across conditions: inspect context and writable-profile reuse.
Prices differ for different variants: align business identity before comparing offers.
In stock but undeliverable: inspect shipping conditions rather than assuming the price extraction failed.
One condition fails: preserve its failure instead of copying another market's record.
Comparable regional data keeps configuration, network observations, and page business facts distinct.
Need an enterprise proxy plan?
We can tailor architecture to your target domains, concurrency, and reliability goals.