PyPartPicker未正确使用代理的问题排查求助
PyPartPicker未正确使用代理的问题排查求助
我最近在做一个数据库更新工具,用PyPartPicker爬取PCPartPicker的配件信息,再上传到Supabase数据库。已经实现了异步功能,但一直碰到限流问题,所以想通过代理轮换避免请求被封。
通过日志能看到代理在正常循环切换,但代理后台完全看不到有流量使用。而且程序爬了大概8个配件后就卡在Browser Listening: 这个信息上,和不用代理时的情况一模一样。显然请求根本没用到代理,我是完全照着PyPartPicker的GitHub和PIP文档来配置的啊...
有没有办法能查看当前请求实际使用的IP?我猜会不会是必须用socks5代理?但我用的就是Webshare.io免费版的socks5代理啊。或者我哪里配置错了?求各位大佬帮忙看看🥺
import pypartpicker import time import random from supabase import create_client, Client import logging from requests.exceptions import HTTPError import requests_html import asyncio from itertools import cycle proxy_list = [ "socks5://lxpclygj:9bauszs4gj1x@198.23.239.134:6540", "socks5://lxpclygj:9bauszs4gj1x@207.244.217.165:6712", "socks5://lxpclygj:9bauszs4gj1x@107.172.163.27:6543", "socks5://lxpclygj:9bauszs4gj1x@64.137.42.112:5157", "socks5://lxpclygj:9bauszs4gj1x@173.211.0.148:6641", "socks5://lxpclygj:9bauszs4gj1x@161.123.152.115:6360", "socks5://lxpclygj:9bauszs4gj1x@167.160.180.203:6754", "socks5://lxpclygj:9bauszs4gj1x@154.36.110.199:6853", "socks5://lxpclygj:9bauszs4gj1x@173.0.9.70:5653", "socks5://lxpclygj:9bauszs4gj1x@173.0.9.209:5792", ] proxy_cycle = cycle(proxy_list) session = requests_html.HTMLSession() # Setup logging logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s") # Initialize Supabase client url = "***CENSORED***" # Replace with your Supabase URL key = "***CENSORED***" # Replace with your Supabase API key try: supabase: Client = create_client(url, key) logging.info("Connected to Supabase successfully.") except Exception as e: logging.error(f"Failed to connect to Supabase: {e}") exit(1) # Supported Product Types CPU_PRODUCTS = ["Intel Core i3", "Intel Core i5", "Intel Core i7", "Intel Core i9", "Intel Xeon", "AMD Ryzen 3", "AMD Ryzen 5", "AMD Ryzen 7", "AMD Ryzen 9", "AMD Threadripper", "AMD Athlon 3000G", "AMD Athlon 200GE", "Intel Pentium G6400", "Intel Pentium 5", "Intel Pentium 6", "Intel Pentium 7", "Intel Celeron G4", "Intel Celeron G5", "Intel Celeron G6"] def response_retriever(url): retries = 5 backoff_time = 2 # Initial backoff in seconds for _ in range(retries): proxy = next(proxy_cycle) # Rotate proxy try: logging.info(f"Using proxy {proxy} for {url}") response = session.get(url, proxies={"http": proxy, "https": proxy}) if response.status_code == 200: logging.info(f"Successfully retrieved response from {url} using proxy {proxy}") return response elif response.status_code == 429: logging.warning(f"Rate limited (429) for {url}. Retrying in {backoff_time}s...") time.sleep(backoff_time) backoff_time *= random.uniform(1.5, 2.0) # Exponential backoff else: logging.warning(f"Unexpected status code {response.status_code} for {url}") return None except requests_html.RequestException as e: logging.error(f"Failed to connect to {url} using proxy {proxy}: {e}") time.sleep(backoff_time) backoff_time *= random.uniform(1.5, 2.0) # Exponential backoff logging.error(f"Failed to retrieve a valid response after {retries} attempts for {url}") return None # Initialize PyPartPicker Client with the custom response retriever pcpp = pypartpicker.Client(response_retriever=response_retriever) async def fetch_top_parts(): async with pypartpicker.AsyncClient() as pcpp: # Counters for debugging error_count = 0 warning_count = 0 skipped_parts = [] # Iterate through each product type and fetch all results for product in CPU_PRODUCTS: page = 1 while True: try: logging.info(f"Fetching {product} parts on page {page}...") result = await pcpp.get_part_search(product, page=page, region="au") if result and result.parts: for part_summary in result.parts: if part_summary and part_summary.url: while True: try: proxy = next(proxy_cycle) logging.info(f"Using proxy {proxy} for {part_summary.url}") part = await pcpp.get_part(part_summary.url) if part: # Validate and prepare data for insertion in_stock_vendors = [ vendor for vendor in part.vendors if vendor.in_stock ] if part.vendors else [] in_stock_vendors.sort(key=lambda v: v.price.total if v.price else float('inf')) cheapest_vendor = in_stock_vendors[0] if in_stock_vendors else None data = { "part_type": "processor", "name": part.name if part.name else None, "total_price": cheapest_vendor.price.total if cheapest_vendor and cheapest_vendor.price else None, "base_price": cheapest_vendor.price.base if cheapest_vendor and cheapest_vendor.price else None, "discounts": cheapest_vendor.price.discounts if cheapest_vendor and cheapest_vendor.price else None, "shipping_price": cheapest_vendor.price.shipping if cheapest_vendor and cheapest_vendor.price else None, "tax_price": cheapest_vendor.price.tax if cheapest_vendor and cheapest_vendor.price else None, "vendor_store": getattr(cheapest_vendor, "name", "N/A") if cheapest_vendor else None, "store_product_url": getattr(cheapest_vendor, "buy_url", "N/A") if cheapest_vendor else None, "vendor_logo_url": getattr(cheapest_vendor, "logo_url", "N/A") if cheapest_vendor else None, "in_stock": bool(in_stock_vendors) and cheapest_vendor is not None, "product_url": getattr(part, "url", "N/A"), "image_urls": part.image_urls if part.image_urls else None, "manufacturer": part.specs.get("Manufacturer", None) if part.specs else None, "part_number": part.specs.get("Part #", None) if part.specs else None, "series": part.specs.get("Series", None) if part.specs else None, "microarchitecture": part.specs.get("Microarchitecture", None) if part.specs else None, "core_family": part.specs.get("Core Family", None) if part.specs else None, "socket": part.specs.get("Socket", None) if part.specs else None, "core_count": part.specs.get("Core Count", None) if part.specs else None, "thread_count": part.specs.get("Thread Count", None) if part.specs else None, "performance_core_clock": part.specs.get("Performance Core Clock", None) if part.specs else None, "performance_core_boost_clock": part.specs.get("Performance Core Boost Clock", None) if part.specs else None, "l2_cache": part.specs.get("L2 Cache", None) if part.specs else None, "l3_cache": part.specs.get("L3 Cache", None) if part.specs else None, "tdp": part.specs.get("TDP", None) if part.specs else None } # 此处省略Supabase数据插入逻辑 except Exception as e: logging.error(f"Error fetching part {part_summary.url}: {e}") error_count += 1 break else: logging.info(f"No more parts found for {product} on page {page}") break page += 1 except Exception as e: logging.error(f"Error fetching {product} page {page}: {e}") warning_count += 1 break asyncio.run(fetch_top_parts())
备注:内容来源于stack exchange,提问作者Stylus
相关产品推荐
相关产品推荐

