{"id":97387,"date":"2026-08-29T11:40:45","date_gmt":"2026-08-29T03:40:45","guid":{"rendered":"https:\/\/www.wsisp.com\/helps\/97387.html"},"modified":"2026-08-29T11:40:45","modified_gmt":"2026-08-29T03:40:45","slug":"python-%e7%88%ac%e8%99%ab%e6%8a%80%e6%9c%af%e5%85%a8%e6%a0%88%e6%8c%87%e5%8d%97","status":"publish","type":"post","link":"https:\/\/www.wsisp.com\/helps\/97387.html","title":{"rendered":"Python \u722c\u866b\u6280\u672f\u5168\u6808\u6307\u5357"},"content":{"rendered":"<h2>Python \u722c\u866b\u6280\u672f\u5168\u6808\u6307\u5357<\/h2>\n<p>\u9762\u5411\u8bfb\u8005&#xff1a;\u6709\u4e00\u5b9a Python \u57fa\u7840\u7684\u6570\u636e\u5f00\u53d1\u5de5\u7a0b\u5e08 \u7248\u672c\u8bf4\u660e&#xff1a;\u878d\u5165 2025-2026 \u5e74\u6700\u65b0\u6280\u672f\u52a8\u6001&#xff0c;\u8986\u76d6 curl_cffi\u3001Playwright \u65b0\u7248\u3001AI \u8f85\u52a9\u9006\u5411\u7b49\u524d\u6cbf\u5185\u5bb9<\/p>\n<hr \/>\n<h3>\u76ee\u5f55<\/h3>\n<li>\u722c\u866b\u5168\u666f\u6982\u8ff0<\/li>\n<li>HTTP\u534f\u8bae\u4e0e\u7f51\u7edc\u57fa\u7840<\/li>\n<li>Python\u722c\u866b\u57fa\u7840\u5e93<\/li>\n<li>HTML\u89e3\u6790\u4e0e\u6570\u636e\u63d0\u53d6<\/li>\n<li>\u4e3b\u6d41\u722c\u866b\u6846\u67b6\u8be6\u89e3<\/li>\n<li>\u52a8\u6001\u9875\u9762\u722c\u53d6<\/li>\n<li>\u53cd\u722c\u866b\u6280\u672f\u5168\u89e3<\/li>\n<li>\u53cd\u53cd\u722c\u866b\u5b9e\u6218<\/li>\n<li>\u9006\u5411\u5de5\u7a0b\u57fa\u7840<\/li>\n<li>JS\u9006\u5411\u6df1\u5ea6\u5b9e\u6218<\/li>\n<li>APP\u722c\u866b\u4e0e\u6293\u5305<\/li>\n<li>\u5206\u5e03\u5f0f\u722c\u866b\u67b6\u6784<\/li>\n<li>\u6570\u636e\u5b58\u50a8\u4e0e\u6e05\u6d17<\/li>\n<li>\u6cd5\u5f8b\u5408\u89c4\u4e0erobots\u534f\u8bae<\/li>\n<li>\u9a8c\u8bc1\u7801\u4e13\u9879\u7a81\u7834<\/li>\n<li>\u9ad8\u5e76\u53d1\u4e0e\u6027\u80fd\u4f18\u5316<\/li>\n<li>\u5b9e\u6218\u9879\u76ee<\/li>\n<li>2025-2026\u722c\u866b\u65b0\u6280\u672f\u8d8b\u52bf<\/li>\n<hr \/>\n<h3>1. \u722c\u866b\u5168\u666f\u6982\u8ff0<\/h3>\n<h4>1.1 \u4ec0\u4e48\u662f\u722c\u866b<\/h4>\n<p>\u7f51\u7edc\u722c\u866b&#xff08;Web Crawler \/ Spider&#xff09;\u662f\u4e00\u79cd\u6309\u7167\u4e00\u5b9a\u89c4\u5219\u81ea\u52a8\u6293\u53d6\u4e07\u7ef4\u7f51\u4fe1\u606f\u7684\u7a0b\u5e8f\u6216\u811a\u672c\u3002\u5176\u6838\u5fc3\u5de5\u4f5c\u6d41\u7a0b\u53ef\u4ee5\u6982\u62ec\u4e3a&#xff1a;<\/p>\n<p>\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510<br \/>\n\u2502                    \u722c\u866b\u5de5\u4f5c\u6d41\u7a0b\u5168\u666f\u56fe                         \u2502<br \/>\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524<br \/>\n\u2502                                                             \u2502<br \/>\n\u2502  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\u2502<br \/>\n\u2502  \u2502 \u79cd\u5b50URL  \u2502\u2500\u2500\u2500&gt;\u2502 \u53d1\u9001\u8bf7\u6c42 \u2502\u2500\u2500\u2500&gt;\u2502 \u63a5\u6536\u54cd\u5e94 \u2502\u2500\u2500\u2500&gt;\u2502 \u89e3\u6790\u63d0 \u2502\u2502<br \/>\n\u2502  \u2502   \u961f\u5217   \u2502    \u2502 (HTTP)   \u2502    \u2502  (HTML)  \u2502    \u2502 \u53d6\u6570\u636e \u2502\u2502<br \/>\n\u2502  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518    \u2514\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2518\u2502<br \/>\n\u2502       ^                                              \u2502     \u2502<br \/>\n\u2502       \u2502         \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510         \u2502     \u2502<br \/>\n\u2502       \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2502 \u8c03\u5ea6\u63a7\u5236 \u2502&lt;\u2500\u2500\u2500\u2502 \u6570\u636e\u5b58\u50a8 \u2502&lt;\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518     \u2502<br \/>\n\u2502                 \u2502   \u5f15\u64ce   \u2502    \u2502  Pipeline \u2502               \u2502<br \/>\n\u2502                 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518               \u2502<br \/>\n\u2502                                                             \u2502<br \/>\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/p>\n<h4>1.2 \u722c\u866b\u53d1\u5c55\u5386\u53f2<\/h4>\n<table>\n<tr>\u9636\u6bb5\u65f6\u95f4\u7279\u5f81\u4ee3\u8868\u6280\u672f<\/tr>\n<tbody>\n<tr>\n<td>\u840c\u82bd\u671f<\/td>\n<td>1993-2000<\/td>\n<td>\u641c\u7d22\u5f15\u64ce\u722c\u866b\u8bde\u751f<\/td>\n<td>World Wide Web Wanderer\u3001Googlebot<\/td>\n<\/tr>\n<tr>\n<td>\u6210\u957f\u671f<\/td>\n<td>2000-2010<\/td>\n<td>\u5f00\u6e90\u6846\u67b6\u6d8c\u73b0<\/td>\n<td>Scrapy(2008)\u3001Nutch\u3001Heritrix<\/td>\n<\/tr>\n<tr>\n<td>\u5bf9\u6297\u671f<\/td>\n<td>2010-2020<\/td>\n<td>\u53cd\u722c\u4e0e\u53cd\u53cd\u722c\u535a\u5f08<\/td>\n<td>Selenium\u3001PhantomJS\u3001\u4ee3\u7406\u6c60<\/td>\n<\/tr>\n<tr>\n<td>\u667a\u80fd\u5316<\/td>\n<td>2020-2025<\/td>\n<td>AI\u8f85\u52a9\u9006\u5411\u3001\u65e0\u5934\u6d4f\u89c8\u5668\u666e\u53ca<\/td>\n<td>Playwright\u3001curl_cffi\u3001GPT\u9006\u5411<\/td>\n<\/tr>\n<tr>\n<td>\u65b0\u7eaa\u5143<\/td>\n<td>2025-2026<\/td>\n<td>TLS\u6307\u7eb9\u4f2a\u88c5\u3001LLM\u5206\u6790JS<\/td>\n<td>curl_cffi 0.14&#043;\u3001AI Agent\u722c\u866b<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>1.3 \u722c\u866b\u5206\u7c7b<\/h4>\n<table>\n<tr>\u7c7b\u578b\u8bf4\u660e\u9002\u7528\u573a\u666f\u793a\u4f8b<\/tr>\n<tbody>\n<tr>\n<td>\u901a\u7528\u722c\u866b<\/td>\n<td>\u5927\u89c4\u6a21\u6293\u53d6\u5168\u7f51\u6570\u636e<\/td>\n<td>\u641c\u7d22\u5f15\u64ce\u7d22\u5f15<\/td>\n<td>Googlebot\u3001BaiduSpider<\/td>\n<\/tr>\n<tr>\n<td>\u805a\u7126\u722c\u866b<\/td>\n<td>\u9488\u5bf9\u7279\u5b9a\u4e3b\u9898\/\u7f51\u7ad9<\/td>\n<td>\u7535\u5546\u6bd4\u4ef7\u3001\u8206\u60c5\u76d1\u63a7<\/td>\n<td>\u5546\u54c1\u4ef7\u683c\u91c7\u96c6\u5668<\/td>\n<\/tr>\n<tr>\n<td>\u589e\u91cf\u722c\u866b<\/td>\n<td>\u53ea\u6293\u53d6\u65b0\u589e\/\u53d8\u66f4\u5185\u5bb9<\/td>\n<td>\u65b0\u95fb\u76d1\u63a7\u3001\u66f4\u65b0\u68c0\u6d4b<\/td>\n<td>\u65b0\u95fb\u805a\u5408\u7cfb\u7edf<\/td>\n<\/tr>\n<tr>\n<td>\u5206\u5e03\u5f0f\u722c\u866b<\/td>\n<td>\u591a\u673a\u534f\u540c\u5927\u89c4\u6a21\u91c7\u96c6<\/td>\n<td>\u5168\u7f51\u6570\u636e\u3001PB\u7ea7<\/td>\n<td>Scrapy-Redis\u96c6\u7fa4<\/td>\n<\/tr>\n<tr>\n<td>\u6df1\u5ea6\u5b66\u4e60\u722c\u866b<\/td>\n<td>\u7ed3\u5408AI\u8fdb\u884c\u667a\u80fd\u63d0\u53d6<\/td>\n<td>\u7ed3\u6784\u5316\u4fe1\u606f\u62bd\u53d6<\/td>\n<td>\u57fa\u4e8eBERT\u7684\u7f51\u9875\u89e3\u6790<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>1.4 \u722c\u866b vs RPA vs API\u8c03\u7528<\/h4>\n<table>\n<tr>\u5bf9\u6bd4\u7ef4\u5ea6\u7f51\u7edc\u722c\u866bRPA&#xff08;\u673a\u5668\u4eba\u6d41\u7a0b\u81ea\u52a8\u5316&#xff09;API\u8c03\u7528<\/tr>\n<tbody>\n<tr>\n<td>\u5b9e\u73b0\u65b9\u5f0f<\/td>\n<td>\u6a21\u62dfHTTP\u8bf7\u6c42<\/td>\n<td>\u6a21\u62df\u4eba\u7c7bUI\u64cd\u4f5c<\/td>\n<td>\u76f4\u63a5\u8c03\u7528\u63a5\u53e3<\/td>\n<\/tr>\n<tr>\n<td>\u5f00\u53d1\u96be\u5ea6<\/td>\n<td>\u4e2d\u7b49<\/td>\n<td>\u4f4e&#xff08;\u53ef\u89c6\u5316\u914d\u7f6e&#xff09;<\/td>\n<td>\u4f4e&#xff08;\u6709\u6587\u6863\u65f6&#xff09;<\/td>\n<\/tr>\n<tr>\n<td>\u6267\u884c\u6548\u7387<\/td>\n<td>\u9ad8<\/td>\n<td>\u4f4e&#xff08;\u9700\u6e32\u67d3UI&#xff09;<\/td>\n<td>\u6700\u9ad8<\/td>\n<\/tr>\n<tr>\n<td>\u7a33\u5b9a\u6027<\/td>\n<td>\u4e2d&#xff08;\u53d7\u53cd\u722c\u5f71\u54cd&#xff09;<\/td>\n<td>\u4f4e&#xff08;UI\u53d8\u5316\u654f\u611f&#xff09;<\/td>\n<td>\u9ad8<\/td>\n<\/tr>\n<tr>\n<td>\u6570\u636e\u5b8c\u6574\u6027<\/td>\n<td>\u53ef\u63a7<\/td>\n<td>\u4e0e\u4eba\u7c7b\u64cd\u4f5c\u4e00\u81f4<\/td>\n<td>\u53d6\u51b3\u4e8eAPI\u8bbe\u8ba1<\/td>\n<\/tr>\n<tr>\n<td>\u6cd5\u5f8b\u98ce\u9669<\/td>\n<td>\u4e2d-\u9ad8<\/td>\n<td>\u4e2d<\/td>\n<td>\u4f4e<\/td>\n<\/tr>\n<tr>\n<td>\u5178\u578b\u5de5\u5177<\/td>\n<td>Scrapy\/Playwright<\/td>\n<td>UiPath\/\u5f71\u5200<\/td>\n<td>requests\/httpx<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u9762\u8bd5\u52a0\u5206\u63d0\u793a&#xff1a;\u5728\u6280\u672f\u9009\u578b\u65f6&#xff0c;\u4f18\u5148\u8bc4\u4f30\u76ee\u6807\u7cfb\u7edf\u662f\u5426\u63d0\u4f9b\u5b98\u65b9API\u3002API\u8c03\u7528\u662f\u6700\u7a33\u5b9a\u3001\u5408\u89c4\u3001\u9ad8\u6548\u7684\u65b9\u5f0f\u3002\u53ea\u6709\u5f53API\u65e0\u6cd5\u6ee1\u8db3\u9700\u6c42&#xff08;\u5982\u6570\u636e\u4e0d\u5b8c\u6574\u3001\u9891\u7387\u53d7\u9650&#xff09;\u65f6&#xff0c;\u624d\u8003\u8651\u722c\u866b\u65b9\u6848\u3002<\/p>\n<h4>1.5 \u5e94\u7528\u573a\u666f\u5168\u666f<\/h4>\n<table>\n<tr>\u9886\u57df\u5178\u578b\u5e94\u7528\u6570\u636e\u91cf\u7ea7<\/tr>\n<tbody>\n<tr>\n<td>\u7535\u5546<\/td>\n<td>\u5546\u54c1\u6bd4\u4ef7\u3001\u9500\u91cf\u76d1\u63a7\u3001\u8bc4\u4ef7\u5206\u6790<\/td>\n<td>\u767e\u4e07\u7ea7SKU<\/td>\n<\/tr>\n<tr>\n<td>\u91d1\u878d<\/td>\n<td>\u80a1\u7968\u884c\u60c5\u3001\u8d22\u62a5\u6293\u53d6\u3001\u8206\u60c5\u9884\u8b66<\/td>\n<td>\u5b9e\u65f6\/\u65e5\u66f4<\/td>\n<\/tr>\n<tr>\n<td>\u5b66\u672f<\/td>\n<td>\u8bba\u6587\u68c0\u7d22\u3001\u671f\u520a\u4e0b\u8f7d\u3001\u4e13\u5229\u5206\u6790<\/td>\n<td>\u5341\u4e07\u7ea7\u6587\u6863<\/td>\n<\/tr>\n<tr>\n<td>\u793e\u4ea4\u5a92\u4f53<\/td>\n<td>\u8bdd\u9898\u8ffd\u8e2a\u3001KOL\u5206\u6790\u3001\u8d8b\u52bf\u9884\u6d4b<\/td>\n<td>\u4ebf\u7ea7\u6d88\u606f<\/td>\n<\/tr>\n<tr>\n<td>\u62db\u8058<\/td>\n<td>\u804c\u4f4d\u805a\u5408\u3001\u85aa\u8d44\u5206\u6790\u3001\u6280\u80fd\u9700\u6c42<\/td>\n<td>\u767e\u4e07\u7ea7\u5c97\u4f4d<\/td>\n<\/tr>\n<tr>\n<td>\u623f\u5730\u4ea7<\/td>\n<td>\u623f\u4ef7\u76d1\u63a7\u3001\u697c\u76d8\u5bf9\u6bd4\u3001\u79df\u91d1\u6307\u6570<\/td>\n<td>\u5341\u4e07\u7ea7\u623f\u6e90<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr \/>\n<h3>2. HTTP\u534f\u8bae\u4e0e\u7f51\u7edc\u57fa\u7840<\/h3>\n<h4>2.1 HTTP\/HTTPS \u539f\u7406<\/h4>\n<p>HTTP&#xff08;HyperText Transfer Protocol&#xff09;\u662f Web \u6570\u636e\u901a\u4fe1\u7684\u57fa\u7840\u534f\u8bae\u3002HTTPS \u5728 HTTP \u57fa\u7840\u4e0a\u589e\u52a0\u4e86 TLS\/SSL \u52a0\u5bc6\u5c42\u3002<\/p>\n<p>\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510<br \/>\n\u2502              HTTP vs HTTPS \u534f\u8bae\u6808\u5bf9\u6bd4                     \u2502<br \/>\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524<br \/>\n\u2502                                                         \u2502<br \/>\n\u2502  HTTP \u534f\u8bae\u6808:                HTTPS \u534f\u8bae\u6808:              \u2502<br \/>\n\u2502  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510           \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510           \u2502<br \/>\n\u2502  \u2502   HTTP\/1.1   \u2502           \u2502   HTTP\/2     \u2502           \u2502<br \/>\n\u2502  \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524           \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524           \u2502<br \/>\n\u2502  \u2502              \u2502           \u2502   TLS 1.3    \u2502           \u2502<br \/>\n\u2502  \u2502              \u2502           \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524           \u2502<br \/>\n\u2502  \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524           \u2502              \u2502           \u2502<br \/>\n\u2502  \u2502    TCP       \u2502           \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524           \u2502<br \/>\n\u2502  \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524           \u2502    TCP       \u2502           \u2502<br \/>\n\u2502  \u2502    IP        \u2502           \u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524           \u2502<br \/>\n\u2502  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518           \u2502    IP        \u2502           \u2502<br \/>\n\u2502                              \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518           \u2502<br \/>\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/p>\n<p>HTTPS \u63e1\u624b\u8fc7\u7a0b&#xff08;TLS 1.3 \u7b80\u5316\u7248&#xff09;&#xff1a;<\/p>\n<p>\u5ba2\u6237\u7aef                                    \u670d\u52a1\u7aef<br \/>\n  \u2502                                        \u2502<br \/>\n  \u2502\u2500\u2500\u2500\u2500 ClientHello \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500&gt;\u2502  (\u652f\u6301\u7684\u5bc6\u7801\u5957\u4ef6\u3001\u6269\u5c55\u3001SNI)<br \/>\n  \u2502                                        \u2502<br \/>\n  \u2502&lt;\u2500\u2500\u2500\u2500 ServerHello \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2502  (\u9009\u5b9a\u7684\u5bc6\u7801\u5957\u4ef6\u3001\u8bc1\u4e66)<br \/>\n  \u2502&lt;\u2500\u2500\u2500\u2500 Certificate \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2502  (\u670d\u52a1\u5668\u8bc1\u4e66\u94fe)<br \/>\n  \u2502&lt;\u2500\u2500\u2500\u2500 EncryptedExtensions \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2502<br \/>\n  \u2502&lt;\u2500\u2500\u2500\u2500 Finished \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2502<br \/>\n  \u2502                                        \u2502<br \/>\n  \u2502\u2500\u2500\u2500\u2500 Finished \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500&gt;\u2502  (\u63e1\u624b\u5b8c\u6210&#xff0c;\u5f00\u59cb\u52a0\u5bc6\u901a\u4fe1)<br \/>\n  \u2502                                        \u2502<br \/>\n  \u2502&lt;\u2550\u2550\u2550\u2550 \u52a0\u5bc6\u7684\u5e94\u7528\u6570\u636e \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550&gt;\u2502<\/p>\n<h4>2.2 \u8bf7\u6c42\u54cd\u5e94\u6a21\u578b<\/h4>\n<p><span class=\"token keyword\">import<\/span> requests<\/p>\n<p><span class=\"token comment\"># \u5b8c\u6574\u7684\u8bf7\u6c42\u793a\u4f8b<\/span><br \/>\nresponse <span class=\"token operator\">&#061;<\/span> requests<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><br \/>\n    url<span class=\"token operator\">&#061;<\/span><span class=\"token string\">&#034;https:\/\/httpbin.org\/get&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    params<span class=\"token operator\">&#061;<\/span><span class=\"token punctuation\">{<\/span><span class=\"token string\">&#034;page&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;size&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token number\">20<\/span><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span>          <span class=\"token comment\"># URL\u67e5\u8be2\u53c2\u6570<\/span><br \/>\n    headers<span class=\"token operator\">&#061;<\/span><span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token string\">&#034;User-Agent&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;Mozilla\/5.0 (Windows NT 10.0; Win64; x64) &#034;<\/span><br \/>\n                      <span class=\"token string\">&#034;AppleWebKit\/537.36 (KHTML, like Gecko) &#034;<\/span><br \/>\n                      <span class=\"token string\">&#034;Chrome\/131.0.0.0 Safari\/537.36&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token string\">&#034;Accept&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;application\/json&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token string\">&#034;Accept-Language&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;zh-CN,zh;q&#061;0.9,en;q&#061;0.8&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token string\">&#034;Accept-Encoding&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;gzip, deflate, br&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token string\">&#034;Connection&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;keep-alive&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    cookies<span class=\"token operator\">&#061;<\/span><span class=\"token punctuation\">{<\/span><span class=\"token string\">&#034;session_id&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;abc123def456&#034;<\/span><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    timeout<span class=\"token operator\">&#061;<\/span><span class=\"token punctuation\">(<\/span><span class=\"token number\">5<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">30<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span>                         <span class=\"token comment\"># (\u8fde\u63a5\u8d85\u65f6, \u8bfb\u53d6\u8d85\u65f6)<\/span><br \/>\n    allow_redirects<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">True<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    verify<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">True<\/span><span class=\"token punctuation\">,<\/span>                             <span class=\"token comment\"># SSL\u8bc1\u4e66\u9a8c\u8bc1<\/span><br \/>\n<span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u72b6\u6001\u7801: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>response<span class=\"token punctuation\">.<\/span>status_code<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n<span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u54cd\u5e94\u5934: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>response<span class=\"token punctuation\">.<\/span>headers<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#039;Content-Type&#039;<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n<span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u7f16\u7801: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>response<span class=\"token punctuation\">.<\/span>encoding<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n<span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;JSON\u6570\u636e: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>response<span class=\"token punctuation\">.<\/span>json<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n<span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u8bf7\u6c42\u8017\u65f6: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>response<span class=\"token punctuation\">.<\/span>elapsed<span class=\"token punctuation\">.<\/span>total_seconds<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><span class=\"token format-spec\">.3f<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">s&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><\/p>\n<h4>2.3 \u5e38\u89c1\u72b6\u6001\u7801<\/h4>\n<table>\n<tr>\u72b6\u6001\u7801\u542b\u4e49\u722c\u866b\u5e94\u5bf9\u7b56\u7565<\/tr>\n<tbody>\n<tr>\n<td>200<\/td>\n<td>\u6210\u529f<\/td>\n<td>\u6b63\u5e38\u89e3\u6790<\/td>\n<\/tr>\n<tr>\n<td>301<\/td>\n<td>\u6c38\u4e45\u91cd\u5b9a\u5411<\/td>\n<td>\u66f4\u65b0URL\u5e93<\/td>\n<\/tr>\n<tr>\n<td>302<\/td>\n<td>\u4e34\u65f6\u91cd\u5b9a\u5411<\/td>\n<td>\u8ddf\u8e2aLocation\u5934<\/td>\n<\/tr>\n<tr>\n<td>304<\/td>\n<td>\u672a\u4fee\u6539&#xff08;\u7f13\u5b58&#xff09;<\/td>\n<td>\u5229\u7528\u7f13\u5b58\u7b56\u7565<\/td>\n<\/tr>\n<tr>\n<td>400<\/td>\n<td>\u8bf7\u6c42\u9519\u8bef<\/td>\n<td>\u68c0\u67e5\u8bf7\u6c42\u53c2\u6570<\/td>\n<\/tr>\n<tr>\n<td>401<\/td>\n<td>\u672a\u6388\u6743<\/td>\n<td>\u9700\u8981\u8ba4\u8bc1\u4fe1\u606f<\/td>\n<\/tr>\n<tr>\n<td>403<\/td>\n<td>\u7981\u6b62\u8bbf\u95ee<\/td>\n<td>\u53ef\u80fd\u89e6\u53d1\u53cd\u722c&#xff0c;\u68c0\u67e5UA\/IP<\/td>\n<\/tr>\n<tr>\n<td>404<\/td>\n<td>\u8d44\u6e90\u4e0d\u5b58\u5728<\/td>\n<td>\u8df3\u8fc7\u8be5URL<\/td>\n<\/tr>\n<tr>\n<td>429<\/td>\n<td>\u8bf7\u6c42\u8fc7\u591a<\/td>\n<td>\u5fc5\u987b\u964d\u901f&#xff0c;\u589e\u52a0\u5ef6\u8fdf<\/td>\n<\/tr>\n<tr>\n<td>500<\/td>\n<td>\u670d\u52a1\u5668\u9519\u8bef<\/td>\n<td>\u91cd\u8bd5\u6216\u8df3\u8fc7<\/td>\n<\/tr>\n<tr>\n<td>503<\/td>\n<td>\u670d\u52a1\u4e0d\u53ef\u7528<\/td>\n<td>\u53ef\u80fd\u662f\u53cd\u722c&#xff08;\u5982Cloudflare&#xff09;&#xff0c;\u7b49\u5f85\u91cd\u8bd5<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u751f\u4ea7\u8e29\u5751\u63d0\u9192&#xff1a;429 \u72b6\u6001\u7801\u662f\u6700\u660e\u663e\u7684&#034;\u4f60\u88ab\u5c01\u4e86&#034;\u4fe1\u53f7\u3002\u751f\u4ea7\u73af\u5883\u5fc5\u987b\u5b9e\u73b0\u6307\u6570\u9000\u907f\u91cd\u8bd5\u7b56\u7565&#xff0c;\u9047\u5230 429 \u7acb\u5373\u505c\u6b62\u8bf7\u6c42\u81f3\u5c11 60 \u79d2\u3002<\/p>\n<h4>2.4 Cookie\/Session \u673a\u5236<\/h4>\n<p><span class=\"token keyword\">import<\/span> requests<\/p>\n<p><span class=\"token comment\"># \u65b9\u5f0f1&#xff1a;\u4f7f\u7528Session\u81ea\u52a8\u7ba1\u7406Cookie<\/span><br \/>\nsession <span class=\"token operator\">&#061;<\/span> requests<span class=\"token punctuation\">.<\/span>Session<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token comment\"># \u767b\u5f55<\/span><br \/>\nlogin_resp <span class=\"token operator\">&#061;<\/span> session<span class=\"token punctuation\">.<\/span>post<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;https:\/\/httpbin.org\/post&#034;<\/span><span class=\"token punctuation\">,<\/span> data<span class=\"token operator\">&#061;<\/span><span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token string\">&#034;username&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;test_user&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    <span class=\"token string\">&#034;password&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;test_pass_123&#034;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token comment\"># Session\u4f1a\u81ea\u52a8\u643a\u5e26\u767b\u5f55\u540e\u7684Cookie<\/span><br \/>\nprofile_resp <span class=\"token operator\">&#061;<\/span> session<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;https:\/\/httpbin.org\/cookies&#034;<\/span><span class=\"token punctuation\">)<\/span><br \/>\n<span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;Cookies: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>session<span class=\"token punctuation\">.<\/span>cookies<span class=\"token punctuation\">.<\/span>get_dict<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token comment\"># \u65b9\u5f0f2&#xff1a;\u624b\u52a8\u8bbe\u7f6eCookie<\/span><br \/>\nsession<span class=\"token punctuation\">.<\/span>cookies<span class=\"token punctuation\">.<\/span><span class=\"token builtin\">set<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;token&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;eyJhbGciOiJIUzI1NiJ9.xxxx&#034;<\/span><span class=\"token punctuation\">,<\/span> domain<span class=\"token operator\">&#061;<\/span><span class=\"token string\">&#034;.example.com&#034;<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<h4>2.5 WebSocket \u57fa\u7840<\/h4>\n<p><span class=\"token keyword\">import<\/span> asyncio<br \/>\n<span class=\"token keyword\">import<\/span> websockets<br \/>\n<span class=\"token keyword\">import<\/span> json<\/p>\n<p><span class=\"token keyword\">async<\/span> <span class=\"token keyword\">def<\/span> <span class=\"token function\">ws_crawler<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;WebSocket\u6570\u636e\u6293\u53d6\u793a\u4f8b&#034;&#034;&#034;<\/span><br \/>\n    uri <span class=\"token operator\">&#061;<\/span> <span class=\"token string\">&#034;wss:\/\/stream.binance.com:9443\/ws\/btcusdt&#064;trade&#034;<\/span><br \/>\n    <span class=\"token keyword\">async<\/span> <span class=\"token keyword\">with<\/span> websockets<span class=\"token punctuation\">.<\/span>connect<span class=\"token punctuation\">(<\/span>uri<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">as<\/span> websocket<span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token keyword\">for<\/span> i <span class=\"token keyword\">in<\/span> <span class=\"token builtin\">range<\/span><span class=\"token punctuation\">(<\/span><span class=\"token number\">100<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n            message <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">await<\/span> websocket<span class=\"token punctuation\">.<\/span>recv<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n            data <span class=\"token operator\">&#061;<\/span> json<span class=\"token punctuation\">.<\/span>loads<span class=\"token punctuation\">(<\/span>message<span class=\"token punctuation\">)<\/span><br \/>\n            <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u4ef7\u683c: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>data<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#039;p&#039;<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">, \u6570\u91cf: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>data<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#039;q&#039;<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">, \u65f6\u95f4: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>data<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#039;T&#039;<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token comment\"># asyncio.run(ws_crawler())<\/span><\/p>\n<h4>2.6 HTTP\/2 \u7279\u6027<\/h4>\n<table>\n<tr>\u7279\u6027HTTP\/1.1HTTP\/2\u722c\u866b\u5f71\u54cd<\/tr>\n<tbody>\n<tr>\n<td>\u591a\u8def\u590d\u7528<\/td>\n<td>\u4e0d\u652f\u6301&#xff0c;\u961f\u5934\u963b\u585e<\/td>\n<td>\u652f\u6301&#xff0c;\u5355\u8fde\u63a5\u591a\u8bf7\u6c42<\/td>\n<td>\u51cf\u5c11\u8fde\u63a5\u6570<\/td>\n<\/tr>\n<tr>\n<td>\u5934\u90e8\u538b\u7f29<\/td>\n<td>\u4e0d\u652f\u6301<\/td>\n<td>\u652f\u6301 HPACK<\/td>\n<td>\u51cf\u5c11\u5e26\u5bbd<\/td>\n<\/tr>\n<tr>\n<td>\u670d\u52a1\u5668\u63a8\u9001<\/td>\n<td>\u4e0d\u652f\u6301<\/td>\n<td>\u652f\u6301<\/td>\n<td>\u53ef\u9884\u53d6\u8d44\u6e90<\/td>\n<\/tr>\n<tr>\n<td>\u4e8c\u8fdb\u5236\u5e27<\/td>\n<td>\u6587\u672c<\/td>\n<td>\u4e8c\u8fdb\u5236<\/td>\n<td>\u89e3\u6790\u66f4\u9ad8\u6548<\/td>\n<\/tr>\n<tr>\n<td>\u6d41\u4f18\u5148\u7ea7<\/td>\n<td>\u4e0d\u652f\u6301<\/td>\n<td>\u652f\u6301<\/td>\n<td>\u8d44\u6e90\u52a0\u8f7d\u4f18\u5316<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u9762\u8bd5\u52a0\u5206\u63d0\u793a&#xff1a;2025 \u5e74\u8d77&#xff0c;\u8d8a\u6765\u8d8a\u591a\u7f51\u7ad9\u5f3a\u5236\u8981\u6c42 HTTP\/2 \u652f\u6301\u3002Python \u7684 httpx \u548c curl_cffi \u90fd\u539f\u751f\u652f\u6301 HTTP\/2&#xff0c;\u800c\u4f20\u7edf requests \u5e93\u53ea\u652f\u6301\u5230 HTTP\/1.1\u3002<\/p>\n<hr \/>\n<h3>3. Python\u722c\u866b\u57fa\u7840\u5e93<\/h3>\n<h4>3.1 \u56db\u5927HTTP\u5ba2\u6237\u7aef\u5bf9\u6bd4<\/h4>\n<table>\n<tr>\u7279\u6027requestshttpxaiohttpcurl_cffi<\/tr>\n<tbody>\n<tr>\n<td>\u540c\u6b65\/\u5f02\u6b65<\/td>\n<td>\u540c\u6b65<\/td>\n<td>\u540c\u6b65&#043;\u5f02\u6b65<\/td>\n<td>\u5f02\u6b65<\/td>\n<td>\u540c\u6b65&#043;\u5f02\u6b65<\/td>\n<\/tr>\n<tr>\n<td>HTTP\/2<\/td>\n<td>\u4e0d\u652f\u6301<\/td>\n<td>\u652f\u6301<\/td>\n<td>\u652f\u6301<\/td>\n<td>\u652f\u6301<\/td>\n<\/tr>\n<tr>\n<td>TLS\u6307\u7eb9\u4f2a\u88c5<\/td>\n<td>\u4e0d\u652f\u6301<\/td>\n<td>\u4e0d\u652f\u6301<\/td>\n<td>\u4e0d\u652f\u6301<\/td>\n<td>\u652f\u6301<\/td>\n<\/tr>\n<tr>\n<td>\u6d4f\u89c8\u5668\u6a21\u62df<\/td>\n<td>\u4e0d\u652f\u6301<\/td>\n<td>\u4e0d\u652f\u6301<\/td>\n<td>\u4e0d\u652f\u6301<\/td>\n<td>\u652f\u6301 impersonate<\/td>\n<\/tr>\n<tr>\n<td>\u8fde\u63a5\u6c60<\/td>\n<td>\u652f\u6301<\/td>\n<td>\u652f\u6301<\/td>\n<td>\u652f\u6301<\/td>\n<td>\u652f\u6301<\/td>\n<\/tr>\n<tr>\n<td>WebSocket<\/td>\n<td>\u4e0d\u652f\u6301<\/td>\n<td>\u652f\u6301<\/td>\n<td>\u652f\u6301<\/td>\n<td>\u4e0d\u652f\u6301<\/td>\n<\/tr>\n<tr>\n<td>\u81ea\u52a8\u91cd\u8bd5<\/td>\n<td>\u4e0d\u652f\u6301<\/td>\n<td>\u652f\u6301<\/td>\n<td>\u652f\u6301<\/td>\n<td>\u652f\u6301<\/td>\n<\/tr>\n<tr>\n<td>\u5b66\u4e60\u66f2\u7ebf<\/td>\n<td>\u4f4e<\/td>\n<td>\u4f4e<\/td>\n<td>\u4e2d<\/td>\n<td>\u4f4e<\/td>\n<\/tr>\n<tr>\n<td>\u9002\u7528\u573a\u666f<\/td>\n<td>\u7b80\u5355\u811a\u672c<\/td>\n<td>\u73b0\u4ee3\u66ff\u4ee3<\/td>\n<td>\u9ad8\u5e76\u53d1<\/td>\n<td>\u53cd\u722c\u7ed5\u8fc7<\/td>\n<\/tr>\n<tr>\n<td>\u7ef4\u62a4\u72b6\u6001<\/td>\n<td>\u7ef4\u62a4\u4e2d<\/td>\n<td>\u6d3b\u8dc3<\/td>\n<td>\u6d3b\u8dc3<\/td>\n<td>\u6d3b\u8dc3(2025\u70ed\u95e8)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>3.2 requests \u8fdb\u9636\u7528\u6cd5<\/h4>\n<p><span class=\"token keyword\">import<\/span> requests<br \/>\n<span class=\"token keyword\">from<\/span> requests<span class=\"token punctuation\">.<\/span>adapters <span class=\"token keyword\">import<\/span> HTTPAdapter<br \/>\n<span class=\"token keyword\">from<\/span> urllib3<span class=\"token punctuation\">.<\/span>util<span class=\"token punctuation\">.<\/span>retry <span class=\"token keyword\">import<\/span> Retry<\/p>\n<p><span class=\"token comment\"># \u521b\u5efa\u5e26\u91cd\u8bd5\u673a\u5236\u7684Session<\/span><br \/>\n<span class=\"token keyword\">def<\/span> <span class=\"token function\">create_robust_session<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    session <span class=\"token operator\">&#061;<\/span> requests<span class=\"token punctuation\">.<\/span>Session<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>    <span class=\"token comment\"># \u914d\u7f6e\u91cd\u8bd5\u7b56\u7565<\/span><br \/>\n    retry_strategy <span class=\"token operator\">&#061;<\/span> Retry<span class=\"token punctuation\">(<\/span><br \/>\n        total<span class=\"token operator\">&#061;<\/span><span class=\"token number\">3<\/span><span class=\"token punctuation\">,<\/span>                          <span class=\"token comment\"># \u6700\u5927\u91cd\u8bd5\u6b21\u6570<\/span><br \/>\n        backoff_factor<span class=\"token operator\">&#061;<\/span><span class=\"token number\">1<\/span><span class=\"token punctuation\">,<\/span>                 <span class=\"token comment\"># \u9000\u907f\u56e0\u5b50&#xff1a;1s, 2s, 4s<\/span><br \/>\n        status_forcelist<span class=\"token operator\">&#061;<\/span><span class=\"token punctuation\">[<\/span><span class=\"token number\">429<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">500<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">502<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">503<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">504<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        allowed_methods<span class=\"token operator\">&#061;<\/span><span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;GET&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;POST&#034;<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">,<\/span>  <span class=\"token comment\"># \u5141\u8bb8\u91cd\u8bd5\u7684\u65b9\u6cd5<\/span><br \/>\n        raise_on_status<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">False<\/span><span class=\"token punctuation\">,<\/span>            <span class=\"token comment\"># \u4e0d\u629b\u5f02\u5e38&#xff0c;\u8fd4\u56deResponse<\/span><br \/>\n    <span class=\"token punctuation\">)<\/span><\/p>\n<p>    <span class=\"token comment\"># \u914d\u7f6e\u8fde\u63a5\u6c60<\/span><br \/>\n    adapter <span class=\"token operator\">&#061;<\/span> HTTPAdapter<span class=\"token punctuation\">(<\/span><br \/>\n        max_retries<span class=\"token operator\">&#061;<\/span>retry_strategy<span class=\"token punctuation\">,<\/span><br \/>\n        pool_connections<span class=\"token operator\">&#061;<\/span><span class=\"token number\">10<\/span><span class=\"token punctuation\">,<\/span>              <span class=\"token comment\"># \u8fde\u63a5\u6c60\u5927\u5c0f<\/span><br \/>\n        pool_maxsize<span class=\"token operator\">&#061;<\/span><span class=\"token number\">20<\/span><span class=\"token punctuation\">,<\/span>                  <span class=\"token comment\"># \u6700\u5927\u8fde\u63a5\u6570<\/span><br \/>\n    <span class=\"token punctuation\">)<\/span><\/p>\n<p>    session<span class=\"token punctuation\">.<\/span>mount<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;http:\/\/&#034;<\/span><span class=\"token punctuation\">,<\/span> adapter<span class=\"token punctuation\">)<\/span><br \/>\n    session<span class=\"token punctuation\">.<\/span>mount<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;https:\/\/&#034;<\/span><span class=\"token punctuation\">,<\/span> adapter<span class=\"token punctuation\">)<\/span><\/p>\n<p>    <span class=\"token keyword\">return<\/span> session<\/p>\n<p><span class=\"token comment\"># \u4ee3\u7406\u914d\u7f6e<\/span><br \/>\nproxies <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token string\">&#034;http&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;http:\/\/user:pass&#064;proxy.example.com:8080&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    <span class=\"token string\">&#034;https&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;http:\/\/user:pass&#064;proxy.example.com:8080&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><\/p>\n<p>session <span class=\"token operator\">&#061;<\/span> create_robust_session<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\nresp <span class=\"token operator\">&#061;<\/span> session<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;https:\/\/httpbin.org\/get&#034;<\/span><span class=\"token punctuation\">,<\/span> proxies<span class=\"token operator\">&#061;<\/span>proxies<span class=\"token punctuation\">,<\/span> timeout<span class=\"token operator\">&#061;<\/span><span class=\"token number\">10<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<h4>3.3 httpx \u5f02\u6b65\u5b9e\u6218<\/h4>\n<p><span class=\"token keyword\">import<\/span> httpx<br \/>\n<span class=\"token keyword\">import<\/span> asyncio<\/p>\n<p><span class=\"token keyword\">async<\/span> <span class=\"token keyword\">def<\/span> <span class=\"token function\">async_crawler<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;httpx\u5f02\u6b65\u722c\u866b\u793a\u4f8b &#8211; \u9ad8\u5e76\u53d1\u8bf7\u6c42&#034;&#034;&#034;<\/span><br \/>\n    urls <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span><br \/>\n        <span class=\"token string\">&#034;https:\/\/httpbin.org\/get&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token string\">&#034;https:\/\/httpbin.org\/headers&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token string\">&#034;https:\/\/httpbin.org\/cookies&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    <span class=\"token punctuation\">]<\/span><\/p>\n<p>    <span class=\"token comment\"># \u4f7f\u7528\u8fde\u63a5\u6c60\u590d\u7528<\/span><br \/>\n    <span class=\"token keyword\">async<\/span> <span class=\"token keyword\">with<\/span> httpx<span class=\"token punctuation\">.<\/span>AsyncClient<span class=\"token punctuation\">(<\/span><br \/>\n        http2<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">True<\/span><span class=\"token punctuation\">,<\/span>                      <span class=\"token comment\"># \u542f\u7528HTTP\/2<\/span><br \/>\n        timeout<span class=\"token operator\">&#061;<\/span>httpx<span class=\"token punctuation\">.<\/span>Timeout<span class=\"token punctuation\">(<\/span><span class=\"token number\">10.0<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        limits<span class=\"token operator\">&#061;<\/span>httpx<span class=\"token punctuation\">.<\/span>Limits<span class=\"token punctuation\">(<\/span><br \/>\n            max_connections<span class=\"token operator\">&#061;<\/span><span class=\"token number\">100<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            max_keepalive_connections<span class=\"token operator\">&#061;<\/span><span class=\"token number\">20<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        follow_redirects<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">True<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    <span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">as<\/span> client<span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token comment\"># \u5e76\u53d1\u8bf7\u6c42<\/span><br \/>\n        tasks <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span>client<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span>url<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">for<\/span> url <span class=\"token keyword\">in<\/span> urls<span class=\"token punctuation\">]<\/span><br \/>\n        responses <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">await<\/span> asyncio<span class=\"token punctuation\">.<\/span>gather<span class=\"token punctuation\">(<\/span><span class=\"token operator\">*<\/span>tasks<span class=\"token punctuation\">,<\/span> return_exceptions<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">True<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>        <span class=\"token keyword\">for<\/span> url<span class=\"token punctuation\">,<\/span> resp <span class=\"token keyword\">in<\/span> <span class=\"token builtin\">zip<\/span><span class=\"token punctuation\">(<\/span>urls<span class=\"token punctuation\">,<\/span> responses<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token builtin\">isinstance<\/span><span class=\"token punctuation\">(<\/span>resp<span class=\"token punctuation\">,<\/span> httpx<span class=\"token punctuation\">.<\/span>Response<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n                <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>url<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\"> -&gt; <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>resp<span class=\"token punctuation\">.<\/span>status_code<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n            <span class=\"token keyword\">else<\/span><span class=\"token punctuation\">:<\/span><br \/>\n                <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>url<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\"> -&gt; ERROR: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>resp<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token comment\"># asyncio.run(async_crawler())<\/span><\/p>\n<h4>3.4 curl_cffi&#xff1a;TLS\u6307\u7eb9\u4f2a\u88c5\u7684\u5229\u5668<\/h4>\n<p><span class=\"token keyword\">from<\/span> curl_cffi <span class=\"token keyword\">import<\/span> requests <span class=\"token keyword\">as<\/span> cffi_requests<\/p>\n<p><span class=\"token comment\"># \u6a21\u62dfChrome\u6d4f\u89c8\u5668\u7684TLS\u6307\u7eb9<\/span><br \/>\nsession <span class=\"token operator\">&#061;<\/span> cffi_requests<span class=\"token punctuation\">.<\/span>Session<span class=\"token punctuation\">(<\/span>impersonate<span class=\"token operator\">&#061;<\/span><span class=\"token string\">&#034;chrome136&#034;<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token comment\"># \u4e00\u6b21impersonate\u53c2\u6570\u81ea\u52a8\u5904\u7406&#xff1a;<\/span><br \/>\n<span class=\"token comment\"># &#8211; TLS\u6307\u7eb9 (JA3\/JA4)<\/span><br \/>\n<span class=\"token comment\"># &#8211; HTTP\/2 SETTINGS<\/span><br \/>\n<span class=\"token comment\"># &#8211; \u4f2a\u5934\u90e8\u987a\u5e8f (masp for Chrome)<\/span><br \/>\n<span class=\"token comment\"># &#8211; User-Agent\u3001Sec-Ch-Ua \u7b49Headers<\/span><br \/>\nresponse <span class=\"token operator\">&#061;<\/span> session<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;https:\/\/tls.browserleaks.com\/json&#034;<\/span><span class=\"token punctuation\">)<\/span><br \/>\ndata <span class=\"token operator\">&#061;<\/span> response<span class=\"token punctuation\">.<\/span>json<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n<span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;JA3 Hash: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>data<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;ja3_hash&#039;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#039;N\/A&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n<span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;HTTP Version: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>data<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;http_version&#039;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#039;N\/A&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token comment\"># \u652f\u6301\u7684\u6d4f\u89c8\u5668\u76ee\u6807&#xff08;2025\u5e74curl_cffi 0.14\u7248\u672c&#xff09;<\/span><br \/>\n<span class=\"token comment\"># chrome99 ~ chrome142, safari153 ~ safari2601, firefox133\/135\/144<\/span><br \/>\n<span class=\"token comment\"># edge99\/101, tor145<\/span><br \/>\n<span class=\"token comment\"># \u7b80\u5199: chrome, safari, firefox \u81ea\u52a8\u6307\u5411\u6700\u65b0\u7248\u672c<\/span><\/p>\n<p>\u751f\u4ea7\u8e29\u5751\u63d0\u9192&#xff1a;curl_cffi \u7684 JA3 \u54c8\u5e0c\u6bcf\u6b21\u8fd0\u884c\u90fd\u4f1a\u53d8\u5316&#xff0c;\u8fd9\u662f\u6b63\u5e38\u884c\u4e3a\u3002\u56e0\u4e3a GREASE \u673a\u5236\u4f1a\u5728 ClientHello \u4e2d\u63d2\u5165\u968f\u673a\u503c&#xff0c;\u771f\u5b9e Chrome \u4e5f\u662f\u5982\u6b64\u3002\u5173\u952e\u662f\u63e1\u624b\u7684&#034;\u5f62\u72b6&#034;&#xff08;\u5bc6\u7801\u5957\u4ef6\u3001\u6269\u5c55\u7684\u7ec4\u6210\u548c\u987a\u5e8f&#xff09;\u8981\u5339\u914d\u76ee\u6807\u6d4f\u89c8\u5668\u3002<\/p>\n<h3>4. HTML\u89e3\u6790\u4e0e\u6570\u636e\u63d0\u53d6<\/h3>\n<h4>4.1 \u516d\u5927\u89e3\u6790\u65b9\u6848\u5bf9\u6bd4<\/h4>\n<table>\n<tr>\u65b9\u6848\u901f\u5ea6\u6613\u7528\u6027\u529f\u80fd\u4f9d\u8d56\u63a8\u8350\u573a\u666f<\/tr>\n<tbody>\n<tr>\n<td>\u6b63\u5219\u8868\u8fbe\u5f0f<\/td>\n<td>\u6781\u5feb<\/td>\n<td>\u4e2d\u7b49<\/td>\n<td>\u57fa\u7840<\/td>\n<td>\u65e0<\/td>\n<td>\u7b80\u5355\u6a21\u5f0f\u5339\u914d<\/td>\n<\/tr>\n<tr>\n<td>BeautifulSoup<\/td>\n<td>\u8f83\u6162<\/td>\n<td>\u6781\u597d<\/td>\n<td>\u5168\u9762<\/td>\n<td>bs4<\/td>\n<td>\u5feb\u901f\u5f00\u53d1<\/td>\n<\/tr>\n<tr>\n<td>lxml\/XPath<\/td>\n<td>\u6781\u5feb<\/td>\n<td>\u4e2d\u7b49<\/td>\n<td>\u5f3a\u5927<\/td>\n<td>lxml<\/td>\n<td>\u9ad8\u6027\u80fd\u89e3\u6790<\/td>\n<\/tr>\n<tr>\n<td>CSS\u9009\u62e9\u5668<\/td>\n<td>\u5feb<\/td>\n<td>\u597d<\/td>\n<td>\u4e2d\u7b49<\/td>\n<td>cssselect<\/td>\n<td>\u524d\u7aef\u5f00\u53d1\u8005<\/td>\n<\/tr>\n<tr>\n<td>pyquery<\/td>\n<td>\u5feb<\/td>\n<td>\u597d<\/td>\n<td>jQuery\u98ce\u683c<\/td>\n<td>pyquery<\/td>\n<td>jQuery\u719f\u6089\u8005<\/td>\n<\/tr>\n<tr>\n<td>selectolax<\/td>\n<td>\u6781\u5feb<\/td>\n<td>\u4e2d\u7b49<\/td>\n<td>\u57fa\u7840<\/td>\n<td>selectolax<\/td>\n<td>\u6781\u81f4\u6027\u80fd<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>4.2 \u5b9e\u6218\u4ee3\u7801\u5bf9\u6bd4<\/h4>\n<p>html <span class=\"token operator\">&#061;<\/span> <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;<br \/>\n&lt;html&gt;<br \/>\n&lt;body&gt;<br \/>\n  &lt;div class&#061;&#034;product-list&#034;&gt;<br \/>\n    &lt;div class&#061;&#034;item&#034; data-id&#061;&#034;1001&#034;&gt;<br \/>\n      &lt;h3 class&#061;&#034;title&#034;&gt;Python\u7f16\u7a0b\u4ece\u5165\u95e8\u5230\u5b9e\u8df5&lt;\/h3&gt;<br \/>\n      &lt;span class&#061;&#034;price&#034;&gt;89.00&lt;\/span&gt;<br \/>\n      &lt;span class&#061;&#034;stock&#034;&gt;\u6709\u8d27&lt;\/span&gt;<br \/>\n      &lt;a href&#061;&#034;\/book\/1001&#034; class&#061;&#034;link&#034;&gt;\u8be6\u60c5&lt;\/a&gt;<br \/>\n    &lt;\/div&gt;<br \/>\n    &lt;div class&#061;&#034;item&#034; data-id&#061;&#034;1002&#034;&gt;<br \/>\n      &lt;h3 class&#061;&#034;title&#034;&gt;\u6d41\u7545\u7684Python&lt;\/h3&gt;<br \/>\n      &lt;span class&#061;&#034;price&#034;&gt;128.00&lt;\/span&gt;<br \/>\n      &lt;span class&#061;&#034;stock&#034;&gt;\u7f3a\u8d27&lt;\/span&gt;<br \/>\n      &lt;a href&#061;&#034;\/book\/1002&#034; class&#061;&#034;link&#034;&gt;\u8be6\u60c5&lt;\/a&gt;<br \/>\n    &lt;\/div&gt;<br \/>\n  &lt;\/div&gt;<br \/>\n&lt;\/body&gt;<br \/>\n&lt;\/html&gt;<br \/>\n&#034;&#034;&#034;<\/span><\/p>\n<p><span class=\"token comment\"># &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061; \u65b9\u68481: BeautifulSoup &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<\/span><br \/>\n<span class=\"token keyword\">from<\/span> bs4 <span class=\"token keyword\">import<\/span> BeautifulSoup<\/p>\n<p>soup <span class=\"token operator\">&#061;<\/span> BeautifulSoup<span class=\"token punctuation\">(<\/span>html<span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;lxml&#034;<\/span><span class=\"token punctuation\">)<\/span><br \/>\n<span class=\"token keyword\">for<\/span> item <span class=\"token keyword\">in<\/span> soup<span class=\"token punctuation\">.<\/span>select<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;.item&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    title <span class=\"token operator\">&#061;<\/span> item<span class=\"token punctuation\">.<\/span>select_one<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;.title&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>get_text<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    price <span class=\"token operator\">&#061;<\/span> item<span class=\"token punctuation\">.<\/span>select_one<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;.price&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>get_text<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    book_id <span class=\"token operator\">&#061;<\/span> item<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;data-id&#034;<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;[BS4] ID:<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>book_id<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\"> <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>title<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\"> <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>price<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token comment\"># &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061; \u65b9\u68482: lxml &#043; XPath &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<\/span><br \/>\n<span class=\"token keyword\">from<\/span> lxml <span class=\"token keyword\">import<\/span> etree<\/p>\n<p>tree <span class=\"token operator\">&#061;<\/span> etree<span class=\"token punctuation\">.<\/span>HTML<span class=\"token punctuation\">(<\/span>html<span class=\"token punctuation\">)<\/span><br \/>\nitems <span class=\"token operator\">&#061;<\/span> tree<span class=\"token punctuation\">.<\/span>xpath<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;\/\/div[&#064;class&#061;&#034;item&#034;]&#039;<\/span><span class=\"token punctuation\">)<\/span><br \/>\n<span class=\"token keyword\">for<\/span> item <span class=\"token keyword\">in<\/span> items<span class=\"token punctuation\">:<\/span><br \/>\n    title <span class=\"token operator\">&#061;<\/span> item<span class=\"token punctuation\">.<\/span>xpath<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;.\/\/h3[&#064;class&#061;&#034;title&#034;]\/text()&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">[<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">]<\/span><br \/>\n    price <span class=\"token operator\">&#061;<\/span> item<span class=\"token punctuation\">.<\/span>xpath<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;.\/\/span[&#064;class&#061;&#034;price&#034;]\/text()&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">[<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">]<\/span><br \/>\n    book_id <span class=\"token operator\">&#061;<\/span> item<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;data-id&#034;<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;[XPath] ID:<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>book_id<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\"> <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>title<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\"> <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>price<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token comment\"># &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061; \u65b9\u68483: \u6b63\u5219\u8868\u8fbe\u5f0f &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<\/span><br \/>\n<span class=\"token keyword\">import<\/span> re<\/p>\n<p>titles <span class=\"token operator\">&#061;<\/span> re<span class=\"token punctuation\">.<\/span>findall<span class=\"token punctuation\">(<\/span><span class=\"token string\">r&#039;class&#061;&#034;title&#034;&gt;(.*?)&lt;\/h3&gt;&#039;<\/span><span class=\"token punctuation\">,<\/span> html<span class=\"token punctuation\">)<\/span><br \/>\nprices <span class=\"token operator\">&#061;<\/span> re<span class=\"token punctuation\">.<\/span>findall<span class=\"token punctuation\">(<\/span><span class=\"token string\">r&#039;class&#061;&#034;price&#034;&gt;(.*?)&lt;\/span&gt;&#039;<\/span><span class=\"token punctuation\">,<\/span> html<span class=\"token punctuation\">)<\/span><br \/>\nids <span class=\"token operator\">&#061;<\/span> re<span class=\"token punctuation\">.<\/span>findall<span class=\"token punctuation\">(<\/span><span class=\"token string\">r&#039;data-id&#061;&#034;(\\\\d&#043;)&#034;&#039;<\/span><span class=\"token punctuation\">,<\/span> html<span class=\"token punctuation\">)<\/span><br \/>\n<span class=\"token keyword\">for<\/span> i<span class=\"token punctuation\">,<\/span> t<span class=\"token punctuation\">,<\/span> p <span class=\"token keyword\">in<\/span> <span class=\"token builtin\">zip<\/span><span class=\"token punctuation\">(<\/span>ids<span class=\"token punctuation\">,<\/span> titles<span class=\"token punctuation\">,<\/span> prices<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;[Regex] ID:<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>i<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\"> <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>t<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\"> <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>p<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token comment\"># &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061; \u65b9\u68484: pyquery &#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;&#061;<\/span><br \/>\n<span class=\"token keyword\">from<\/span> pyquery <span class=\"token keyword\">import<\/span> PyQuery <span class=\"token keyword\">as<\/span> pq<\/p>\n<p>doc <span class=\"token operator\">&#061;<\/span> pq<span class=\"token punctuation\">(<\/span>html<span class=\"token punctuation\">)<\/span><br \/>\n<span class=\"token keyword\">for<\/span> item <span class=\"token keyword\">in<\/span> doc<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;.item&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>items<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    title <span class=\"token operator\">&#061;<\/span> item<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;.title&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>text<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    price <span class=\"token operator\">&#061;<\/span> item<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;.price&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>text<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    book_id <span class=\"token operator\">&#061;<\/span> item<span class=\"token punctuation\">.<\/span>attr<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;data-id&#034;<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;[PyQuery] ID:<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>book_id<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\"> <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>title<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\"> <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>price<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><\/p>\n<h4>4.3 \u6027\u80fd\u57fa\u51c6\u6d4b\u8bd5\u53c2\u8003<\/h4>\n<p>\u6d4b\u8bd5\u6761\u4ef6&#xff1a;10000\u6b21\u91cd\u590d\u89e3\u6790\u540c\u4e00HTML\u9875\u9762<\/p>\n<p>\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510<br \/>\n\u2502 \u65b9\u6848            \u2502  \u8017\u65f6(s) \u2502  \u5185\u5b58(MB) \u2502<br \/>\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524<br \/>\n\u2502 selectolax      \u2502    0.3   \u2502    2.1   \u2502<br \/>\n\u2502 lxml (XPath)    \u2502    0.8   \u2502    5.3   \u2502<br \/>\n\u2502 parsel          \u2502    1.2   \u2502    6.1   \u2502<br \/>\n\u2502 pyquery         \u2502    1.5   \u2502    7.8   \u2502<br \/>\n\u2502 BS4 &#043; lxml      \u2502    3.2   \u2502   12.4   \u2502<br \/>\n\u2502 BS4&#043;html.parser \u2502    8.5   \u2502   10.2   \u2502<br \/>\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/p>\n<p>\u9762\u8bd5\u52a0\u5206\u63d0\u793a&#xff1a;\u5728\u9ad8\u5e76\u53d1\u722c\u866b\u573a\u666f&#xff08;\u5982 Scrapy&#xff09;&#xff0c;\u63a8\u8350\u4f7f\u7528 parsel&#xff08;Scrapy\u5185\u7f6e&#xff09;\u6216 lxml&#xff0c;\u5b83\u4eec\u57fa\u4e8e C \u6269\u5c55&#xff0c;\u6027\u80fd\u662f BeautifulSoup \u7684 3-10 \u500d\u3002selectolax \u57fa\u4e8e Modest\/lexbor \u5f15\u64ce&#xff0c;\u662f\u76ee\u524d\u6700\u5feb\u7684 Python HTML \u89e3\u6790\u5e93\u3002<\/p>\n<h3>5. \u4e3b\u6d41\u722c\u866b\u6846\u67b6\u8be6\u89e3<\/h3>\n<h4>5.1 Scrapy \u67b6\u6784\u5168\u666f<\/h4>\n<p>\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510<br \/>\n\u2502                     Scrapy \u6838\u5fc3\u67b6\u6784                               \u2502<br \/>\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524<br \/>\n\u2502                                                                 \u2502<br \/>\n\u2502                        \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510                             \u2502<br \/>\n\u2502                        \u2502  Engine  \u2502  (\u6838\u5fc3\u5f15\u64ce&#xff0c;\u9a71\u52a8\u6570\u636e\u6d41)       \u2502<br \/>\n\u2502                        \u2514\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2518                             \u2502<br \/>\n\u2502                             \u2502                                   \u2502<br \/>\n\u2502              \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510                    \u2502<br \/>\n\u2502              \u2502              \u2502              \u2502                     \u2502<br \/>\n\u2502    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25bc\u2500\u2500\u2510  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u25bc\u2500\u2500\u2500\u2500\u2500\u2500\u2510  \u250c\u2500\u2500\u2500\u25bc\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510         \u2502<br \/>\n\u2502    \u2502 Scheduler  \u2502  \u2502  Downloader  \u2502  \u2502   Spider     \u2502         \u2502<br \/>\n\u2502    \u2502  (\u8c03\u5ea6\u5668)  \u2502  \u2502  (\u4e0b\u8f7d\u5668)    \u2502  \u2502  (\u722c\u866b\u903b\u8f91)  \u2502         \u2502<br \/>\n\u2502    \u2514\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2518  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2518  \u2514\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518         \u2502<br \/>\n\u2502          \u2502                 \u2502                \u2502                   \u2502<br \/>\n\u2502    \u250c\u2500\u2500\u2500\u2500\u2500\u25bc\u2500\u2500\u2500\u2500\u2500\u2500\u2510  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u25bc\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510  \u250c\u2500\u2500\u2500\u2500\u25bc\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510         \u2502<br \/>\n\u2502    \u2502  \u8bf7\u6c42\u961f\u5217  \u2502  \u2502 \u4e0b\u8f7d\u4e2d\u95f4\u4ef6   \u2502  \u2502   \u89e3\u6790\u56de\u8c03   \u2502         \u2502<br \/>\n\u2502    \u2502(Redis\/\u672c\u5730)\u2502  \u2502(\u4ee3\u7406\/\u91cd\u8bd5\/UA)\u2502  \u2502   (parse)    \u2502         \u2502<br \/>\n\u2502    \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518         \u2502<br \/>\n\u2502                                              \u2502                  \u2502<br \/>\n\u2502                                       \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u25bc\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510         \u2502<br \/>\n\u2502                                       \u2502   Pipeline   \u2502         \u2502<br \/>\n\u2502                                       \u2502(\u6e05\u6d17\/\u9a8c\u8bc1\/\u5b58\u50a8)\u2502        \u2502<br \/>\n\u2502                                       \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518         \u2502<br \/>\n\u2502                                                                 \u2502<br \/>\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/p>\n<h4>5.2 Scrapy \u6838\u5fc3\u7ec4\u4ef6<\/h4>\n<table>\n<tr>\u7ec4\u4ef6\u804c\u8d23\u5173\u952e\u914d\u7f6e<\/tr>\n<tbody>\n<tr>\n<td>Engine<\/td>\n<td>\u63a7\u5236\u6570\u636e\u6d41&#xff0c;\u89e6\u53d1\u4e8b\u4ef6<\/td>\n<td>\u81ea\u52a8\u7ba1\u7406<\/td>\n<\/tr>\n<tr>\n<td>Scheduler<\/td>\n<td>\u7ba1\u7406\u8bf7\u6c42\u961f\u5217&#xff0c;\u8c03\u5ea6\u4f18\u5148\u7ea7<\/td>\n<td>SCHEDULER<\/td>\n<\/tr>\n<tr>\n<td>Downloader<\/td>\n<td>\u6267\u884cHTTP\u8bf7\u6c42&#xff0c;\u83b7\u53d6\u7f51\u9875<\/td>\n<td>DOWNLOAD_TIMEOUT<\/td>\n<\/tr>\n<tr>\n<td>Spider<\/td>\n<td>\u89e3\u6790\u54cd\u5e94&#xff0c;\u63d0\u53d6\u6570\u636e\/\u65b0\u8bf7\u6c42<\/td>\n<td>\u81ea\u5b9a\u4e49 parse()<\/td>\n<\/tr>\n<tr>\n<td>Item<\/td>\n<td>\u5b9a\u4e49\u6570\u636e\u7ed3\u6784<\/td>\n<td>scrapy.Item<\/td>\n<\/tr>\n<tr>\n<td>Pipeline<\/td>\n<td>\u6e05\u6d17\u3001\u9a8c\u8bc1\u3001\u5b58\u50a8\u6570\u636e<\/td>\n<td>ITEM_PIPELINES<\/td>\n<\/tr>\n<tr>\n<td>Middleware<\/td>\n<td>\u62e6\u622a\/\u4fee\u6539\u8bf7\u6c42\u548c\u54cd\u5e94<\/td>\n<td>DOWNLOADER_MIDDLEWARES<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>5.3 Scrapy \u5b9e\u6218\u793a\u4f8b<\/h4>\n<p><span class=\"token comment\"># items.py &#8211; \u5b9a\u4e49\u6570\u636e\u7ed3\u6784<\/span><br \/>\n<span class=\"token keyword\">import<\/span> scrapy<\/p>\n<p><span class=\"token keyword\">class<\/span> <span class=\"token class-name\">BookItem<\/span><span class=\"token punctuation\">(<\/span>scrapy<span class=\"token punctuation\">.<\/span>Item<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    title <span class=\"token operator\">&#061;<\/span> scrapy<span class=\"token punctuation\">.<\/span>Field<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    price <span class=\"token operator\">&#061;<\/span> scrapy<span class=\"token punctuation\">.<\/span>Field<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    rating <span class=\"token operator\">&#061;<\/span> scrapy<span class=\"token punctuation\">.<\/span>Field<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    url <span class=\"token operator\">&#061;<\/span> scrapy<span class=\"token punctuation\">.<\/span>Field<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token comment\"># spiders\/books.py &#8211; \u722c\u866b\u903b\u8f91<\/span><br \/>\n<span class=\"token keyword\">import<\/span> scrapy<br \/>\n<span class=\"token keyword\">from<\/span> <span class=\"token punctuation\">.<\/span><span class=\"token punctuation\">.<\/span>items <span class=\"token keyword\">import<\/span> BookItem<\/p>\n<p><span class=\"token keyword\">class<\/span> <span class=\"token class-name\">BooksSpider<\/span><span class=\"token punctuation\">(<\/span>scrapy<span class=\"token punctuation\">.<\/span>Spider<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    name <span class=\"token operator\">&#061;<\/span> <span class=\"token string\">&#034;books&#034;<\/span><br \/>\n    allowed_domains <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;books.toscrape.com&#034;<\/span><span class=\"token punctuation\">]<\/span><br \/>\n    start_urls <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;https:\/\/books.toscrape.com\/&#034;<\/span><span class=\"token punctuation\">]<\/span><\/p>\n<p>    <span class=\"token comment\"># \u81ea\u5b9a\u4e49\u8bbe\u7f6e<\/span><br \/>\n    custom_settings <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token string\">&#034;DOWNLOAD_DELAY&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token string\">&#034;CONCURRENT_REQUESTS_PER_DOMAIN&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token number\">4<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">parse<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> response<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token keyword\">for<\/span> book <span class=\"token keyword\">in<\/span> response<span class=\"token punctuation\">.<\/span>css<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;article.product_pod&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n            item <span class=\"token operator\">&#061;<\/span> BookItem<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n            item<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;title&#034;<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#061;<\/span> book<span class=\"token punctuation\">.<\/span>css<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;h3 a::attr(title)&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n            item<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;price&#034;<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#061;<\/span> book<span class=\"token punctuation\">.<\/span>css<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;.price_color::text&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n            item<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;rating&#034;<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#061;<\/span> book<span class=\"token punctuation\">.<\/span>css<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;p.star-rating::attr(class)&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n            item<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;url&#034;<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#061;<\/span> response<span class=\"token punctuation\">.<\/span>urljoin<span class=\"token punctuation\">(<\/span>book<span class=\"token punctuation\">.<\/span>css<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;h3 a::attr(href)&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><br \/>\n            <span class=\"token keyword\">yield<\/span> item<\/p>\n<p>        <span class=\"token comment\"># \u81ea\u52a8\u7ffb\u9875<\/span><br \/>\n        next_page <span class=\"token operator\">&#061;<\/span> response<span class=\"token punctuation\">.<\/span>css<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;li.next a::attr(href)&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> next_page<span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">yield<\/span> response<span class=\"token punctuation\">.<\/span>follow<span class=\"token punctuation\">(<\/span>next_page<span class=\"token punctuation\">,<\/span> self<span class=\"token punctuation\">.<\/span>parse<span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token comment\"># pipelines.py &#8211; \u6570\u636e\u5b58\u50a8\u7ba1\u9053<\/span><br \/>\n<span class=\"token keyword\">import<\/span> pymongo<\/p>\n<p><span class=\"token keyword\">class<\/span> <span class=\"token class-name\">MongoDBPipeline<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token keyword\">def<\/span> <span class=\"token function\">__init__<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> mongo_uri<span class=\"token punctuation\">,<\/span> db_name<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>mongo_uri <span class=\"token operator\">&#061;<\/span> mongo_uri<br \/>\n        self<span class=\"token punctuation\">.<\/span>db_name <span class=\"token operator\">&#061;<\/span> db_name<\/p>\n<p>    <span class=\"token decorator annotation punctuation\">&#064;classmethod<\/span><br \/>\n    <span class=\"token keyword\">def<\/span> <span class=\"token function\">from_crawler<\/span><span class=\"token punctuation\">(<\/span>cls<span class=\"token punctuation\">,<\/span> crawler<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> cls<span class=\"token punctuation\">(<\/span><br \/>\n            mongo_uri<span class=\"token operator\">&#061;<\/span>crawler<span class=\"token punctuation\">.<\/span>settings<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;MONGO_URI&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            db_name<span class=\"token operator\">&#061;<\/span>crawler<span class=\"token punctuation\">.<\/span>settings<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;MONGO_DB&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token punctuation\">)<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">open_spider<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> spider<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>client <span class=\"token operator\">&#061;<\/span> pymongo<span class=\"token punctuation\">.<\/span>MongoClient<span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">.<\/span>mongo_uri<span class=\"token punctuation\">)<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>db <span class=\"token operator\">&#061;<\/span> self<span class=\"token punctuation\">.<\/span>client<span class=\"token punctuation\">[<\/span>self<span class=\"token punctuation\">.<\/span>db_name<span class=\"token punctuation\">]<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">process_item<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> item<span class=\"token punctuation\">,<\/span> spider<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>db<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;books&#034;<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">.<\/span>update_one<span class=\"token punctuation\">(<\/span><br \/>\n            <span class=\"token punctuation\">{<\/span><span class=\"token string\">&#034;url&#034;<\/span><span class=\"token punctuation\">:<\/span> item<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;url&#034;<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token punctuation\">{<\/span><span class=\"token string\">&#034;$set&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">dict<\/span><span class=\"token punctuation\">(<\/span>item<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            upsert<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">True<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> item<\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">close_spider<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> spider<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>client<span class=\"token punctuation\">.<\/span>close<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<h4>5.4 \u6846\u67b6\u6a2a\u5411\u5bf9\u6bd4<\/h4>\n<table>\n<tr>\u6846\u67b6\u8bed\u8a00\u5f02\u6b65\u5206\u5e03\u5f0f\u52a8\u6001\u6e32\u67d3\u5b66\u4e60\u66f2\u7ebf\u9002\u7528\u89c4\u6a21<\/tr>\n<tbody>\n<tr>\n<td>Scrapy<\/td>\n<td>Python<\/td>\n<td>\u652f\u6301(asyncio)<\/td>\n<td>\u652f\u6301(scrapy-redis)<\/td>\n<td>\u9700\u6269\u5c55<\/td>\n<td>\u4e2d<\/td>\n<td>\u5927\u578b<\/td>\n<\/tr>\n<tr>\n<td>httpx&#043;bs4<\/td>\n<td>Python<\/td>\n<td>\u652f\u6301(asyncio)<\/td>\n<td>\u9700\u81ea\u5efa<\/td>\n<td>\u9700\u914d\u5408<\/td>\n<td>\u4f4e<\/td>\n<td>\u5c0f\u578b<\/td>\n<\/tr>\n<tr>\n<td>Feapder<\/td>\n<td>Python<\/td>\n<td>\u652f\u6301<\/td>\n<td>\u652f\u6301<\/td>\n<td>\u5185\u7f6ePlaywright<\/td>\n<td>\u4f4e<\/td>\n<td>\u4e2d\u578b<\/td>\n<\/tr>\n<tr>\n<td>Crawley<\/td>\n<td>Python<\/td>\n<td>\u4e0d\u652f\u6301<\/td>\n<td>\u4e0d\u652f\u6301<\/td>\n<td>\u4e0d\u652f\u6301<\/td>\n<td>\u4f4e<\/td>\n<td>\u5c0f\u578b<\/td>\n<\/tr>\n<tr>\n<td>PySpider<\/td>\n<td>Python<\/td>\n<td>\u652f\u6301<\/td>\n<td>\u652f\u6301<\/td>\n<td>\u652f\u6301<\/td>\n<td>\u4e2d<\/td>\n<td>\u4e2d\u578b(\u5df2\u505c\u66f4)<\/td>\n<\/tr>\n<tr>\n<td>Colly<\/td>\n<td>Go<\/td>\n<td>\u652f\u6301<\/td>\n<td>\u9700\u81ea\u5efa<\/td>\n<td>\u4e0d\u652f\u6301<\/td>\n<td>\u4e2d<\/td>\n<td>\u5927\u578b<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u751f\u4ea7\u8e29\u5751\u63d0\u9192&#xff1a;2025\u5e74 Scrapy \u9ed8\u8ba4 download_delay \u4ece 0 \u79d2\u6539\u4e3a 1 \u79d2&#xff0c;concurrent_requests_per_domain \u4ece 8 \u964d\u4e3a 1\u3002\u8fd9\u662f\u4e3a\u4e86\u964d\u4f4e\u5bf9\u76ee\u6807\u7f51\u7ad9\u7684\u538b\u529b\u3001\u964d\u4f4e\u6cd5\u5f8b\u98ce\u9669\u3002\u5982\u9700\u9ad8\u5e76\u53d1&#xff0c;\u9700\u624b\u52a8\u8c03\u6574\u914d\u7f6e\u3002<\/p>\n<hr \/>\n<h3>6. \u52a8\u6001\u9875\u9762\u722c\u53d6<\/h3>\n<h4>6.1 \u4e09\u5927\u6d4f\u89c8\u5668\u81ea\u52a8\u5316\u5de5\u5177\u5bf9\u6bd4<\/h4>\n<table>\n<tr>\u7279\u6027SeleniumPlaywrightPuppeteer<\/tr>\n<tbody>\n<tr>\n<td>\u5f00\u53d1\u5546<\/td>\n<td>SeleniumHQ<\/td>\n<td>Microsoft<\/td>\n<td>Google<\/td>\n<\/tr>\n<tr>\n<td>\u6d4f\u89c8\u5668\u652f\u6301<\/td>\n<td>Chrome\/Firefox\/Safari\/Edge<\/td>\n<td>Chromium\/Firefox\/WebKit<\/td>\n<td>\u4ec5Chromium<\/td>\n<\/tr>\n<tr>\n<td>\u8bed\u8a00\u652f\u6301<\/td>\n<td>Python\/Java\/C#\/JS<\/td>\n<td>Python\/JS\/Java\/.NET<\/td>\n<td>JS\/Python(\u975e\u5b98\u65b9)<\/td>\n<\/tr>\n<tr>\n<td>\u81ea\u52a8\u7b49\u5f85<\/td>\n<td>\u4e0d\u652f\u6301&#xff0c;\u9700\u624b\u52a8<\/td>\n<td>\u652f\u6301\u667a\u80fd\u7b49\u5f85<\/td>\n<td>\u4e0d\u652f\u6301&#xff0c;\u9700\u624b\u52a8<\/td>\n<\/tr>\n<tr>\n<td>\u7f51\u7edc\u62e6\u622a<\/td>\n<td>\u6709\u9650<\/td>\n<td>\u5f3a\u5927<\/td>\n<td>\u5f3a\u5927<\/td>\n<\/tr>\n<tr>\n<td>\u6267\u884c\u901f\u5ea6<\/td>\n<td>\u6162<\/td>\n<td>\u5feb&#xff08;\u5feb30%\u4ee5\u4e0a&#xff09;<\/td>\n<td>\u5feb<\/td>\n<\/tr>\n<tr>\n<td>\u65e0\u5934\u6a21\u5f0f<\/td>\n<td>\u652f\u6301<\/td>\n<td>\u652f\u6301&#xff08;\u9ed8\u8ba4&#xff09;<\/td>\n<td>\u652f\u6301<\/td>\n<\/tr>\n<tr>\n<td>\u79fb\u52a8\u7aef\u6a21\u62df<\/td>\n<td>\u6709\u9650<\/td>\n<td>\u652f\u6301\u8bbe\u5907\u63cf\u8ff0\u7b26<\/td>\n<td>\u652f\u6301<\/td>\n<\/tr>\n<tr>\n<td>\u622a\u56fe\/\u5f55\u5c4f<\/td>\n<td>\u622a\u56fe<\/td>\n<td>\u622a\u56fe&#043;\u5f55\u5c4f<\/td>\n<td>\u622a\u56fe&#043;\u5f55\u5c4f<\/td>\n<\/tr>\n<tr>\n<td>\u793e\u533a\u6d3b\u8dc3\u5ea6<\/td>\n<td>\u9ad8&#xff08;\u8001\u724c&#xff09;<\/td>\n<td>\u6781\u9ad8&#xff08;\u65b0\u661f&#xff09;<\/td>\n<td>\u4e2d<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>6.2 Playwright \u5b9e\u6218<\/h4>\n<p><span class=\"token keyword\">from<\/span> playwright<span class=\"token punctuation\">.<\/span>sync_api <span class=\"token keyword\">import<\/span> sync_playwright<br \/>\n<span class=\"token keyword\">import<\/span> json<\/p>\n<p><span class=\"token keyword\">def<\/span> <span class=\"token function\">crawl_spa_page<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u4f7f\u7528Playwright\u722c\u53d6SPA\u52a8\u6001\u9875\u9762&#034;&#034;&#034;<\/span><br \/>\n    <span class=\"token keyword\">with<\/span> sync_playwright<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">as<\/span> p<span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token comment\"># \u542f\u52a8\u6d4f\u89c8\u5668&#xff08;Chromium&#xff0c;\u65e0\u5934\u6a21\u5f0f&#xff09;<\/span><br \/>\n        browser <span class=\"token operator\">&#061;<\/span> p<span class=\"token punctuation\">.<\/span>chromium<span class=\"token punctuation\">.<\/span>launch<span class=\"token punctuation\">(<\/span><br \/>\n            headless<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">True<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            args<span class=\"token operator\">&#061;<\/span><span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;&#8211;disable-blink-features&#061;AutomationControlled&#034;<\/span><span class=\"token punctuation\">]<\/span><br \/>\n        <span class=\"token punctuation\">)<\/span><\/p>\n<p>        <span class=\"token comment\"># \u521b\u5efa\u4e0a\u4e0b\u6587&#xff08;\u6a21\u62df\u771f\u5b9e\u8bbe\u5907&#xff09;<\/span><br \/>\n        context <span class=\"token operator\">&#061;<\/span> browser<span class=\"token punctuation\">.<\/span>new_context<span class=\"token punctuation\">(<\/span><br \/>\n            viewport<span class=\"token operator\">&#061;<\/span><span class=\"token punctuation\">{<\/span><span class=\"token string\">&#034;width&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token number\">1920<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;height&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token number\">1080<\/span><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            user_agent<span class=\"token operator\">&#061;<\/span><span class=\"token string\">&#034;Mozilla\/5.0 (Windows NT 10.0; Win64; x64) &#034;<\/span><br \/>\n                       <span class=\"token string\">&#034;AppleWebKit\/537.36 (KHTML, like Gecko) &#034;<\/span><br \/>\n                       <span class=\"token string\">&#034;Chrome\/131.0.0.0 Safari\/537.36&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            locale<span class=\"token operator\">&#061;<\/span><span class=\"token string\">&#034;zh-CN&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            timezone_id<span class=\"token operator\">&#061;<\/span><span class=\"token string\">&#034;Asia\/Shanghai&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token punctuation\">)<\/span><\/p>\n<p>        page <span class=\"token operator\">&#061;<\/span> context<span class=\"token punctuation\">.<\/span>new_page<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>        <span class=\"token comment\"># \u62e6\u622aXHR\/Fetch\u8bf7\u6c42&#xff0c;\u63d0\u53d6API\u6570\u636e<\/span><br \/>\n        api_responses <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">]<\/span><br \/>\n        <span class=\"token keyword\">def<\/span> <span class=\"token function\">handle_response<\/span><span class=\"token punctuation\">(<\/span>response<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token string\">&#034;\/api\/&#034;<\/span> <span class=\"token keyword\">in<\/span> response<span class=\"token punctuation\">.<\/span>url<span class=\"token punctuation\">:<\/span><br \/>\n                <span class=\"token keyword\">try<\/span><span class=\"token punctuation\">:<\/span><br \/>\n                    api_responses<span class=\"token punctuation\">.<\/span>append<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span><br \/>\n                        <span class=\"token string\">&#034;url&#034;<\/span><span class=\"token punctuation\">:<\/span> response<span class=\"token punctuation\">.<\/span>url<span class=\"token punctuation\">,<\/span><br \/>\n                        <span class=\"token string\">&#034;status&#034;<\/span><span class=\"token punctuation\">:<\/span> response<span class=\"token punctuation\">.<\/span>status<span class=\"token punctuation\">,<\/span><br \/>\n                        <span class=\"token string\">&#034;body&#034;<\/span><span class=\"token punctuation\">:<\/span> response<span class=\"token punctuation\">.<\/span>json<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n                    <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><br \/>\n                <span class=\"token keyword\">except<\/span> Exception<span class=\"token punctuation\">:<\/span><br \/>\n                    <span class=\"token keyword\">pass<\/span><\/p>\n<p>        page<span class=\"token punctuation\">.<\/span>on<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;response&#034;<\/span><span class=\"token punctuation\">,<\/span> handle_response<span class=\"token punctuation\">)<\/span><\/p>\n<p>        <span class=\"token comment\"># \u5bfc\u822a\u5230\u76ee\u6807\u9875\u9762<\/span><br \/>\n        page<span class=\"token punctuation\">.<\/span>goto<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;https:\/\/quotes.toscrape.com\/js\/&#034;<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>        <span class=\"token comment\"># \u7b49\u5f85\u52a8\u6001\u5185\u5bb9\u52a0\u8f7d<\/span><br \/>\n        page<span class=\"token punctuation\">.<\/span>wait_for_selector<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;.quote&#034;<\/span><span class=\"token punctuation\">,<\/span> state<span class=\"token operator\">&#061;<\/span><span class=\"token string\">&#034;visible&#034;<\/span><span class=\"token punctuation\">,<\/span> timeout<span class=\"token operator\">&#061;<\/span><span class=\"token number\">10000<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>        <span class=\"token comment\"># \u63d0\u53d6\u6e32\u67d3\u540e\u7684\u6570\u636e<\/span><br \/>\n        quotes <span class=\"token operator\">&#061;<\/span> page<span class=\"token punctuation\">.<\/span>query_selector_all<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;.quote&#034;<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        results <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">]<\/span><br \/>\n        <span class=\"token keyword\">for<\/span> quote <span class=\"token keyword\">in<\/span> quotes<span class=\"token punctuation\">:<\/span><br \/>\n            text <span class=\"token operator\">&#061;<\/span> quote<span class=\"token punctuation\">.<\/span>query_selector<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;.text&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>inner_text<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n            author <span class=\"token operator\">&#061;<\/span> quote<span class=\"token punctuation\">.<\/span>query_selector<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;.author&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>inner_text<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n            results<span class=\"token punctuation\">.<\/span>append<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span><span class=\"token string\">&#034;text&#034;<\/span><span class=\"token punctuation\">:<\/span> text<span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;author&#034;<\/span><span class=\"token punctuation\">:<\/span> author<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>        <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u63d0\u53d6\u5230 <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span><span class=\"token builtin\">len<\/span><span class=\"token punctuation\">(<\/span>results<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\"> \u6761\u540d\u8a00&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u62e6\u622a\u5230 <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span><span class=\"token builtin\">len<\/span><span class=\"token punctuation\">(<\/span>api_responses<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\"> \u4e2aAPI\u54cd\u5e94&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>        browser<span class=\"token punctuation\">.<\/span>close<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> results<\/p>\n<p><span class=\"token comment\"># crawl_spa_page()<\/span><\/p>\n<h4>6.3 JS\u6e32\u67d3\u7b49\u5f85\u7b56\u7565<\/h4>\n<table>\n<tr>\u7b56\u7565\u8bf4\u660e\u9002\u7528\u573a\u666f\u4ee3\u7801\u793a\u4f8b<\/tr>\n<tbody>\n<tr>\n<td>\u56fa\u5b9a\u7b49\u5f85<\/td>\n<td>time.sleep(n)<\/td>\n<td>\u8c03\u8bd5\u7528&#xff0c;\u4e0d\u63a8\u8350<\/td>\n<td>time.sleep(3)<\/td>\n<\/tr>\n<tr>\n<td>\u5143\u7d20\u7b49\u5f85<\/td>\n<td>\u7b49\u5f85\u7279\u5b9a\u5143\u7d20\u51fa\u73b0<\/td>\n<td>\u6700\u5e38\u7528<\/td>\n<td>wait_for_selector(&#034;.data&#034;)<\/td>\n<\/tr>\n<tr>\n<td>\u7f51\u7edc\u7a7a\u95f2<\/td>\n<td>\u7b49\u5f85\u65e0\u65b0\u8bf7\u6c42<\/td>\n<td>SPA\u52a0\u8f7d<\/td>\n<td>wait_for_load_state(&#034;networkidle&#034;)<\/td>\n<\/tr>\n<tr>\n<td>DOM\u52a0\u8f7d<\/td>\n<td>DOM\u89e3\u6790\u5b8c\u6210<\/td>\n<td>\u9759\u6001\u5185\u5bb9<\/td>\n<td>wait_for_load_state(&#034;domcontentloaded&#034;)<\/td>\n<\/tr>\n<tr>\n<td>\u81ea\u5b9a\u4e49\u6761\u4ef6<\/td>\n<td>\u8f6e\u8be2\u68c0\u67e5<\/td>\n<td>\u590d\u6742\u573a\u666f<\/td>\n<td>page.wait_for_function(&#8230;)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span class=\"token comment\"># \u9ad8\u7ea7\u7b49\u5f85\u7b56\u7565\u793a\u4f8b<\/span><br \/>\n<span class=\"token comment\"># \u7b49\u5f85\u76f4\u5230\u67d0\u4e2a\u5143\u7d20\u7684\u6587\u672c\u4e0d\u518d\u5305\u542b&#034;\u52a0\u8f7d\u4e2d&#034;<\/span><br \/>\npage<span class=\"token punctuation\">.<\/span>wait_for_function<span class=\"token punctuation\">(<\/span><br \/>\n    <span class=\"token string\">&#034;() &#061;&gt; !document.querySelector(&#039;.status&#039;).textContent.includes(&#039;loading&#039;)&#034;<\/span><br \/>\n<span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token comment\"># \u7b49\u5f85API\u8bf7\u6c42\u5b8c\u6210<\/span><br \/>\n<span class=\"token keyword\">with<\/span> page<span class=\"token punctuation\">.<\/span>expect_response<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;**\/api\/data*&#034;<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">as<\/span> response_info<span class=\"token punctuation\">:<\/span><br \/>\n    page<span class=\"token punctuation\">.<\/span>click<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;#load-button&#034;<\/span><span class=\"token punctuation\">)<\/span><br \/>\nresponse <span class=\"token operator\">&#061;<\/span> response_info<span class=\"token punctuation\">.<\/span>value<br \/>\ndata <span class=\"token operator\">&#061;<\/span> response<span class=\"token punctuation\">.<\/span>json<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>\u9762\u8bd5\u52a0\u5206\u63d0\u793a&#xff1a;Playwright \u7684 expect_response \u662f\u62e6\u622a API \u6570\u636e\u7684\u5229\u5668\u3002\u5f88\u591a SPA \u9875\u9762\u7684\u6570\u636e\u901a\u8fc7 JSON API \u8fd4\u56de&#xff0c;\u76f4\u63a5\u62e6\u622a API \u54cd\u5e94\u6bd4\u89e3\u6790 DOM \u66f4\u9ad8\u6548\u3001\u66f4\u7a33\u5b9a\u3002<\/p>\n<hr \/>\n<h3>7. \u53cd\u722c\u866b\u6280\u672f\u5168\u89e3<\/h3>\n<h4>7.1 \u53cd\u722c\u6280\u672f\u5206\u7c7b\u5168\u666f<\/h4>\n<p>\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510<br \/>\n\u2502                   \u53cd\u722c\u866b\u6280\u672f\u4f53\u7cfb\u5168\u666f                                \u2502<br \/>\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524<br \/>\n\u2502                                                                  \u2502<br \/>\n\u2502  \u8bf7\u6c42\u5c42\u68c0\u6d4b:                                                     \u2502<br \/>\n\u2502  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#043;  \u2502<br \/>\n\u2502  | User-Agent\u68c0\u6d4b | Referer\u6821\u9a8c | Accept\u5934\u6821\u9a8c                |  \u2502<br \/>\n\u2502  | Cookie\u5b8c\u6574\u6027   | \u8bf7\u6c42\u5934\u987a\u5e8f  | Accept-Language             |  \u2502<br \/>\n\u2502  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#043;  \u2502<br \/>\n\u2502                                                                  \u2502<br \/>\n\u2502  \u7f51\u7edc\u5c42\u68c0\u6d4b:                                                     \u2502<br \/>\n\u2502  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#043;  \u2502<br \/>\n\u2502  | IP\u9891\u7387\u9650\u5236   | IP\u4fe1\u8a89\u8bc4\u5206    | TLS\u6307\u7eb9(JA3\/JA4)           |  \u2502<br \/>\n\u2502  | HTTP\/2\u6307\u7eb9   | TCP\u6307\u7eb9       | \u5730\u7406\u4f4d\u7f6e\u68c0\u6d4b                |  \u2502<br \/>\n\u2502  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#043;  \u2502<br \/>\n\u2502                                                                  \u2502<br \/>\n\u2502  \u884c\u4e3a\u5c42\u68c0\u6d4b:                                                     \u2502<br \/>\n\u2502  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#043;  \u2502<br \/>\n\u2502  | \u8bf7\u6c42\u9891\u7387\u5f02\u5e38 | \u9f20\u6807\u8f68\u8ff9\u5206\u6790  | \u9875\u9762\u505c\u7559\u65f6\u95f4               |  \u2502<br \/>\n\u2502  | \u6eda\u52a8\u884c\u4e3a\u6a21\u5f0f | \u70b9\u51fb\u6a21\u5f0f      | \u6d4f\u89c8\u5668\u6307\u7eb9(Canvas\/WebGL)   |  \u2502<br \/>\n\u2502  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#043;  \u2502<br \/>\n\u2502                                                                  \u2502<br \/>\n\u2502  \u9a8c\u8bc1\u5c42\u6311\u6218:                                                     \u2502<br \/>\n\u2502  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#043;  \u2502<br \/>\n\u2502  | \u56fe\u7247\u9a8c\u8bc1\u7801  | \u6ed1\u5757\u9a8c\u8bc1\u7801    | \u70b9\u9009\u9a8c\u8bc1\u7801                  |  \u2502<br \/>\n\u2502  | \u884c\u4e3a\u9a8c\u8bc1\u7801  | reCAPTCHA v3  | hCaptcha                   |  \u2502<br \/>\n\u2502  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#043;  \u2502<br \/>\n\u2502                                                                  \u2502<br \/>\n\u2502  \u9ad8\u7ea7\u9632\u62a4:                                                       \u2502<br \/>\n\u2502  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#043;  \u2502<br \/>\n\u2502  | JS\u6df7\u6dc6\/JSVMP  | \u871c\u7f50\u9677\u9631     | \u52a8\u6001Token                 |  \u2502<br \/>\n\u2502  | \u5b57\u4f53\u53cd\u722c      | Cookie\u52a0\u5bc6   | \u745e\u6570\/\u6570\u7f8e\u5546\u4e1a\u9632\u62a4           |  \u2502<br \/>\n\u2502  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#043;  \u2502<br \/>\n\u2502                                                                  \u2502<br \/>\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/p>\n<h4>7.2 \u5404\u5c42\u53cd\u722c\u8be6\u89e3<\/h4>\n<table>\n<tr>\u53cd\u722c\u7c7b\u578b\u68c0\u6d4b\u539f\u7406\u96be\u5ea6\u5178\u578b\u4ea7\u54c1<\/tr>\n<tbody>\n<tr>\n<td>User-Agent\u68c0\u6d4b<\/td>\n<td>\u68c0\u67e5UA\u662f\u5426\u4e3a\u5df2\u77e5\u722c\u866b<\/td>\n<td>\u4f4e<\/td>\n<td>\u57fa\u7840\u9632\u62a4<\/td>\n<\/tr>\n<tr>\n<td>IP\u9650\u5236<\/td>\n<td>\u5355IP\u8bf7\u6c42\u9891\u7387\u8fc7\u9ad8\u5219\u5c01\u7981<\/td>\n<td>\u4e2d<\/td>\n<td>\u5927\u591a\u6570\u7f51\u7ad9<\/td>\n<\/tr>\n<tr>\n<td>Cookie\u9a8c\u8bc1<\/td>\n<td>\u9996\u6b21\u8bbf\u95ee\u8bbe\u7f6e\u52a0\u5bc6Cookie<\/td>\n<td>\u9ad8<\/td>\n<td>Cloudflare<\/td>\n<\/tr>\n<tr>\n<td>JS\u6311\u6218<\/td>\n<td>\u6267\u884cJS\u8ba1\u7b97\u751f\u6210Token<\/td>\n<td>\u9ad8<\/td>\n<td>\u745e\u6570\u4fe1\u606f<\/td>\n<\/tr>\n<tr>\n<td>TLS\u6307\u7eb9<\/td>\n<td>\u68c0\u6d4bJA3\/JA4\u6307\u7eb9<\/td>\n<td>\u5f88\u9ad8<\/td>\n<td>Akamai\/DataDome<\/td>\n<\/tr>\n<tr>\n<td>\u6d4f\u89c8\u5668\u6307\u7eb9<\/td>\n<td>Canvas\/WebGL\/Audio\u6307\u7eb9<\/td>\n<td>\u5f88\u9ad8<\/td>\n<td>Cloudflare<\/td>\n<\/tr>\n<tr>\n<td>\u884c\u4e3a\u5206\u6790<\/td>\n<td>\u9f20\u6807\u8f68\u8ff9\u3001\u70b9\u51fb\u6a21\u5f0f<\/td>\n<td>\u5f88\u9ad8<\/td>\n<td>\u6570\u7f8e\/\u6781\u9a8c<\/td>\n<\/tr>\n<tr>\n<td>JSVMP<\/td>\n<td>JS\u865a\u62df\u5316\u4fdd\u62a4<\/td>\n<td>\u6781\u9ad8<\/td>\n<td>\u745e\u6570\/\u6570\u7f8e<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>7.3 \u871c\u7f50\u9677\u9631\u68c0\u6d4b<\/h4>\n<p><span class=\"token comment\"># \u871c\u7f50\u68c0\u6d4b\u793a\u4f8b &#8212; \u7f51\u7ad9\u5728HTML\u4e2d\u653e\u7f6e\u9690\u85cf\u94fe\u63a5<\/span><br \/>\n<span class=\"token comment\"># \u6b63\u5e38\u7528\u6237\u4e0d\u53ef\u89c1&#xff0c;\u4f46\u722c\u866b\u4f1a\u8ddf\u968f<\/span><\/p>\n<p><span class=\"token keyword\">from<\/span> lxml <span class=\"token keyword\">import<\/span> etree<\/p>\n<p>hidden_html <span class=\"token operator\">&#061;<\/span> <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;<br \/>\n&lt;div style&#061;&#034;display:none; position:absolute; left:-9999px;&#034;&gt;<br \/>\n    &lt;a href&#061;&#034;\/admin\/secret&#034; class&#061;&#034;trap&#034;&gt;\u7ba1\u7406\u5165\u53e3&lt;\/a&gt;<br \/>\n    &lt;a href&#061;&#034;\/api\/internal&#034; class&#061;&#034;trap&#034;&gt;\u5185\u90e8\u63a5\u53e3&lt;\/a&gt;<br \/>\n&lt;\/div&gt;<br \/>\n&lt;a href&#061;&#034;\/real-page&#034; class&#061;&#034;real&#034;&gt;\u6b63\u5e38\u94fe\u63a5&lt;\/a&gt;<br \/>\n&#034;&#034;&#034;<\/span><\/p>\n<p><span class=\"token keyword\">def<\/span> <span class=\"token function\">is_visible<\/span><span class=\"token punctuation\">(<\/span>element<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u68c0\u67e5\u5143\u7d20\u662f\u5426\u53ef\u89c1&#xff08;\u7b80\u5316\u7248&#xff09;&#034;&#034;&#034;<\/span><br \/>\n    style <span class=\"token operator\">&#061;<\/span> element<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;style&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;&#034;<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    parent <span class=\"token operator\">&#061;<\/span> element<span class=\"token punctuation\">.<\/span>getparent<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>    <span class=\"token comment\"># \u68c0\u67e5display:none<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token string\">&#034;display:none&#034;<\/span> <span class=\"token keyword\">in<\/span> style <span class=\"token keyword\">or<\/span> <span class=\"token string\">&#034;display: none&#034;<\/span> <span class=\"token keyword\">in<\/span> style<span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">False<\/span><br \/>\n    <span class=\"token comment\"># \u68c0\u67e5position\u79fb\u51fa\u89c6\u53e3<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> <span class=\"token string\">&#034;left:-9999&#034;<\/span> <span class=\"token keyword\">in<\/span> style <span class=\"token keyword\">or<\/span> <span class=\"token string\">&#034;top:-9999&#034;<\/span> <span class=\"token keyword\">in<\/span> style<span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">False<\/span><br \/>\n    <span class=\"token comment\"># \u9012\u5f52\u68c0\u67e5\u7236\u5143\u7d20<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> parent <span class=\"token keyword\">is<\/span> <span class=\"token keyword\">not<\/span> <span class=\"token boolean\">None<\/span> <span class=\"token keyword\">and<\/span> parent<span class=\"token punctuation\">.<\/span>tag <span class=\"token operator\">!&#061;<\/span> <span class=\"token string\">&#034;html&#034;<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> is_visible<span class=\"token punctuation\">(<\/span>parent<span class=\"token punctuation\">)<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">True<\/span><\/p>\n<p>tree <span class=\"token operator\">&#061;<\/span> etree<span class=\"token punctuation\">.<\/span>HTML<span class=\"token punctuation\">(<\/span>hidden_html<span class=\"token punctuation\">)<\/span><br \/>\n<span class=\"token keyword\">for<\/span> link <span class=\"token keyword\">in<\/span> tree<span class=\"token punctuation\">.<\/span>xpath<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;\/\/a&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> is_visible<span class=\"token punctuation\">(<\/span>link<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u53ef\u89c1\u94fe\u63a5: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>link<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;href&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n    <span class=\"token keyword\">else<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u871c\u7f50\u94fe\u63a5&#xff0c;\u8df3\u8fc7: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>link<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;href&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>\u751f\u4ea7\u8e29\u5751\u63d0\u9192&#xff1a;\u5f88\u591a\u7f51\u7ad9\u4f7f\u7528\u871c\u7f50\u94fe\u63a5\u68c0\u6d4b\u722c\u866b\u3002\u5982\u679c\u4f60\u7684\u722c\u866b\u65e0\u5dee\u522b\u5730\u8ddf\u968f\u6240\u6709\u94fe\u63a5&#xff0c;\u5f88\u53ef\u80fd\u89e6\u53d1\u871c\u7f50\u800c\u88ab\u5c01\u7981\u3002\u5efa\u8bae\u5728\u63d0\u53d6\u94fe\u63a5\u65f6&#xff0c;\u68c0\u67e5\u5143\u7d20\u7684\u53ef\u89c1\u6027\u3002<\/p>\n<h3>8. \u53cd\u53cd\u722c\u866b\u5b9e\u6218<\/h3>\n<h4>8.1 \u4ee3\u7406\u6c60\u642d\u5efa&#xff08;Redis &#043; FastAPI&#xff09;<\/h4>\n<p><span class=\"token comment\"># proxy_pool.py &#8211; \u8f7b\u91cf\u7ea7\u4ee3\u7406\u6c60\u670d\u52a1<\/span><br \/>\n<span class=\"token keyword\">import<\/span> redis<br \/>\n<span class=\"token keyword\">import<\/span> time<br \/>\n<span class=\"token keyword\">import<\/span> random<br \/>\n<span class=\"token keyword\">import<\/span> asyncio<br \/>\n<span class=\"token keyword\">from<\/span> fastapi <span class=\"token keyword\">import<\/span> FastAPI<br \/>\n<span class=\"token keyword\">from<\/span> typing <span class=\"token keyword\">import<\/span> Optional<br \/>\n<span class=\"token keyword\">from<\/span> datetime <span class=\"token keyword\">import<\/span> datetime<\/p>\n<p>app <span class=\"token operator\">&#061;<\/span> FastAPI<span class=\"token punctuation\">(<\/span>title<span class=\"token operator\">&#061;<\/span><span class=\"token string\">&#034;Proxy Pool Service&#034;<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token comment\"># Redis\u8fde\u63a5<\/span><br \/>\nredis_client <span class=\"token operator\">&#061;<\/span> redis<span class=\"token punctuation\">.<\/span>Redis<span class=\"token punctuation\">(<\/span>host<span class=\"token operator\">&#061;<\/span><span class=\"token string\">&#034;localhost&#034;<\/span><span class=\"token punctuation\">,<\/span> port<span class=\"token operator\">&#061;<\/span><span class=\"token number\">6379<\/span><span class=\"token punctuation\">,<\/span> db<span class=\"token operator\">&#061;<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">,<\/span> decode_responses<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">True<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>PROXY_KEY <span class=\"token operator\">&#061;<\/span> <span class=\"token string\">&#034;proxy_pool&#034;<\/span>           <span class=\"token comment\"># \u4ee3\u7406\u6c60Hash<\/span><\/p>\n<p><span class=\"token keyword\">class<\/span> <span class=\"token class-name\">ProxyManager<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u4ee3\u7406\u6c60\u7ba1\u7406\u5668&#034;&#034;&#034;<\/span><\/p>\n<p>    MAX_SCORE <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">100<\/span>       <span class=\"token comment\"># \u6700\u9ad8\u5206<\/span><br \/>\n    MIN_SCORE <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0<\/span>         <span class=\"token comment\"># \u6700\u4f4e\u5206<\/span><br \/>\n    INIT_SCORE <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">10<\/span>       <span class=\"token comment\"># \u521d\u59cb\u5206<\/span><br \/>\n    CHECK_INTERVAL <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">300<\/span>  <span class=\"token comment\"># \u68c0\u6d4b\u95f4\u9694(\u79d2)<\/span><\/p>\n<p>    <span class=\"token decorator annotation punctuation\">&#064;classmethod<\/span><br \/>\n    <span class=\"token keyword\">async<\/span> <span class=\"token keyword\">def<\/span> <span class=\"token function\">is_valid_proxy<\/span><span class=\"token punctuation\">(<\/span>cls<span class=\"token punctuation\">,<\/span> proxy<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">bool<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u9a8c\u8bc1\u4ee3\u7406\u662f\u5426\u53ef\u7528&#034;&#034;&#034;<\/span><br \/>\n        <span class=\"token keyword\">import<\/span> httpx<br \/>\n        <span class=\"token keyword\">try<\/span><span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">async<\/span> <span class=\"token keyword\">with<\/span> httpx<span class=\"token punctuation\">.<\/span>AsyncClient<span class=\"token punctuation\">(<\/span><br \/>\n                proxies<span class=\"token operator\">&#061;<\/span><span class=\"token punctuation\">{<\/span><span class=\"token string\">&#034;all:\/\/&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string-interpolation\"><span class=\"token string\">f&#034;http:\/\/<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>proxy<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                timeout<span class=\"token operator\">&#061;<\/span><span class=\"token number\">10<\/span><br \/>\n            <span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">as<\/span> client<span class=\"token punctuation\">:<\/span><br \/>\n                resp <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">await<\/span> client<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;https:\/\/httpbin.org\/get&#034;<\/span><span class=\"token punctuation\">)<\/span><br \/>\n                <span class=\"token keyword\">return<\/span> resp<span class=\"token punctuation\">.<\/span>status_code <span class=\"token operator\">&#061;&#061;<\/span> <span class=\"token number\">200<\/span><br \/>\n        <span class=\"token keyword\">except<\/span> Exception<span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">False<\/span><\/p>\n<p>    <span class=\"token decorator annotation punctuation\">&#064;classmethod<\/span><br \/>\n    <span class=\"token keyword\">async<\/span> <span class=\"token keyword\">def<\/span> <span class=\"token function\">add_proxy<\/span><span class=\"token punctuation\">(<\/span>cls<span class=\"token punctuation\">,<\/span> proxy<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u6dfb\u52a0\u4ee3\u7406\u5230\u6c60\u4e2d&#034;&#034;&#034;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token keyword\">not<\/span> redis_client<span class=\"token punctuation\">.<\/span>hexists<span class=\"token punctuation\">(<\/span>PROXY_KEY<span class=\"token punctuation\">,<\/span> proxy<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n            redis_client<span class=\"token punctuation\">.<\/span>hset<span class=\"token punctuation\">(<\/span>PROXY_KEY<span class=\"token punctuation\">,<\/span> proxy<span class=\"token punctuation\">,<\/span> cls<span class=\"token punctuation\">.<\/span>INIT_SCORE<span class=\"token punctuation\">)<\/span><\/p>\n<p>    <span class=\"token decorator annotation punctuation\">&#064;classmethod<\/span><br \/>\n    <span class=\"token keyword\">async<\/span> <span class=\"token keyword\">def<\/span> <span class=\"token function\">get_random_proxy<\/span><span class=\"token punctuation\">(<\/span>cls<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> Optional<span class=\"token punctuation\">[<\/span><span class=\"token builtin\">str<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u968f\u673a\u83b7\u53d6\u4e00\u4e2a\u9ad8\u5206\u4ee3\u7406&#034;&#034;&#034;<\/span><br \/>\n        proxies <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span><span class=\"token punctuation\">}<\/span><br \/>\n        all_proxies <span class=\"token operator\">&#061;<\/span> redis_client<span class=\"token punctuation\">.<\/span>hgetall<span class=\"token punctuation\">(<\/span>PROXY_KEY<span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">for<\/span> proxy<span class=\"token punctuation\">,<\/span> score <span class=\"token keyword\">in<\/span> all_proxies<span class=\"token punctuation\">.<\/span>items<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token builtin\">int<\/span><span class=\"token punctuation\">(<\/span>score<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&gt;&#061;<\/span> <span class=\"token number\">50<\/span><span class=\"token punctuation\">:<\/span><br \/>\n                proxies<span class=\"token punctuation\">[<\/span>proxy<span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token builtin\">int<\/span><span class=\"token punctuation\">(<\/span>score<span class=\"token punctuation\">)<\/span><\/p>\n<p>        <span class=\"token keyword\">if<\/span> <span class=\"token keyword\">not<\/span> proxies<span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">None<\/span><\/p>\n<p>        <span class=\"token comment\"># \u52a0\u6743\u968f\u673a\u9009\u62e9<\/span><br \/>\n        total <span class=\"token operator\">&#061;<\/span> <span class=\"token builtin\">sum<\/span><span class=\"token punctuation\">(<\/span>proxies<span class=\"token punctuation\">.<\/span>values<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        r <span class=\"token operator\">&#061;<\/span> random<span class=\"token punctuation\">.<\/span>uniform<span class=\"token punctuation\">(<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">,<\/span> total<span class=\"token punctuation\">)<\/span><br \/>\n        cumulative <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0<\/span><br \/>\n        <span class=\"token keyword\">for<\/span> proxy<span class=\"token punctuation\">,<\/span> score <span class=\"token keyword\">in<\/span> proxies<span class=\"token punctuation\">.<\/span>items<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n            cumulative <span class=\"token operator\">&#043;&#061;<\/span> score<br \/>\n            <span class=\"token keyword\">if<\/span> r <span class=\"token operator\">&lt;&#061;<\/span> cumulative<span class=\"token punctuation\">:<\/span><br \/>\n                <span class=\"token keyword\">return<\/span> proxy<br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token builtin\">list<\/span><span class=\"token punctuation\">(<\/span>proxies<span class=\"token punctuation\">.<\/span>keys<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">[<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">]<\/span><\/p>\n<p>    <span class=\"token decorator annotation punctuation\">&#064;classmethod<\/span><br \/>\n    <span class=\"token keyword\">async<\/span> <span class=\"token keyword\">def<\/span> <span class=\"token function\">increase_score<\/span><span class=\"token punctuation\">(<\/span>cls<span class=\"token punctuation\">,<\/span> proxy<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u4ee3\u7406\u53ef\u7528\u65f6\u52a0\u5206&#034;&#034;&#034;<\/span><br \/>\n        current <span class=\"token operator\">&#061;<\/span> <span class=\"token builtin\">int<\/span><span class=\"token punctuation\">(<\/span>redis_client<span class=\"token punctuation\">.<\/span>hget<span class=\"token punctuation\">(<\/span>PROXY_KEY<span class=\"token punctuation\">,<\/span> proxy<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">or<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> current <span class=\"token operator\">&lt;<\/span> cls<span class=\"token punctuation\">.<\/span>MAX_SCORE<span class=\"token punctuation\">:<\/span><br \/>\n            redis_client<span class=\"token punctuation\">.<\/span>hset<span class=\"token punctuation\">(<\/span>PROXY_KEY<span class=\"token punctuation\">,<\/span> proxy<span class=\"token punctuation\">,<\/span> current <span class=\"token operator\">&#043;<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>    <span class=\"token decorator annotation punctuation\">&#064;classmethod<\/span><br \/>\n    <span class=\"token keyword\">async<\/span> <span class=\"token keyword\">def<\/span> <span class=\"token function\">decrease_score<\/span><span class=\"token punctuation\">(<\/span>cls<span class=\"token punctuation\">,<\/span> proxy<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u4ee3\u7406\u4e0d\u53ef\u7528\u65f6\u51cf\u5206&#034;&#034;&#034;<\/span><br \/>\n        current <span class=\"token operator\">&#061;<\/span> <span class=\"token builtin\">int<\/span><span class=\"token punctuation\">(<\/span>redis_client<span class=\"token punctuation\">.<\/span>hget<span class=\"token punctuation\">(<\/span>PROXY_KEY<span class=\"token punctuation\">,<\/span> proxy<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">or<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> current <span class=\"token operator\">&gt;<\/span> cls<span class=\"token punctuation\">.<\/span>MIN_SCORE<span class=\"token punctuation\">:<\/span><br \/>\n            redis_client<span class=\"token punctuation\">.<\/span>hset<span class=\"token punctuation\">(<\/span>PROXY_KEY<span class=\"token punctuation\">,<\/span> proxy<span class=\"token punctuation\">,<\/span> current <span class=\"token operator\">&#8211;<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">else<\/span><span class=\"token punctuation\">:<\/span><br \/>\n            redis_client<span class=\"token punctuation\">.<\/span>hdel<span class=\"token punctuation\">(<\/span>PROXY_KEY<span class=\"token punctuation\">,<\/span> proxy<span class=\"token punctuation\">)<\/span><\/p>\n<p>proxy_mgr <span class=\"token operator\">&#061;<\/span> ProxyManager<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token decorator annotation punctuation\">&#064;app<span class=\"token punctuation\">.<\/span>get<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;\/proxy\/random&#034;<\/span><span class=\"token punctuation\">)<\/span><br \/>\n<span class=\"token keyword\">async<\/span> <span class=\"token keyword\">def<\/span> <span class=\"token function\">get_proxy<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u83b7\u53d6\u968f\u673a\u4ee3\u7406&#034;&#034;&#034;<\/span><br \/>\n    proxy <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">await<\/span> proxy_mgr<span class=\"token punctuation\">.<\/span>get_random_proxy<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    <span class=\"token keyword\">if<\/span> proxy<span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token punctuation\">{<\/span><span class=\"token string\">&#034;proxy&#034;<\/span><span class=\"token punctuation\">:<\/span> proxy<span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;url&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string-interpolation\"><span class=\"token string\">f&#034;http:\/\/<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>proxy<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token punctuation\">{<\/span><span class=\"token string\">&#034;error&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;no available proxy&#034;<\/span><span class=\"token punctuation\">}<\/span><\/p>\n<p><span class=\"token decorator annotation punctuation\">&#064;app<span class=\"token punctuation\">.<\/span>post<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;\/proxy\/add&#034;<\/span><span class=\"token punctuation\">)<\/span><br \/>\n<span class=\"token keyword\">async<\/span> <span class=\"token keyword\">def<\/span> <span class=\"token function\">add_proxy<\/span><span class=\"token punctuation\">(<\/span>proxy<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u6dfb\u52a0\u4ee3\u7406&#034;&#034;&#034;<\/span><br \/>\n    <span class=\"token keyword\">await<\/span> proxy_mgr<span class=\"token punctuation\">.<\/span>add_proxy<span class=\"token punctuation\">(<\/span>proxy<span class=\"token punctuation\">)<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> <span class=\"token punctuation\">{<\/span><span class=\"token string\">&#034;status&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;added&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;proxy&#034;<\/span><span class=\"token punctuation\">:<\/span> proxy<span class=\"token punctuation\">}<\/span><\/p>\n<h4>8.2 \u9a8c\u8bc1\u7801\u8bc6\u522b&#xff08;ddddocr&#xff09;<\/h4>\n<p><span class=\"token keyword\">import<\/span> ddddocr<br \/>\n<span class=\"token keyword\">import<\/span> requests<\/p>\n<p><span class=\"token comment\"># \u521d\u59cb\u5316OCR\u8bc6\u522b\u5668<\/span><br \/>\nocr <span class=\"token operator\">&#061;<\/span> ddddocr<span class=\"token punctuation\">.<\/span>DdddOcr<span class=\"token punctuation\">(<\/span>show_ad<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">False<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token keyword\">def<\/span> <span class=\"token function\">recognize_captcha<\/span><span class=\"token punctuation\">(<\/span>image_url<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u8bc6\u522b\u56fe\u7247\u9a8c\u8bc1\u7801&#034;&#034;&#034;<\/span><br \/>\n    response <span class=\"token operator\">&#061;<\/span> requests<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span>image_url<span class=\"token punctuation\">,<\/span> timeout<span class=\"token operator\">&#061;<\/span><span class=\"token number\">10<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    image_bytes <span class=\"token operator\">&#061;<\/span> response<span class=\"token punctuation\">.<\/span>content<br \/>\n    result <span class=\"token operator\">&#061;<\/span> ocr<span class=\"token punctuation\">.<\/span>classification<span class=\"token punctuation\">(<\/span>image_bytes<span class=\"token punctuation\">)<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> result<\/p>\n<p><span class=\"token comment\"># \u4f7f\u7528\u793a\u4f8b<\/span><br \/>\ncaptcha_text <span class=\"token operator\">&#061;<\/span> recognize_captcha<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;https:\/\/example.com\/captcha.jpg&#034;<\/span><span class=\"token punctuation\">)<\/span><br \/>\n<span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u9a8c\u8bc1\u7801\u8bc6\u522b\u7ed3\u679c: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>captcha_text<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token comment\"># \u6ed1\u5757\u9a8c\u8bc1\u7801 &#8211; \u7f3a\u53e3\u68c0\u6d4b<\/span><br \/>\ndet <span class=\"token operator\">&#061;<\/span> ddddocr<span class=\"token punctuation\">.<\/span>DdddOcr<span class=\"token punctuation\">(<\/span>det<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">False<\/span><span class=\"token punctuation\">,<\/span> ocr<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">False<\/span><span class=\"token punctuation\">,<\/span> show_ad<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">False<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token keyword\">def<\/span> <span class=\"token function\">find_slider_gap<\/span><span class=\"token punctuation\">(<\/span>bg_bytes<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">bytes<\/span><span class=\"token punctuation\">,<\/span> slider_bytes<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">bytes<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">int<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u627e\u5230\u6ed1\u5757\u7f3a\u53e3\u7684x\u5750\u6807&#034;&#034;&#034;<\/span><br \/>\n    result <span class=\"token operator\">&#061;<\/span> det<span class=\"token punctuation\">.<\/span>slide_match<span class=\"token punctuation\">(<\/span>slider_bytes<span class=\"token punctuation\">,<\/span> bg_bytes<span class=\"token punctuation\">,<\/span> simple_target<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">True<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> result<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;target&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">[<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">]<\/span><\/p>\n<h4>8.3 curl_cffi \u5b9e\u6218\u7ed5\u8fc7 TLS \u68c0\u6d4b<\/h4>\n<p><span class=\"token keyword\">from<\/span> curl_cffi <span class=\"token keyword\">import<\/span> requests <span class=\"token keyword\">as<\/span> cffi_requests<\/p>\n<p><span class=\"token keyword\">def<\/span> <span class=\"token function\">bypass_cloudflare<\/span><span class=\"token punctuation\">(<\/span>url<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u4f7f\u7528curl_cffi\u7ed5\u8fc7Cloudflare\u7684TLS\u6307\u7eb9\u68c0\u6d4b&#034;&#034;&#034;<\/span><br \/>\n    session <span class=\"token operator\">&#061;<\/span> cffi_requests<span class=\"token punctuation\">.<\/span>Session<span class=\"token punctuation\">(<\/span><br \/>\n        impersonate<span class=\"token operator\">&#061;<\/span><span class=\"token string\">&#034;chrome136&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        verify<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">True<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    <span class=\"token punctuation\">)<\/span><\/p>\n<p>    response <span class=\"token operator\">&#061;<\/span> session<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span>url<span class=\"token punctuation\">,<\/span> timeout<span class=\"token operator\">&#061;<\/span><span class=\"token number\">30<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>    <span class=\"token keyword\">if<\/span> <span class=\"token string\">&#034;cf-chl-bypass&#034;<\/span> <span class=\"token keyword\">in<\/span> response<span class=\"token punctuation\">.<\/span>text<span class=\"token punctuation\">.<\/span>lower<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;Cloudflare\u6311\u6218\u9875\u9762&#xff0c;\u53ef\u80fd\u9700\u8981\u989d\u5916\u5904\u7406&#034;<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    <span class=\"token keyword\">elif<\/span> response<span class=\"token punctuation\">.<\/span>status_code <span class=\"token operator\">&#061;&#061;<\/span> <span class=\"token number\">200<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u6210\u529f\u7ed5\u8fc7&#xff0c;\u72b6\u6001\u7801: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>response<span class=\"token punctuation\">.<\/span>status_code<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u9875\u9762\u957f\u5ea6: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span><span class=\"token builtin\">len<\/span><span class=\"token punctuation\">(<\/span>response<span class=\"token punctuation\">.<\/span>text<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\"> \u5b57\u7b26&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n    <span class=\"token keyword\">else<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u8bf7\u6c42\u5931\u8d25: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>response<span class=\"token punctuation\">.<\/span>status_code<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>    <span class=\"token keyword\">return<\/span> response<\/p>\n<p><span class=\"token comment\"># \u5bf9\u6bd4&#xff1a;requests vs curl_cffi<\/span><br \/>\n<span class=\"token comment\"># requests.get(url)  -&gt; 403 Forbidden (JA3\u88ab\u6807\u8bb0\u4e3aPython)<\/span><br \/>\n<span class=\"token comment\"># curl_cffi.get(url, impersonate&#061;&#034;chrome136&#034;) -&gt; 200 OK (JA3\u5339\u914dChrome)<\/span><\/p>\n<h4>8.4 \u8bf7\u6c42\u4f2a\u88c5\u6700\u4f73\u5b9e\u8df5<\/h4>\n<p><span class=\"token keyword\">import<\/span> random<br \/>\n<span class=\"token keyword\">import<\/span> time<\/p>\n<p><span class=\"token comment\"># \u771f\u5b9e\u6d4f\u89c8\u5668Header\u6a21\u677f&#xff08;2025-2026\u7248\u672c&#xff09;<\/span><br \/>\nCHROME_HEADERS_TEMPLATES <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span><br \/>\n    <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token string\">&#034;User-Agent&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 &#034;<\/span><br \/>\n                      <span class=\"token string\">&#034;(KHTML, like Gecko) Chrome\/131.0.0.0 Safari\/537.36&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token string\">&#034;Accept&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;text\/html,application\/xhtml&#043;xml,application\/xml;q&#061;0.9,image\/avif,&#034;<\/span><br \/>\n                  <span class=\"token string\">&#034;image\/webp,image\/apng,*\/*;q&#061;0.8&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token string\">&#034;Accept-Language&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;zh-CN,zh;q&#061;0.9,en;q&#061;0.8&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token string\">&#034;Accept-Encoding&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;gzip, deflate, br, zstd&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token string\">&#034;Sec-Ch-Ua&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#039;&#034;Chromium&#034;;v&#061;&#034;131&#034;, &#034;Not_A Brand&#034;;v&#061;&#034;24&#034;&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token string\">&#034;Sec-Ch-Ua-Mobile&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;?0&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token string\">&#034;Sec-Ch-Ua-Platform&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#039;&#034;Windows&#034;&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token string\">&#034;Sec-Fetch-Dest&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;document&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token string\">&#034;Sec-Fetch-Mode&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;navigate&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token string\">&#034;Sec-Fetch-Site&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;none&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token string\">&#034;Sec-Fetch-User&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;?1&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token string\">&#034;Upgrade-Insecure-Requests&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;1&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br \/>\n<span class=\"token punctuation\">]<\/span><\/p>\n<p><span class=\"token keyword\">def<\/span> <span class=\"token function\">random_delay<\/span><span class=\"token punctuation\">(<\/span>min_sec<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">float<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">1.0<\/span><span class=\"token punctuation\">,<\/span> max_sec<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">float<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">5.0<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u968f\u673a\u5ef6\u8fdf&#xff0c;\u6a21\u62df\u4eba\u7c7b\u884c\u4e3a&#034;&#034;&#034;<\/span><br \/>\n    delay <span class=\"token operator\">&#061;<\/span> random<span class=\"token punctuation\">.<\/span>uniform<span class=\"token punctuation\">(<\/span>min_sec<span class=\"token punctuation\">,<\/span> max_sec<span class=\"token punctuation\">)<\/span><br \/>\n    time<span class=\"token punctuation\">.<\/span>sleep<span class=\"token punctuation\">(<\/span>delay<span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token keyword\">def<\/span> <span class=\"token function\">get_stealth_headers<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">dict<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u83b7\u53d6\u4f2a\u88c5Headers&#034;&#034;&#034;<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> random<span class=\"token punctuation\">.<\/span>choice<span class=\"token punctuation\">(<\/span>CHROME_HEADERS_TEMPLATES<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>copy<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<h3>9. \u9006\u5411\u5de5\u7a0b\u57fa\u7840<\/h3>\n<h4>9.1 Chrome DevTools \u6838\u5fc3\u9762\u677f<\/h4>\n<table>\n<tr>\u9762\u677f\u7528\u9014\u722c\u866b\u76f8\u5173\u529f\u80fd<\/tr>\n<tbody>\n<tr>\n<td>Network<\/td>\n<td>\u7f51\u7edc\u8bf7\u6c42\u5206\u6790<\/td>\n<td>XHR\/Fetch\u8fc7\u6ee4\u3001\u8bf7\u6c42\u91cd\u653e\u3001\u53c2\u6570\u67e5\u770b<\/td>\n<\/tr>\n<tr>\n<td>Sources<\/td>\n<td>\u6e90\u7801\u8c03\u8bd5<\/td>\n<td>\u65ad\u70b9\u3001\u5355\u6b65\u8c03\u8bd5\u3001Call Stack\u8ffd\u8e2a<\/td>\n<\/tr>\n<tr>\n<td>Elements<\/td>\n<td>DOM\u68c0\u67e5<\/td>\n<td>\u5143\u7d20\u5ba1\u67e5\u3001\u4e8b\u4ef6\u76d1\u542c\u5668\u67e5\u770b<\/td>\n<\/tr>\n<tr>\n<td>Console<\/td>\n<td>\u63a7\u5236\u53f0<\/td>\n<td>Hook\u6ce8\u5165\u3001\u4ee3\u7801\u6267\u884c\u3001\u8c03\u8bd5\u8f93\u51fa<\/td>\n<\/tr>\n<tr>\n<td>Application<\/td>\n<td>\u5b58\u50a8\u67e5\u770b<\/td>\n<td>Cookie\/LocalStorage\/SessionStorage<\/td>\n<\/tr>\n<tr>\n<td>Performance<\/td>\n<td>\u6027\u80fd\u5206\u6790<\/td>\n<td>\u8bc6\u522b\u5173\u952e\u6e32\u67d3\u8def\u5f84<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>9.2 \u9006\u5411\u6838\u5fc3\u6d41\u7a0b<\/h4>\n<p>\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510<br \/>\n\u2502                  JS\u9006\u5411\u5de5\u7a0b\u6807\u51c6\u6d41\u7a0b                              \u2502<br \/>\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524<br \/>\n\u2502                                                               \u2502<br \/>\n\u2502  Step 1: \u6293\u5305\u5206\u6790          Step 2: \u5b9a\u4f4d\u5165\u53e3                    \u2502<br \/>\n\u2502  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#043;     &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#043;                 \u2502<br \/>\n\u2502  | Network          |     | XHR\u65ad\u70b9          |                 \u2502<br \/>\n\u2502  | \u9762\u677f\u8fc7\u6ee4XHR     |&#8211;&gt;  | \u5168\u5c40\u641c\u7d22sign     |                 \u2502<br \/>\n\u2502  | \u5206\u6790\u8bf7\u6c42\u53c2\u6570     |     | \u641c\u7d22\u52a0\u5bc6\u51fd\u6570     |                 \u2502<br \/>\n\u2502  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#043;     &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#043;                 \u2502<br \/>\n\u2502                                |                               \u2502<br \/>\n\u2502  Step 3: \u65ad\u70b9\u8c03\u8bd5              v                               \u2502<br \/>\n\u2502  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#043;                                          \u2502<br \/>\n\u2502  | CallStack\u8ffd\u8e2a    |                                          \u2502<br \/>\n\u2502  | \u9010\u6b65\u8ddf\u8e2a         |                                          \u2502<br \/>\n\u2502  | \u627e\u5230\u52a0\u5bc6\u903b\u8f91     |                                          \u2502<br \/>\n\u2502  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#043;                                          \u2502<br \/>\n\u2502         |                                                     \u2502<br \/>\n\u2502  Step 4: \u7b97\u6cd5\u8bc6\u522b    Step 5: \u903b\u8f91\u8fd8\u539f    Step 6: Python\u590d\u73b0    \u2502<br \/>\n\u2502  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#043;  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#043;  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;-&#043;\u2502<br \/>\n\u2502  | MD5\/SHA\/AES     |  | AST\u8fd8\u539f\u63a7\u5236\u6d41    |  | requests\u672c\u5730   \u2502\u2502<br \/>\n\u2502  | RSA\/Base64       |-&gt;| \u5b57\u7b26\u4e32\u8868\u8fd8\u539f     |-&gt;| \u9a8c\u8bc1\u7b7e\u540d       \u2502\u2502<br \/>\n\u2502  | HMAC\/\u81ea\u5b9a\u4e49      |  | \u6b7b\u4ee3\u7801\u6d88\u9664       |  | \u5bf9\u6bd4\u7ed3\u679c       \u2502\u2502<br \/>\n\u2502  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#043;  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#043;  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;-&#043;\u2502<br \/>\n\u2502                                                               \u2502<br \/>\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/p>\n<h4>9.3 \u5e38\u89c1\u52a0\u5bc6\u7b97\u6cd5\u8bc6\u522b<\/h4>\n<table>\n<tr>\u4ee3\u7801\u7279\u5f81\u7b97\u6cd5\u8f93\u51fa\u7279\u5f81\u5e94\u5bf9\u65b9\u6848<\/tr>\n<tbody>\n<tr>\n<td>CryptoJS.MD5()<\/td>\n<td>MD5<\/td>\n<td>32\u4f4dhex<\/td>\n<td>hashlib.md5<\/td>\n<\/tr>\n<tr>\n<td>CryptoJS.SHA256()<\/td>\n<td>SHA-256<\/td>\n<td>64\u4f4dhex<\/td>\n<td>hashlib.sha256<\/td>\n<\/tr>\n<tr>\n<td>CryptoJS.AES.encrypt()<\/td>\n<td>AES<\/td>\n<td>Base64\u6216hex<\/td>\n<td>pycryptodome<\/td>\n<\/tr>\n<tr>\n<td>JSEncrypt \/ encrypt<\/td>\n<td>RSA<\/td>\n<td>Base64<\/td>\n<td>rsa\u5e93<\/td>\n<\/tr>\n<tr>\n<td>btoa() \/ atob()<\/td>\n<td>Base64<\/td>\n<td>\u7ed3\u5c3e&#061;<\/td>\n<td>base64\u6a21\u5757<\/td>\n<\/tr>\n<tr>\n<td>encodeURIComponent<\/td>\n<td>URL\u7f16\u7801<\/td>\n<td>%XX\u683c\u5f0f<\/td>\n<td>urllib.parse<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>9.4 Hook \u6280\u672f\u5b9e\u6218<\/h4>\n<p><span class=\"token comment\">\/\/ \u5728Chrome Console\u4e2d\u6ce8\u5165\u7684Hook\u811a\u672c<\/span><\/p>\n<p><span class=\"token comment\">\/\/ 1. Hook XMLHttpRequest &#8211; \u62e6\u622a\u6240\u6709XHR\u8bf7\u6c42<\/span><br \/>\n<span class=\"token punctuation\">(<\/span><span class=\"token keyword\">function<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">const<\/span> originalOpen <span class=\"token operator\">&#061;<\/span> <span class=\"token class-name\">XMLHttpRequest<\/span><span class=\"token punctuation\">.<\/span>prototype<span class=\"token punctuation\">.<\/span>open<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token keyword\">const<\/span> originalSend <span class=\"token operator\">&#061;<\/span> <span class=\"token class-name\">XMLHttpRequest<\/span><span class=\"token punctuation\">.<\/span>prototype<span class=\"token punctuation\">.<\/span>send<span class=\"token punctuation\">;<\/span><\/p>\n<p>    <span class=\"token class-name\">XMLHttpRequest<\/span><span class=\"token punctuation\">.<\/span>prototype<span class=\"token punctuation\">.<\/span><span class=\"token function-variable function\">open<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">function<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">method<span class=\"token punctuation\">,<\/span> url<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>_url <span class=\"token operator\">&#061;<\/span> url<span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>_method <span class=\"token operator\">&#061;<\/span> method<span class=\"token punctuation\">;<\/span><br \/>\n        console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;[XHR] &#039;<\/span> <span class=\"token operator\">&#043;<\/span> method <span class=\"token operator\">&#043;<\/span> <span class=\"token string\">&#039; &#039;<\/span> <span class=\"token operator\">&#043;<\/span> url<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token function\">originalOpen<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">apply<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">this<\/span><span class=\"token punctuation\">,<\/span> arguments<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>    <span class=\"token class-name\">XMLHttpRequest<\/span><span class=\"token punctuation\">.<\/span>prototype<span class=\"token punctuation\">.<\/span><span class=\"token function-variable function\">send<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">function<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">body<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>_url <span class=\"token operator\">&amp;&amp;<\/span> <span class=\"token keyword\">this<\/span><span class=\"token punctuation\">.<\/span>_url<span class=\"token punctuation\">.<\/span><span class=\"token function\">includes<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;\/api\/&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;[XHR Body]&#039;<\/span><span class=\"token punctuation\">,<\/span> body<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            console<span class=\"token punctuation\">.<\/span><span class=\"token function\">trace<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token comment\">\/\/ \u6253\u5370\u8c03\u7528\u6808<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token function\">originalSend<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">apply<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">this<\/span><span class=\"token punctuation\">,<\/span> arguments<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p><span class=\"token comment\">\/\/ 2. Hook fetch &#8211; \u62e6\u622aFetch\u8bf7\u6c42<\/span><br \/>\n<span class=\"token punctuation\">(<\/span><span class=\"token keyword\">function<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">const<\/span> originalFetch <span class=\"token operator\">&#061;<\/span> window<span class=\"token punctuation\">.<\/span>fetch<span class=\"token punctuation\">;<\/span><br \/>\n    window<span class=\"token punctuation\">.<\/span><span class=\"token function-variable function\">fetch<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">function<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\"><span class=\"token operator\">&#8230;<\/span>args<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;[Fetch]&#039;<\/span><span class=\"token punctuation\">,<\/span> args<span class=\"token punctuation\">[<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">,<\/span> args<span class=\"token punctuation\">[<\/span><span class=\"token number\">1<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        console<span class=\"token punctuation\">.<\/span><span class=\"token function\">trace<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token function\">originalFetch<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">apply<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">this<\/span><span class=\"token punctuation\">,<\/span> args<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p><span class=\"token comment\">\/\/ 3. Hook setRequestHeader &#8211; \u6355\u83b7\u52a0\u5bc6Header<\/span><br \/>\n<span class=\"token punctuation\">(<\/span><span class=\"token keyword\">function<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token keyword\">const<\/span> originalSetHeader <span class=\"token operator\">&#061;<\/span> <span class=\"token class-name\">XMLHttpRequest<\/span><span class=\"token punctuation\">.<\/span>prototype<span class=\"token punctuation\">.<\/span>setRequestHeader<span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token class-name\">XMLHttpRequest<\/span><span class=\"token punctuation\">.<\/span>prototype<span class=\"token punctuation\">.<\/span><span class=\"token function-variable function\">setRequestHeader<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">function<\/span><span class=\"token punctuation\">(<\/span><span class=\"token parameter\">name<span class=\"token punctuation\">,<\/span> value<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token regex\"><span class=\"token regex-delimiter\">\/<\/span><span class=\"token regex-source language-regex\">sign|token|auth|x-<\/span><span class=\"token regex-delimiter\">\/<\/span><span class=\"token regex-flags\">i<\/span><\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">test<\/span><span class=\"token punctuation\">(<\/span>name<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;[Header] &#039;<\/span> <span class=\"token operator\">&#043;<\/span> name <span class=\"token operator\">&#043;<\/span> <span class=\"token string\">&#039;: &#039;<\/span> <span class=\"token operator\">&#043;<\/span> value<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            console<span class=\"token punctuation\">.<\/span><span class=\"token function\">trace<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token function\">originalSetHeader<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">apply<\/span><span class=\"token punctuation\">(<\/span><span class=\"token keyword\">this<\/span><span class=\"token punctuation\">,<\/span> arguments<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p><span class=\"token comment\">\/\/ 4. Object.defineProperty Hook &#8211; \u8ffd\u8e2a\u5c5e\u6027\u8bfb\u53d6<\/span><br \/>\n<span class=\"token punctuation\">(<\/span><span class=\"token keyword\">function<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n    <span class=\"token comment\">\/\/ \u76d1\u63a7 navigator.webdriver \u4f55\u65f6\u88ab\u8bfb\u53d6&#xff08;\u5e38\u89c1\u53cd\u722c\u68c0\u6d4b\u70b9&#xff09;<\/span><br \/>\n    Object<span class=\"token punctuation\">.<\/span><span class=\"token function\">defineProperty<\/span><span class=\"token punctuation\">(<\/span>navigator<span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#039;webdriver&#039;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token function-variable function\">get<\/span><span class=\"token operator\">:<\/span> <span class=\"token keyword\">function<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            console<span class=\"token punctuation\">.<\/span><span class=\"token function\">trace<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;[\u68c0\u6d4b\u70b9] navigator.webdriver \u88ab\u8bfb\u53d6&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n            <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">false<\/span><span class=\"token punctuation\">;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><br \/>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/p>\n<p>\u9762\u8bd5\u52a0\u5206\u63d0\u793a&#xff1a;XHR\u65ad\u70b9&#043;Call Stack\u8ffd\u8e2a\u662fJS\u9006\u5411\u6700\u57fa\u672c\u4e5f\u6700\u6709\u6548\u7684\u65b9\u6cd5\u3002\u5728 DevTools Sources XHR\/fetch Breakpoints \u4e2d\u6dfb\u52a0\u63a5\u53e3\u5173\u952e\u8bcd&#xff0c;\u89e6\u53d1\u8bf7\u6c42\u540e\u5373\u53ef\u81ea\u52a8\u65ad\u5728\u53c2\u6570\u62fc\u88c5\u4f4d\u7f6e&#xff0c;\u6cbf\u8c03\u7528\u6808\u5411\u4e0a\u8ffd\u6eaf\u5373\u53ef\u627e\u5230\u52a0\u5bc6\u903b\u8f91\u3002<\/p>\n<h3>10. JS\u9006\u5411\u6df1\u5ea6\u5b9e\u6218<\/h3>\n<h4>10.1 \u7b7e\u540d\u53c2\u6570&#xff08;sign&#xff09;\u7834\u89e3\u6d41\u7a0b<\/h4>\n<p>\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510<br \/>\n\u2502              \u7b7e\u540d\u53c2\u6570\u9006\u5411\u5b8c\u6574\u6d41\u7a0b                                \u2502<br \/>\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524<br \/>\n\u2502                                                               \u2502<br \/>\n\u2502  Step 1: \u6293\u5305\u53d1\u73b0                                             \u2502<br \/>\n\u2502  GET \/api\/products?timestamp&#061;1720000000&amp;sign&#061;a1b2c3d4e5      \u2502<br \/>\n\u2502                    ^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^          \u2502<br \/>\n\u2502                    \u65f6\u95f4\u6233\u53c2\u6570       \u7b7e\u540d\u53c2\u6570(32\u4f4dhex&#061;MD5?)     \u2502<br \/>\n\u2502                                                               \u2502<br \/>\n\u2502  Step 2: \u641c\u7d22\u5b9a\u4f4d                                             \u2502<br \/>\n\u2502  DevTools -&gt; Ctrl&#043;Shift&#043;F -&gt; \u641c\u7d22 &#034;sign&#061;&#034; \u6216 &#034;generateSign&#034;  \u2502<br \/>\n\u2502                                                               \u2502<br \/>\n\u2502  Step 3: \u65ad\u70b9\u5206\u6790                                             \u2502<br \/>\n\u2502  \u627e\u5230\u5173\u952e\u51fd\u6570:                                                 \u2502<br \/>\n\u2502  function generateSign(params, secret) {                      \u2502<br \/>\n\u2502      let sorted &#061; Object.keys(params).sort()                  \u2502<br \/>\n\u2502          .map(k &#061;&gt; k &#043; &#039;&#061;&#039; &#043; params[k]).join(&#039;&amp;&#039;);            \u2502<br \/>\n\u2502      return CryptoJS.MD5(secret &#043; sorted).toString();         \u2502<br \/>\n\u2502  }                                                            \u2502<br \/>\n\u2502                                                               \u2502<br \/>\n\u2502  Step 4: Python\u590d\u73b0                                           \u2502<br \/>\n\u2502  sign &#061; md5(secret &#043; sorted_params).hexdigest()               \u2502<br \/>\n\u2502                                                               \u2502<br \/>\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/p>\n<p><span class=\"token keyword\">import<\/span> hashlib<br \/>\n<span class=\"token keyword\">import<\/span> time<br \/>\n<span class=\"token keyword\">import<\/span> requests<\/p>\n<p><span class=\"token keyword\">def<\/span> <span class=\"token function\">generate_sign<\/span><span class=\"token punctuation\">(<\/span>params<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">dict<\/span><span class=\"token punctuation\">,<\/span> secret<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token string\">&#034;x$12*_d#&#064;&#034;<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;<br \/>\n    \u8fd8\u539f\u76ee\u6807\u7f51\u7ad9\u7684\u7b7e\u540d\u7b97\u6cd5<br \/>\n    :param params: \u8bf7\u6c42\u53c2\u6570\u5b57\u5178<br \/>\n    :param secret: \u901a\u8fc7JS\u9006\u5411\u83b7\u53d6\u7684\u5bc6\u94a5<br \/>\n    &#034;&#034;&#034;<\/span><br \/>\n    <span class=\"token comment\"># \u53c2\u6570\u6309key\u6392\u5e8f&#xff0c;\u62fc\u63a5\u4e3a\u5b57\u7b26\u4e32<\/span><br \/>\n    sorted_str <span class=\"token operator\">&#061;<\/span> <span class=\"token string\">&#034;&amp;&#034;<\/span><span class=\"token punctuation\">.<\/span>join<span class=\"token punctuation\">(<\/span><br \/>\n        <span class=\"token string-interpolation\"><span class=\"token string\">f&#034;<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>k<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#061;<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>params<span class=\"token punctuation\">[<\/span>k<span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span> <span class=\"token keyword\">for<\/span> k <span class=\"token keyword\">in<\/span> <span class=\"token builtin\">sorted<\/span><span class=\"token punctuation\">(<\/span>params<span class=\"token punctuation\">.<\/span>keys<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    <span class=\"token punctuation\">)<\/span><br \/>\n    <span class=\"token comment\"># \u62fc\u63a5\u5bc6\u94a5\u540e\u8ba1\u7b97MD5<\/span><br \/>\n    sign_str <span class=\"token operator\">&#061;<\/span> secret <span class=\"token operator\">&#043;<\/span> sorted_str <span class=\"token operator\">&#043;<\/span> secret<br \/>\n    <span class=\"token keyword\">return<\/span> hashlib<span class=\"token punctuation\">.<\/span>md5<span class=\"token punctuation\">(<\/span>sign_str<span class=\"token punctuation\">.<\/span>encode<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;utf-8&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>hexdigest<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>upper<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token keyword\">def<\/span> <span class=\"token function\">crawl_with_sign<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u5e26\u7b7e\u540d\u7684\u8bf7\u6c42&#034;&#034;&#034;<\/span><br \/>\n    params <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token string\">&#034;page&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token string\">&#034;size&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token number\">20<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token string\">&#034;category&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;electronics&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token string\">&#034;timestamp&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">int<\/span><span class=\"token punctuation\">(<\/span>time<span class=\"token punctuation\">.<\/span>time<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token comment\"># \u751f\u6210\u7b7e\u540d<\/span><br \/>\n    params<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;sign&#034;<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#061;<\/span> generate_sign<span class=\"token punctuation\">(<\/span>params<span class=\"token punctuation\">)<\/span><\/p>\n<p>    response <span class=\"token operator\">&#061;<\/span> requests<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><br \/>\n        <span class=\"token string\">&#034;https:\/\/api.example.com\/products&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        params<span class=\"token operator\">&#061;<\/span>params<span class=\"token punctuation\">,<\/span><br \/>\n        headers<span class=\"token operator\">&#061;<\/span><span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token string\">&#034;User-Agent&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;Mozilla\/5.0 (Windows NT 10.0; Win64; x64) &#034;<\/span><br \/>\n                          <span class=\"token string\">&#034;AppleWebKit\/537.36 Chrome\/131.0.0.0 Safari\/537.36&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token string\">&#034;Referer&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;https:\/\/www.example.com\/&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    <span class=\"token punctuation\">)<\/span><\/p>\n<p>    <span class=\"token keyword\">return<\/span> response<span class=\"token punctuation\">.<\/span>json<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<h4>10.2 Cookie \u52a0\u5bc6\u9006\u5411<\/h4>\n<p><span class=\"token keyword\">import<\/span> re<br \/>\n<span class=\"token keyword\">import<\/span> json<br \/>\n<span class=\"token keyword\">import<\/span> base64<br \/>\n<span class=\"token keyword\">from<\/span> Crypto<span class=\"token punctuation\">.<\/span>Cipher <span class=\"token keyword\">import<\/span> AES<br \/>\n<span class=\"token keyword\">from<\/span> Crypto<span class=\"token punctuation\">.<\/span>Util<span class=\"token punctuation\">.<\/span>Padding <span class=\"token keyword\">import<\/span> unpad<\/p>\n<p><span class=\"token keyword\">def<\/span> <span class=\"token function\">decrypt_cookie_token<\/span><span class=\"token punctuation\">(<\/span>token<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">,<\/span> key<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">dict<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;<br \/>\n    \u89e3\u5bc6Cookie\u4e2d\u7684\u52a0\u5bc6Token<br \/>\n    \u5e38\u89c1\u4e8e\u7535\u5546\u7f51\u7ad9\u7684\u52a0\u5bc6Cookie<br \/>\n    &#034;&#034;&#034;<\/span><br \/>\n    <span class=\"token keyword\">try<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token comment\"># Base64\u89e3\u7801<\/span><br \/>\n        encrypted <span class=\"token operator\">&#061;<\/span> base64<span class=\"token punctuation\">.<\/span>b64decode<span class=\"token punctuation\">(<\/span>token<span class=\"token punctuation\">)<\/span><\/p>\n<p>        <span class=\"token comment\"># AES-CBC\u89e3\u5bc6<\/span><br \/>\n        cipher <span class=\"token operator\">&#061;<\/span> AES<span class=\"token punctuation\">.<\/span>new<span class=\"token punctuation\">(<\/span><br \/>\n            key<span class=\"token punctuation\">.<\/span>encode<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;utf-8&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">:<\/span><span class=\"token number\">16<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">,<\/span>  <span class=\"token comment\"># 128\u4f4d\u5bc6\u94a5<\/span><br \/>\n            AES<span class=\"token punctuation\">.<\/span>MODE_CBC<span class=\"token punctuation\">,<\/span><br \/>\n            iv<span class=\"token operator\">&#061;<\/span>key<span class=\"token punctuation\">.<\/span>encode<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;utf-8&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">:<\/span><span class=\"token number\">16<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token punctuation\">)<\/span><br \/>\n        decrypted <span class=\"token operator\">&#061;<\/span> unpad<span class=\"token punctuation\">(<\/span>cipher<span class=\"token punctuation\">.<\/span>decrypt<span class=\"token punctuation\">(<\/span>encrypted<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> AES<span class=\"token punctuation\">.<\/span>block_size<span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> json<span class=\"token punctuation\">.<\/span>loads<span class=\"token punctuation\">(<\/span>decrypted<span class=\"token punctuation\">.<\/span>decode<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;utf-8&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    <span class=\"token keyword\">except<\/span> Exception <span class=\"token keyword\">as<\/span> e<span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u89e3\u5bc6\u5931\u8d25: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>e<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token punctuation\">{<\/span><span class=\"token punctuation\">}<\/span><\/p>\n<h4>10.3 \u5b57\u4f53\u53cd\u722c\u7834\u89e3<\/h4>\n<p><span class=\"token keyword\">import<\/span> io<br \/>\n<span class=\"token keyword\">import<\/span> fontTools<br \/>\n<span class=\"token keyword\">from<\/span> fontTools<span class=\"token punctuation\">.<\/span>ttLib <span class=\"token keyword\">import<\/span> TTFont<br \/>\n<span class=\"token keyword\">import<\/span> requests<\/p>\n<p><span class=\"token keyword\">def<\/span> <span class=\"token function\">parse_woff_font<\/span><span class=\"token punctuation\">(<\/span>font_bytes<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">bytes<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">dict<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;<br \/>\n    \u89e3\u6790woff\u5b57\u4f53\u6587\u4ef6&#xff0c;\u63d0\u53d6\u5b57\u7b26\u6620\u5c04\u5173\u7cfb<br \/>\n    \u7528\u4e8e\u7834\u89e3\u5b57\u4f53\u53cd\u722c&#xff08;\u5e38\u89c1\u4e8e\u7535\u5546\u4ef7\u683c\u3001\u7535\u8bdd\u53f7\u7801&#xff09;<br \/>\n    &#034;&#034;&#034;<\/span><br \/>\n    font <span class=\"token operator\">&#061;<\/span> TTFont<span class=\"token punctuation\">(<\/span>io<span class=\"token punctuation\">.<\/span>BytesIO<span class=\"token punctuation\">(<\/span>font_bytes<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>    <span class=\"token comment\"># \u83b7\u53d6\u5b57\u7b26\u6620\u5c04\u8868<\/span><br \/>\n    cmap <span class=\"token operator\">&#061;<\/span> font<span class=\"token punctuation\">.<\/span>getBestCmap<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>    <span class=\"token comment\"># \u6784\u5efa Unicode -&gt; \u5b57\u5f62\u540d \u7684\u6620\u5c04<\/span><br \/>\n    mapping <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span><span class=\"token punctuation\">}<\/span><br \/>\n    <span class=\"token keyword\">for<\/span> code<span class=\"token punctuation\">,<\/span> name <span class=\"token keyword\">in<\/span> cmap<span class=\"token punctuation\">.<\/span>items<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        mapping<span class=\"token punctuation\">[<\/span><span class=\"token builtin\">chr<\/span><span class=\"token punctuation\">(<\/span>code<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#061;<\/span> name<\/p>\n<p>    <span class=\"token keyword\">return<\/span> mapping<\/p>\n<p><span class=\"token comment\"># \u4f7f\u7528\u793a\u4f8b<\/span><br \/>\n<span class=\"token comment\"># resp &#061; requests.get(&#034;https:\/\/example.com\/font.woff&#034;)<\/span><br \/>\n<span class=\"token comment\"># mapping &#061; parse_woff_font(resp.content)<\/span><br \/>\n<span class=\"token comment\"># print(f&#034;\u5b57\u7b26\u6620\u5c04: {mapping}&#034;)<\/span><\/p>\n<p>\u751f\u4ea7\u8e29\u5751\u63d0\u9192&#xff1a;\u5b57\u4f53\u53cd\u722c\u7684\u6620\u5c04\u5173\u7cfb\u901a\u5e38\u662f\u52a8\u6001\u751f\u6210\u7684&#xff0c;\u6bcf\u6b21\u8bf7\u6c42\u90fd\u53ef\u80fd\u4e0d\u540c\u3002\u4f60\u9700\u8981\u5728\u6bcf\u6b21\u8bf7\u6c42\u65f6\u540c\u6b65\u4e0b\u8f7d\u5b57\u4f53\u6587\u4ef6\u5e76\u91cd\u65b0\u89e3\u6790\u6620\u5c04\u8868\u3002<\/p>\n<h4>10.4 JS\u6df7\u6dc6\u5bf9\u6297<\/h4>\n<table>\n<tr>\u6df7\u6dc6\u6280\u672f\u7279\u5f81\u7834\u89e3\u65b9\u6cd5<\/tr>\n<tbody>\n<tr>\n<td>\u53d8\u91cf\u540d\u6df7\u6dc6<\/td>\n<td>_0x3f2a12 \u7b49\u65e0\u610f\u4e49\u540d\u79f0<\/td>\n<td>AST\u53cd\u6df7\u6dc6&#043;\u8bed\u4e49\u5206\u6790<\/td>\n<\/tr>\n<tr>\n<td>\u63a7\u5236\u6d41\u5e73\u5766\u5316<\/td>\n<td>\u5de8\u5927\u7684switch-case<\/td>\n<td>AST\u5206\u6790&#043;\u72b6\u6001\u673a\u8fd8\u539f<\/td>\n<\/tr>\n<tr>\n<td>\u5b57\u7b26\u4e32\u52a0\u5bc6<\/td>\n<td>\u5b57\u7b26\u4e32\u6570\u7ec4&#043;\u7d22\u5f15\u8bbf\u95ee<\/td>\n<td>\u89e3\u5bc6\u51fd\u6570\u5b9a\u4f4d&#043;\u6279\u91cf\u8fd8\u539f<\/td>\n<\/tr>\n<tr>\n<td>\u6b7b\u4ee3\u7801\u6ce8\u5165<\/td>\n<td>\u672a\u4f7f\u7528\u7684\u51fd\u6570\/\u53d8\u91cf<\/td>\n<td>\u4ee3\u7801\u8986\u76d6\u7387\u5206\u6790<\/td>\n<\/tr>\n<tr>\n<td>JSVMP<\/td>\n<td>\u5b57\u8282\u7801&#043;\u89e3\u91ca\u5668\u5faa\u73af<\/td>\n<td>\u63d2\u6869\u8ffd\u8e2a&#043;Hook\u51fa\u53e3<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>11. APP\u722c\u866b\u4e0e\u6293\u5305<\/h3>\n<h4>11.1 \u6293\u5305\u5de5\u5177\u5bf9\u6bd4<\/h4>\n<table>\n<tr>\u5de5\u5177\u5e73\u53f0HTTPS\u89e3\u5bc6\u811a\u672c\u80fd\u529b\u514d\u8d39\u63a8\u8350\u573a\u666f<\/tr>\n<tbody>\n<tr>\n<td>Charles<\/td>\n<td>\u5168\u5e73\u53f0<\/td>\n<td>\u652f\u6301<\/td>\n<td>Rewrite\u89c4\u5219<\/td>\n<td>\u8bd5\u752830min<\/td>\n<td>Mac\u7528\u6237\u9996\u9009<\/td>\n<\/tr>\n<tr>\n<td>Fiddler<\/td>\n<td>Windows<\/td>\n<td>\u652f\u6301<\/td>\n<td>FiddlerScript<\/td>\n<td>\u514d\u8d39<\/td>\n<td>Windows\u7528\u6237<\/td>\n<\/tr>\n<tr>\n<td>Burp Suite<\/td>\n<td>\u5168\u5e73\u53f0<\/td>\n<td>\u652f\u6301<\/td>\n<td>Extension\u6269\u5c55<\/td>\n<td>Community\u7248<\/td>\n<td>\u5b89\u5168\u6d4b\u8bd5<\/td>\n<\/tr>\n<tr>\n<td>mitmproxy<\/td>\n<td>\u5168\u5e73\u53f0<\/td>\n<td>\u652f\u6301<\/td>\n<td>Python\u811a\u672c<\/td>\n<td>\u5f00\u6e90\u514d\u8d39<\/td>\n<td>\u7a0b\u5e8f\u5458\u9996\u9009<\/td>\n<\/tr>\n<tr>\n<td>Wireshark<\/td>\n<td>\u5168\u5e73\u53f0<\/td>\n<td>\u9700\u5bc6\u94a5<\/td>\n<td>\u4e0d\u652f\u6301<\/td>\n<td>\u514d\u8d39<\/td>\n<td>\u5e95\u5c42\u534f\u8bae\u5206\u6790<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>11.2 mitmproxy \u811a\u672c\u7f16\u5199<\/h4>\n<p><span class=\"token comment\"># mitm_proxy.py &#8211; mitmproxy\u722c\u866b\u6293\u5305\u811a\u672c<\/span><br \/>\n<span class=\"token comment\"># \u542f\u52a8\u547d\u4ee4: mitmweb -s mitm_proxy.py -p 8080<\/span><\/p>\n<p><span class=\"token keyword\">from<\/span> mitmproxy <span class=\"token keyword\">import<\/span> http<br \/>\n<span class=\"token keyword\">import<\/span> json<br \/>\n<span class=\"token keyword\">import<\/span> os<\/p>\n<p><span class=\"token comment\"># \u914d\u7f6e\u8981\u6293\u53d6\u7684API\u8def\u5f84\u5173\u952e\u8bcd<\/span><br \/>\nAPI_KEYWORDS <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;\/api\/&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;\/graphql&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;\/v1\/&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;\/v2\/&#034;<\/span><span class=\"token punctuation\">]<\/span><\/p>\n<p><span class=\"token keyword\">class<\/span> <span class=\"token class-name\">CrawlAddon<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;mitmproxy\u722c\u866b\u63d2\u4ef6&#034;&#034;&#034;<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">__init__<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>output_dir <span class=\"token operator\">&#061;<\/span> <span class=\"token string\">&#034;.\/captured_data&#034;<\/span><br \/>\n        os<span class=\"token punctuation\">.<\/span>makedirs<span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">.<\/span>output_dir<span class=\"token punctuation\">,<\/span> exist_ok<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">True<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>request_count <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">response<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> flow<span class=\"token punctuation\">:<\/span> http<span class=\"token punctuation\">.<\/span>HTTPFlow<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u62e6\u622a\u54cd\u5e94&#034;&#034;&#034;<\/span><br \/>\n        url <span class=\"token operator\">&#061;<\/span> flow<span class=\"token punctuation\">.<\/span>request<span class=\"token punctuation\">.<\/span>url<\/p>\n<p>        <span class=\"token keyword\">if<\/span> <span class=\"token keyword\">not<\/span> <span class=\"token builtin\">any<\/span><span class=\"token punctuation\">(<\/span>kw <span class=\"token keyword\">in<\/span> url <span class=\"token keyword\">for<\/span> kw <span class=\"token keyword\">in<\/span> API_KEYWORDS<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">return<\/span><\/p>\n<p>        content_type <span class=\"token operator\">&#061;<\/span> flow<span class=\"token punctuation\">.<\/span>response<span class=\"token punctuation\">.<\/span>headers<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;content-type&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;&#034;<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token string\">&#034;json&#034;<\/span> <span class=\"token keyword\">not<\/span> <span class=\"token keyword\">in<\/span> content_type<span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">return<\/span><\/p>\n<p>        self<span class=\"token punctuation\">.<\/span>request_count <span class=\"token operator\">&#043;&#061;<\/span> <span class=\"token number\">1<\/span><\/p>\n<p>        <span class=\"token keyword\">try<\/span><span class=\"token punctuation\">:<\/span><br \/>\n            data <span class=\"token operator\">&#061;<\/span> json<span class=\"token punctuation\">.<\/span>loads<span class=\"token punctuation\">(<\/span>flow<span class=\"token punctuation\">.<\/span>response<span class=\"token punctuation\">.<\/span>get_text<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>            filename <span class=\"token operator\">&#061;<\/span> <span class=\"token string-interpolation\"><span class=\"token string\">f&#034;<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>self<span class=\"token punctuation\">.<\/span>output_dir<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">\/req_<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>self<span class=\"token punctuation\">.<\/span>request_count<span class=\"token punctuation\">:<\/span><span class=\"token format-spec\">04d<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">.json&#034;<\/span><\/span><br \/>\n            <span class=\"token keyword\">with<\/span> <span class=\"token builtin\">open<\/span><span class=\"token punctuation\">(<\/span>filename<span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;w&#034;<\/span><span class=\"token punctuation\">,<\/span> encoding<span class=\"token operator\">&#061;<\/span><span class=\"token string\">&#034;utf-8&#034;<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">as<\/span> f<span class=\"token punctuation\">:<\/span><br \/>\n                json<span class=\"token punctuation\">.<\/span>dump<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span><br \/>\n                    <span class=\"token string\">&#034;url&#034;<\/span><span class=\"token punctuation\">:<\/span> url<span class=\"token punctuation\">,<\/span><br \/>\n                    <span class=\"token string\">&#034;method&#034;<\/span><span class=\"token punctuation\">:<\/span> flow<span class=\"token punctuation\">.<\/span>request<span class=\"token punctuation\">.<\/span>method<span class=\"token punctuation\">,<\/span><br \/>\n                    <span class=\"token string\">&#034;request_headers&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">dict<\/span><span class=\"token punctuation\">(<\/span>flow<span class=\"token punctuation\">.<\/span>request<span class=\"token punctuation\">.<\/span>headers<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                    <span class=\"token string\">&#034;request_body&#034;<\/span><span class=\"token punctuation\">:<\/span> flow<span class=\"token punctuation\">.<\/span>request<span class=\"token punctuation\">.<\/span>get_text<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                    <span class=\"token string\">&#034;status_code&#034;<\/span><span class=\"token punctuation\">:<\/span> flow<span class=\"token punctuation\">.<\/span>response<span class=\"token punctuation\">.<\/span>status_code<span class=\"token punctuation\">,<\/span><br \/>\n                    <span class=\"token string\">&#034;response_data&#034;<\/span><span class=\"token punctuation\">:<\/span> data<span class=\"token punctuation\">,<\/span><br \/>\n                <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span> f<span class=\"token punctuation\">,<\/span> ensure_ascii<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">False<\/span><span class=\"token punctuation\">,<\/span> indent<span class=\"token operator\">&#061;<\/span><span class=\"token number\">2<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>            <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;[<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>self<span class=\"token punctuation\">.<\/span>request_count<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">] <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>flow<span class=\"token punctuation\">.<\/span>request<span class=\"token punctuation\">.<\/span>method<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\"> <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>url<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>        <span class=\"token keyword\">except<\/span> json<span class=\"token punctuation\">.<\/span>JSONDecodeError<span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">pass<\/span><\/p>\n<p>addons <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span>CrawlAddon<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">]<\/span><\/p>\n<h4>11.3 APP\u6293\u5305\u5173\u952e\u6b65\u9aa4<\/h4>\n<p>\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510<br \/>\n\u2502              APP\u6293\u5305\u5b8c\u6574\u6d41\u7a0b                                    \u2502<br \/>\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524<br \/>\n\u2502                                                               \u2502<br \/>\n\u2502  [1.\u5b89\u88c5\u8bc1\u4e66]     [2.\u914d\u7f6e\u4ee3\u7406]     [3.\u4fe1\u4efb\u8bc1\u4e66]               \u2502<br \/>\n\u2502  \u5bfc\u51faCA\u8bc1\u4e66  &#8211;&gt;  WiFi\u4ee3\u7406    &#8211;&gt;  \u7cfb\u7edf\u8bbe\u7f6e                    \u2502<br \/>\n\u2502  \u5230\u624b\u673a        \u6307\u5411\u7535\u8111       \u5b89\u88c5\u8bc1\u4e66                         \u2502<br \/>\n\u2502                                   |                           \u2502<br \/>\n\u2502  [4.\u9a8c\u8bc1\u6293\u5305]     [5.\u5206\u6790\u534f\u8bae]     [6.\u6a21\u62df\u8bf7\u6c42]               \u2502<br \/>\n\u2502  \u6253\u5f00APP     &#8211;&gt;  \u7b5b\u9009API    &#8211;&gt;  Python\u590d\u73b0                  \u2502<br \/>\n\u2502  \u89e6\u53d1\u64cd\u4f5c        \u5206\u6790\u53c2\u6570        \u8bf7\u6c42                          \u2502<br \/>\n\u2502                                                               \u2502<br \/>\n\u2502  \u5e38\u89c1\u95ee\u9898:                                                    \u2502<br \/>\n\u2502  &#8211; Android 7&#043;\u4e0d\u4fe1\u4efb\u7528\u6237\u8bc1\u4e66 -&gt; Root\u540e\u5b89\u88c5\u5230\u7cfb\u7edf\u76ee\u5f55            \u2502<br \/>\n\u2502  &#8211; APP\u8bc1\u4e66\u7ed1\u5b9a(Certificate Pinning) -&gt; Frida Hook             \u2502<br \/>\n\u2502  &#8211; \u8bf7\u6c42\u53c2\u6570\u52a0\u5bc6 -&gt; \u9006\u5411APP\u6216Hook\u52a0\u5bc6\u51fd\u6570                      \u2502<br \/>\n\u2502                                                               \u2502<br \/>\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/p>\n<p>\u9762\u8bd5\u52a0\u5206\u63d0\u793a&#xff1a;Android 7.0&#043; \u9ed8\u8ba4\u4e0d\u4fe1\u4efb\u7528\u6237\u5b89\u88c5\u7684 CA \u8bc1\u4e66\u3002\u89e3\u51b3\u65b9\u6848&#xff1a;(1) Root \u540e\u5c06\u8bc1\u4e66\u5b89\u88c5\u5230\u7cfb\u7edf\u76ee\u5f55&#xff1b;(2) \u4f7f\u7528 Frida \u7ed5\u8fc7 Certificate Pinning&#xff1b;(3) \u4f7f\u7528\u5df2 Root \u7684\u6a21\u62df\u5668\u914d\u5408 Xposed \u7684 JustTrustMe \u6a21\u5757\u3002<\/p>\n<h3>12. \u5206\u5e03\u5f0f\u722c\u866b\u67b6\u6784<\/h3>\n<h4>12.1 Scrapy-Redis \u5206\u5e03\u5f0f\u539f\u7406<\/h4>\n<p>\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510<br \/>\n\u2502               Scrapy-Redis \u5206\u5e03\u5f0f\u67b6\u6784                             \u2502<br \/>\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524<br \/>\n\u2502                                                                  \u2502<br \/>\n\u2502  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510               \u2502<br \/>\n\u2502  \u2502              Redis \u4e2d\u592e\u5b58\u50a8                    \u2502               \u2502<br \/>\n\u2502  \u2502  \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510  \u2502               \u2502<br \/>\n\u2502  \u2502  \u2502 \u8bf7\u6c42\u961f\u5217   \u2502 \u2502 \u53bb\u91cd\u96c6\u5408 \u2502 \u2502 \u7ed3\u679c\u961f\u5217   \u2502  \u2502               \u2502<br \/>\n\u2502  \u2502  \u2502 (List\/ZSET)\u2502 \u2502  (Set)   \u2502 \u2502  (List)    \u2502  \u2502               \u2502<br \/>\n\u2502  \u2502  \u2514\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2518  \u2502               \u2502<br \/>\n\u2502  \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518               \u2502<br \/>\n\u2502           \u2502              \u2502              \u2502                        \u2502<br \/>\n\u2502    \u250c\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253c\u2500\u2500\u2500\u2500\u2500\u2500\u2510                \u2502<br \/>\n\u2502    \u2502      \u2502              \u2502              \u2502      \u2502                \u2502<br \/>\n\u2502  [Worker 1]        [Worker 2]       [Worker N]                 \u2502<br \/>\n\u2502  &#043;&#8212;&#8212;&#8212;&#043;       &#043;&#8212;&#8212;&#8212;-&#043;     &#043;&#8212;&#8212;&#8212;&#043;                \u2502<br \/>\n\u2502  |Scrapy   |       | Scrapy   |     | Scrapy  |                \u2502<br \/>\n\u2502  |Engine   |       | Engine   |     | Engine  |                \u2502<br \/>\n\u2502  &#043;&#8212;-&#043;&#8212;-&#043;       &#043;&#8212;-&#043;&#8212;&#8211;&#043;     &#043;&#8212;-&#043;&#8212;-&#043;                \u2502<br \/>\n\u2502       |                 |               |                      \u2502<br \/>\n\u2502  [Pipeline]        [Pipeline]       [Pipeline]                 \u2502<br \/>\n\u2502  (\u672c\u5730\u5b58\u50a8)        (\u672c\u5730\u5b58\u50a8)       (\u672c\u5730\u5b58\u50a8)                   \u2502<br \/>\n\u2502                                                                  \u2502<br \/>\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/p>\n<h4>12.2 Scrapy-Redis \u914d\u7f6e<\/h4>\n<p><span class=\"token comment\"># settings.py &#8211; Scrapy-Redis \u5206\u5e03\u5f0f\u914d\u7f6e<\/span><\/p>\n<p><span class=\"token comment\"># \u4f7f\u7528Redis\u8c03\u5ea6\u5668<\/span><br \/>\nSCHEDULER <span class=\"token operator\">&#061;<\/span> <span class=\"token string\">&#034;scrapy_redis.scheduler.Scheduler&#034;<\/span><\/p>\n<p><span class=\"token comment\"># \u4f7f\u7528Redis\u53bb\u91cd<\/span><br \/>\nDUPEFILTER_CLASS <span class=\"token operator\">&#061;<\/span> <span class=\"token string\">&#034;scrapy_redis.dupefilter.RFPDupeFilter&#034;<\/span><\/p>\n<p><span class=\"token comment\"># Redis\u8fde\u63a5\u914d\u7f6e<\/span><br \/>\nREDIS_URL <span class=\"token operator\">&#061;<\/span> <span class=\"token string\">&#034;redis:\/\/:your_password&#064;redis-master:6379\/0&#034;<\/span><\/p>\n<p><span class=\"token comment\"># \u6301\u4e45\u5316\u961f\u5217&#xff08;\u65ad\u70b9\u7eed\u722c&#xff09;<\/span><br \/>\nSCHEDULER_PERSIST <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">True<\/span><\/p>\n<p><span class=\"token comment\"># \u961f\u5217\u7c7b\u578b<\/span><br \/>\n<span class=\"token comment\"># SCHEDULER_QUEUE_CLASS &#061; &#034;scrapy_redis.queue.FifoQueue&#034;       # \u5148\u8fdb\u5148\u51fa<\/span><br \/>\n<span class=\"token comment\"># SCHEDULER_QUEUE_CLASS &#061; &#034;scrapy_redis.queue.LifoQueue&#034;       # \u540e\u8fdb\u5148\u51fa(\u6df1\u5ea6\u4f18\u5148)<\/span><br \/>\n<span class=\"token comment\"># SCHEDULER_QUEUE_CLASS &#061; &#034;scrapy_redis.queue.PriorityQueue&#034;   # \u4f18\u5148\u7ea7\u961f\u5217<\/span><\/p>\n<h4>12.3 \u5e03\u9686\u8fc7\u6ee4\u5668\u53bb\u91cd<\/h4>\n<p><span class=\"token keyword\">import<\/span> math<br \/>\n<span class=\"token keyword\">import<\/span> mmh3<br \/>\n<span class=\"token keyword\">from<\/span> bitarray <span class=\"token keyword\">import<\/span> bitarray<\/p>\n<p><span class=\"token keyword\">class<\/span> <span class=\"token class-name\">BloomFilter<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;<br \/>\n    \u5e03\u9686\u8fc7\u6ee4\u5668 &#8211; \u5185\u5b58\u9ad8\u6548\u7684URL\u53bb\u91cd\u65b9\u6848<br \/>\n    \u9002\u7528\u4e8e\u6d77\u91cfURL\u53bb\u91cd&#xff0c;\u8bef\u5224\u7387\u53ef\u63a7<br \/>\n    &#034;&#034;&#034;<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">__init__<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> expected_count<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">int<\/span><span class=\"token punctuation\">,<\/span> error_rate<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">float<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0.001<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>size <span class=\"token operator\">&#061;<\/span> self<span class=\"token punctuation\">.<\/span>_optimal_size<span class=\"token punctuation\">(<\/span>expected_count<span class=\"token punctuation\">,<\/span> error_rate<span class=\"token punctuation\">)<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>hash_count <span class=\"token operator\">&#061;<\/span> self<span class=\"token punctuation\">.<\/span>_optimal_hash_count<span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">.<\/span>size<span class=\"token punctuation\">,<\/span> expected_count<span class=\"token punctuation\">)<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>bit_array <span class=\"token operator\">&#061;<\/span> bitarray<span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">.<\/span>size<span class=\"token punctuation\">)<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>bit_array<span class=\"token punctuation\">.<\/span>setall<span class=\"token punctuation\">(<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>count <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0<\/span><\/p>\n<p>    <span class=\"token decorator annotation punctuation\">&#064;staticmethod<\/span><br \/>\n    <span class=\"token keyword\">def<\/span> <span class=\"token function\">_optimal_size<\/span><span class=\"token punctuation\">(<\/span>n<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">int<\/span><span class=\"token punctuation\">,<\/span> p<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">float<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">int<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        m <span class=\"token operator\">&#061;<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token punctuation\">(<\/span>n <span class=\"token operator\">*<\/span> math<span class=\"token punctuation\">.<\/span>log<span class=\"token punctuation\">(<\/span>p<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">\/<\/span> <span class=\"token punctuation\">(<\/span>math<span class=\"token punctuation\">.<\/span>log<span class=\"token punctuation\">(<\/span><span class=\"token number\">2<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">**<\/span> <span class=\"token number\">2<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token builtin\">int<\/span><span class=\"token punctuation\">(<\/span>m<span class=\"token punctuation\">)<\/span><\/p>\n<p>    <span class=\"token decorator annotation punctuation\">&#064;staticmethod<\/span><br \/>\n    <span class=\"token keyword\">def<\/span> <span class=\"token function\">_optimal_hash_count<\/span><span class=\"token punctuation\">(<\/span>m<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">int<\/span><span class=\"token punctuation\">,<\/span> n<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">int<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">int<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        k <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span>m <span class=\"token operator\">\/<\/span> n<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">*<\/span> math<span class=\"token punctuation\">.<\/span>log<span class=\"token punctuation\">(<\/span><span class=\"token number\">2<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token builtin\">int<\/span><span class=\"token punctuation\">(<\/span>k<span class=\"token punctuation\">)<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">_hash_values<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> item<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token keyword\">for<\/span> i <span class=\"token keyword\">in<\/span> <span class=\"token builtin\">range<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">.<\/span>hash_count<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">yield<\/span> mmh3<span class=\"token punctuation\">.<\/span><span class=\"token builtin\">hash<\/span><span class=\"token punctuation\">(<\/span>item<span class=\"token punctuation\">,<\/span> i<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">%<\/span> self<span class=\"token punctuation\">.<\/span>size<\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">add<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> item<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token keyword\">for<\/span> bit_pos <span class=\"token keyword\">in<\/span> self<span class=\"token punctuation\">.<\/span>_hash_values<span class=\"token punctuation\">(<\/span>item<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n            self<span class=\"token punctuation\">.<\/span>bit_array<span class=\"token punctuation\">[<\/span>bit_pos<span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">1<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>count <span class=\"token operator\">&#043;&#061;<\/span> <span class=\"token number\">1<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">__contains__<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> item<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">bool<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token builtin\">all<\/span><span class=\"token punctuation\">(<\/span><br \/>\n            self<span class=\"token punctuation\">.<\/span>bit_array<span class=\"token punctuation\">[<\/span>bit_pos<span class=\"token punctuation\">]<\/span><br \/>\n            <span class=\"token keyword\">for<\/span> bit_pos <span class=\"token keyword\">in<\/span> self<span class=\"token punctuation\">.<\/span>_hash_values<span class=\"token punctuation\">(<\/span>item<span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token comment\"># \u4f7f\u7528\u793a\u4f8b<\/span><br \/>\nbf <span class=\"token operator\">&#061;<\/span> BloomFilter<span class=\"token punctuation\">(<\/span>expected_count<span class=\"token operator\">&#061;<\/span><span class=\"token number\">10_000_000<\/span><span class=\"token punctuation\">,<\/span> error_rate<span class=\"token operator\">&#061;<\/span><span class=\"token number\">0.001<\/span><span class=\"token punctuation\">)<\/span><br \/>\n<span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u4f4d\u6570\u7ec4\u5927\u5c0f: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>bf<span class=\"token punctuation\">.<\/span>size <span class=\"token operator\">\/<\/span> <span class=\"token number\">1024<\/span> <span class=\"token operator\">\/<\/span> <span class=\"token number\">1024<\/span><span class=\"token punctuation\">:<\/span><span class=\"token format-spec\">.1f<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\"> MB&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n<span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u54c8\u5e0c\u51fd\u6570\u6570: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>bf<span class=\"token punctuation\">.<\/span>hash_count<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>bf<span class=\"token punctuation\">.<\/span>add<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;https:\/\/example.com\/page\/1&#034;<\/span><span class=\"token punctuation\">)<\/span><br \/>\nbf<span class=\"token punctuation\">.<\/span>add<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;https:\/\/example.com\/page\/2&#034;<\/span><span class=\"token punctuation\">)<\/span><br \/>\n<span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;page\/1\u5b58\u5728:&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;https:\/\/example.com\/page\/1&#034;<\/span> <span class=\"token keyword\">in<\/span> bf<span class=\"token punctuation\">)<\/span>  <span class=\"token comment\"># True<\/span><br \/>\n<span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;page\/3\u5b58\u5728:&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;https:\/\/example.com\/page\/3&#034;<\/span> <span class=\"token keyword\">in<\/span> bf<span class=\"token punctuation\">)<\/span>  <span class=\"token comment\"># False<\/span><\/p>\n<h4>12.4 \u5206\u5e03\u5f0f\u8c03\u5ea6\u65b9\u6848\u5bf9\u6bd4<\/h4>\n<table>\n<tr>\u65b9\u6848\u7279\u70b9\u9002\u7528\u89c4\u6a21\u590d\u6742\u5ea6<\/tr>\n<tbody>\n<tr>\n<td>Scrapy-Redis<\/td>\n<td>\u7b80\u5355&#xff0c;Redis\u961f\u5217<\/td>\n<td>\u4e2d\u5c0f&#xff08;10\u8282\u70b9\u5185&#xff09;<\/td>\n<td>\u4f4e<\/td>\n<\/tr>\n<tr>\n<td>Celery &#043; Redis<\/td>\n<td>\u4efb\u52a1\u961f\u5217\u6210\u719f<\/td>\n<td>\u4e2d\u7b49<\/td>\n<td>\u4e2d<\/td>\n<\/tr>\n<tr>\n<td>Kafka &#043; Scrapy<\/td>\n<td>\u9ad8\u541e\u5410&#xff0c;\u6301\u4e45\u5316<\/td>\n<td>\u5927\u578b&#xff08;100&#043;\u8282\u70b9&#xff09;<\/td>\n<td>\u9ad8<\/td>\n<\/tr>\n<tr>\n<td>RabbitMQ &#043; Scrapy<\/td>\n<td>\u53ef\u9760\u6d88\u606f\u4f20\u9012<\/td>\n<td>\u4e2d\u5927\u578b<\/td>\n<td>\u4e2d<\/td>\n<\/tr>\n<tr>\n<td>\u81ea\u7814\u8c03\u5ea6&#xff08;Redis&#043;FastAPI&#xff09;<\/td>\n<td>\u5b8c\u5168\u53ef\u63a7<\/td>\n<td>\u6309\u9700<\/td>\n<td>\u9ad8<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr \/>\n<h3>13. \u6570\u636e\u5b58\u50a8\u4e0e\u6e05\u6d17<\/h3>\n<h4>13.1 \u5b58\u50a8\u65b9\u6848\u5bf9\u6bd4<\/h4>\n<table>\n<tr>\u6570\u636e\u5e93\u7c7b\u578b\u5199\u5165\u901f\u5ea6\u67e5\u8be2\u80fd\u529b\u9002\u7528\u573a\u666f\u63a8\u8350\u89c4\u6a21<\/tr>\n<tbody>\n<tr>\n<td>MongoDB<\/td>\n<td>\u6587\u6863\u578b<\/td>\n<td>\u5feb<\/td>\n<td>\u7075\u6d3b<\/td>\n<td>\u534a\u7ed3\u6784\u5316\u6570\u636e<\/td>\n<td>\u767e\u4e07-\u5343\u4e07<\/td>\n<\/tr>\n<tr>\n<td>MySQL<\/td>\n<td>\u5173\u7cfb\u578b<\/td>\n<td>\u4e2d<\/td>\n<td>SQL\u5f3a\u5927<\/td>\n<td>\u7ed3\u6784\u5316\u6570\u636e<\/td>\n<td>\u5341\u4e07-\u767e\u4e07<\/td>\n<\/tr>\n<tr>\n<td>PostgreSQL<\/td>\n<td>\u5173\u7cfb\u578b<\/td>\n<td>\u4e2d<\/td>\n<td>SQL&#043;JSON<\/td>\n<td>\u590d\u6742\u67e5\u8be2<\/td>\n<td>\u767e\u4e07-\u5343\u4e07<\/td>\n<\/tr>\n<tr>\n<td>Elasticsearch<\/td>\n<td>\u641c\u7d22\u5f15\u64ce<\/td>\n<td>\u5feb<\/td>\n<td>\u5168\u6587\u68c0\u7d22<\/td>\n<td>\u65e5\u5fd7\/\u641c\u7d22<\/td>\n<td>\u5343\u4e07-\u4ebf<\/td>\n<\/tr>\n<tr>\n<td>CSV\/JSON<\/td>\n<td>\u6587\u4ef6<\/td>\n<td>\u6781\u5feb<\/td>\n<td>\u65e0<\/td>\n<td>\u4e34\u65f6\u5b58\u50a8<\/td>\n<td>\u4e07\u7ea7<\/td>\n<\/tr>\n<tr>\n<td>Redis<\/td>\n<td>\u7f13\u5b58<\/td>\n<td>\u6781\u5feb<\/td>\n<td>K-V<\/td>\n<td>\u961f\u5217\/\u7f13\u5b58<\/td>\n<td>\u5185\u5b58\u9650\u5236<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>13.2 MongoDB \u5b58\u50a8\u5b9e\u6218<\/h4>\n<p><span class=\"token keyword\">import<\/span> pymongo<br \/>\n<span class=\"token keyword\">from<\/span> datetime <span class=\"token keyword\">import<\/span> datetime<\/p>\n<p><span class=\"token keyword\">class<\/span> <span class=\"token class-name\">MongoStorage<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;MongoDB\u6570\u636e\u5b58\u50a8\u7ba1\u9053&#034;&#034;&#034;<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">__init__<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> uri<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token string\">&#034;mongodb:\/\/localhost:27017&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                 db_name<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token string\">&#034;crawler_data&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>client <span class=\"token operator\">&#061;<\/span> pymongo<span class=\"token punctuation\">.<\/span>MongoClient<span class=\"token punctuation\">(<\/span>uri<span class=\"token punctuation\">)<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>db <span class=\"token operator\">&#061;<\/span> self<span class=\"token punctuation\">.<\/span>client<span class=\"token punctuation\">[<\/span>db_name<span class=\"token punctuation\">]<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">save_items<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> collection_name<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">,<\/span> items<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">list<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u6279\u91cf\u4fdd\u5b58\u6570\u636e&#034;&#034;&#034;<\/span><br \/>\n        collection <span class=\"token operator\">&#061;<\/span> self<span class=\"token punctuation\">.<\/span>db<span class=\"token punctuation\">[<\/span>collection_name<span class=\"token punctuation\">]<\/span><\/p>\n<p>        <span class=\"token keyword\">for<\/span> item <span class=\"token keyword\">in<\/span> items<span class=\"token punctuation\">:<\/span><br \/>\n            item<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;crawled_at&#034;<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#061;<\/span> datetime<span class=\"token punctuation\">.<\/span>utcnow<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>        operations <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">]<\/span><br \/>\n        <span class=\"token keyword\">for<\/span> item <span class=\"token keyword\">in<\/span> items<span class=\"token punctuation\">:<\/span><br \/>\n            operations<span class=\"token punctuation\">.<\/span>append<span class=\"token punctuation\">(<\/span><br \/>\n                pymongo<span class=\"token punctuation\">.<\/span>UpdateOne<span class=\"token punctuation\">(<\/span><br \/>\n                    <span class=\"token punctuation\">{<\/span><span class=\"token string\">&#034;url&#034;<\/span><span class=\"token punctuation\">:<\/span> item<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;url&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                    <span class=\"token punctuation\">{<\/span><span class=\"token string\">&#034;$set&#034;<\/span><span class=\"token punctuation\">:<\/span> item<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                    upsert<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">True<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                <span class=\"token punctuation\">)<\/span><br \/>\n            <span class=\"token punctuation\">)<\/span><\/p>\n<p>        <span class=\"token keyword\">if<\/span> operations<span class=\"token punctuation\">:<\/span><br \/>\n            result <span class=\"token operator\">&#061;<\/span> collection<span class=\"token punctuation\">.<\/span>bulk_write<span class=\"token punctuation\">(<\/span>operations<span class=\"token punctuation\">)<\/span><br \/>\n            <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u63d2\u5165: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>result<span class=\"token punctuation\">.<\/span>upserted_count<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">, \u66f4\u65b0: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>result<span class=\"token punctuation\">.<\/span>modified_count<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">create_indexes<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> collection_name<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u521b\u5efa\u7d22\u5f15\u52a0\u901f\u67e5\u8be2&#034;&#034;&#034;<\/span><br \/>\n        collection <span class=\"token operator\">&#061;<\/span> self<span class=\"token punctuation\">.<\/span>db<span class=\"token punctuation\">[<\/span>collection_name<span class=\"token punctuation\">]<\/span><br \/>\n        collection<span class=\"token punctuation\">.<\/span>create_index<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;url&#034;<\/span><span class=\"token punctuation\">,<\/span> pymongo<span class=\"token punctuation\">.<\/span>HASHED<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        collection<span class=\"token punctuation\">.<\/span>create_index<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;crawled_at&#034;<\/span><span class=\"token punctuation\">,<\/span> pymongo<span class=\"token punctuation\">.<\/span>DESCENDING<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        collection<span class=\"token punctuation\">.<\/span>create_index<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;title&#034;<\/span><span class=\"token punctuation\">,<\/span> pymongo<span class=\"token punctuation\">.<\/span>TEXT<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<h4>13.3 \u6570\u636e\u6e05\u6d17 Pipeline<\/h4>\n<p><span class=\"token keyword\">import<\/span> pandas <span class=\"token keyword\">as<\/span> pd<br \/>\n<span class=\"token keyword\">import<\/span> re<br \/>\n<span class=\"token keyword\">from<\/span> typing <span class=\"token keyword\">import<\/span> List<span class=\"token punctuation\">,<\/span> Dict<\/p>\n<p><span class=\"token keyword\">class<\/span> <span class=\"token class-name\">DataCleaner<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u6570\u636e\u6e05\u6d17\u7ba1\u9053&#034;&#034;&#034;<\/span><\/p>\n<p>    <span class=\"token decorator annotation punctuation\">&#064;staticmethod<\/span><br \/>\n    <span class=\"token keyword\">def<\/span> <span class=\"token function\">clean_price<\/span><span class=\"token punctuation\">(<\/span>price_str<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">float<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u6e05\u6d17\u4ef7\u683c\u5b57\u6bb5&#034;&#034;&#034;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token keyword\">not<\/span> price_str<span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">return<\/span> <span class=\"token number\">0.0<\/span><br \/>\n        cleaned <span class=\"token operator\">&#061;<\/span> re<span class=\"token punctuation\">.<\/span>sub<span class=\"token punctuation\">(<\/span><span class=\"token string\">r&#039;[^0-9.]&#039;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#039;&#039;<\/span><span class=\"token punctuation\">,<\/span> price_str<span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">try<\/span><span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">return<\/span> <span class=\"token builtin\">float<\/span><span class=\"token punctuation\">(<\/span>cleaned<span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">except<\/span> ValueError<span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">return<\/span> <span class=\"token number\">0.0<\/span><\/p>\n<p>    <span class=\"token decorator annotation punctuation\">&#064;staticmethod<\/span><br \/>\n    <span class=\"token keyword\">def<\/span> <span class=\"token function\">clean_text<\/span><span class=\"token punctuation\">(<\/span>text<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u6e05\u6d17\u6587\u672c\u5b57\u6bb5&#034;&#034;&#034;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token keyword\">not<\/span> text<span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">return<\/span> <span class=\"token string\">&#034;&#034;<\/span><br \/>\n        text <span class=\"token operator\">&#061;<\/span> re<span class=\"token punctuation\">.<\/span>sub<span class=\"token punctuation\">(<\/span><span class=\"token string\">r&#039;\\\\s&#043;&#039;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#039; &#039;<\/span><span class=\"token punctuation\">,<\/span> text<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>strip<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        text <span class=\"token operator\">&#061;<\/span> re<span class=\"token punctuation\">.<\/span>sub<span class=\"token punctuation\">(<\/span><span class=\"token string\">r&#039;[\\\\x00-\\\\x08\\\\x0b\\\\x0c\\\\x0e-\\\\x1f\\\\x7f]&#039;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#039;&#039;<\/span><span class=\"token punctuation\">,<\/span> text<span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> text<\/p>\n<p>    <span class=\"token decorator annotation punctuation\">&#064;staticmethod<\/span><br \/>\n    <span class=\"token keyword\">def<\/span> <span class=\"token function\">deduplicate<\/span><span class=\"token punctuation\">(<\/span>items<span class=\"token punctuation\">:<\/span> List<span class=\"token punctuation\">[<\/span>Dict<span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">,<\/span> key_field<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> List<span class=\"token punctuation\">[<\/span>Dict<span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u57fa\u4e8e\u5173\u952e\u5b57\u6bb5\u53bb\u91cd&#034;&#034;&#034;<\/span><br \/>\n        seen <span class=\"token operator\">&#061;<\/span> <span class=\"token builtin\">set<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        unique_items <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">]<\/span><br \/>\n        <span class=\"token keyword\">for<\/span> item <span class=\"token keyword\">in<\/span> items<span class=\"token punctuation\">:<\/span><br \/>\n            key <span class=\"token operator\">&#061;<\/span> item<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span>key_field<span class=\"token punctuation\">)<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> key <span class=\"token keyword\">and<\/span> key <span class=\"token keyword\">not<\/span> <span class=\"token keyword\">in<\/span> seen<span class=\"token punctuation\">:<\/span><br \/>\n                seen<span class=\"token punctuation\">.<\/span>add<span class=\"token punctuation\">(<\/span>key<span class=\"token punctuation\">)<\/span><br \/>\n                unique_items<span class=\"token punctuation\">.<\/span>append<span class=\"token punctuation\">(<\/span>item<span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> unique_items<\/p>\n<p>    <span class=\"token decorator annotation punctuation\">&#064;staticmethod<\/span><br \/>\n    <span class=\"token keyword\">def<\/span> <span class=\"token function\">to_dataframe<\/span><span class=\"token punctuation\">(<\/span>items<span class=\"token punctuation\">:<\/span> List<span class=\"token punctuation\">[<\/span>Dict<span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> pd<span class=\"token punctuation\">.<\/span>DataFrame<span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u8f6c\u6362\u4e3aDataFrame\u8fdb\u884c\u5206\u6790&#034;&#034;&#034;<\/span><br \/>\n        df <span class=\"token operator\">&#061;<\/span> pd<span class=\"token punctuation\">.<\/span>DataFrame<span class=\"token punctuation\">(<\/span>items<span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token string\">&#039;price&#039;<\/span> <span class=\"token keyword\">in<\/span> df<span class=\"token punctuation\">.<\/span>columns<span class=\"token punctuation\">:<\/span><br \/>\n            df<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#039;price&#039;<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#061;<\/span> pd<span class=\"token punctuation\">.<\/span>to_numeric<span class=\"token punctuation\">(<\/span>df<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#039;price&#039;<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">,<\/span> errors<span class=\"token operator\">&#061;<\/span><span class=\"token string\">&#039;coerce&#039;<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        df<span class=\"token punctuation\">.<\/span>dropna<span class=\"token punctuation\">(<\/span>how<span class=\"token operator\">&#061;<\/span><span class=\"token string\">&#039;all&#039;<\/span><span class=\"token punctuation\">,<\/span> inplace<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">True<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> df<\/p>\n<p>    <span class=\"token decorator annotation punctuation\">&#064;staticmethod<\/span><br \/>\n    <span class=\"token keyword\">def<\/span> <span class=\"token function\">export_csv<\/span><span class=\"token punctuation\">(<\/span>df<span class=\"token punctuation\">:<\/span> pd<span class=\"token punctuation\">.<\/span>DataFrame<span class=\"token punctuation\">,<\/span> filepath<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u5bfc\u51fa\u4e3aCSV&#034;&#034;&#034;<\/span><br \/>\n        df<span class=\"token punctuation\">.<\/span>to_csv<span class=\"token punctuation\">(<\/span>filepath<span class=\"token punctuation\">,<\/span> index<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">False<\/span><span class=\"token punctuation\">,<\/span> encoding<span class=\"token operator\">&#061;<\/span><span class=\"token string\">&#039;utf-8-sig&#039;<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>\u751f\u4ea7\u8e29\u5751\u63d0\u9192&#xff1a;MongoDB \u7684 update_one &#043; upsert \u6a21\u5f0f\u5728\u9ad8\u9891\u5199\u5165\u65f6\u53ef\u80fd\u4ea7\u751f\u7ade\u6001\u6761\u4ef6\u3002\u751f\u4ea7\u73af\u5883\u5efa\u8bae\u4f7f\u7528 bulk_write \u6279\u91cf\u64cd\u4f5c&#xff0c;\u5e76\u5728 url \u5b57\u6bb5\u4e0a\u521b\u5efa\u552f\u4e00\u7d22\u5f15\u3002<\/p>\n<hr \/>\n<h3>14. \u6cd5\u5f8b\u5408\u89c4\u4e0erobots\u534f\u8bae<\/h3>\n<h4>14.1 \u4e2d\u56fd\u76f8\u5173\u6cd5\u5f8b\u6cd5\u89c4<\/h4>\n<table>\n<tr>\u6cd5\u5f8b\u6cd5\u89c4\u751f\u6548\u65f6\u95f4\u4e0e\u722c\u866b\u76f8\u5173\u7684\u6838\u5fc3\u6761\u6b3e<\/tr>\n<tbody>\n<tr>\n<td>\u300a\u7f51\u7edc\u5b89\u5168\u6cd5\u300b<\/td>\n<td>2017.06<\/td>\n<td>\u7b2c27\u6761&#xff1a;\u7981\u6b62\u4ece\u4e8b\u975e\u6cd5\u4fb5\u5165\u7f51\u7edc\u3001\u5e72\u6270\u7f51\u7edc\u6b63\u5e38\u529f\u80fd<\/td>\n<\/tr>\n<tr>\n<td>\u300a\u6570\u636e\u5b89\u5168\u6cd5\u300b<\/td>\n<td>2021.09<\/td>\n<td>\u7b2c32\u6761&#xff1a;\u4efb\u4f55\u7ec4\u7ec7\u548c\u4e2a\u4eba\u6536\u96c6\u6570\u636e\u5e94\u5f53\u5408\u6cd5\u6b63\u5f53<\/td>\n<\/tr>\n<tr>\n<td>\u300a\u4e2a\u4eba\u4fe1\u606f\u4fdd\u62a4\u6cd5\u300b<\/td>\n<td>2021.11<\/td>\n<td>\u7b2c13\u6761&#xff1a;\u5904\u7406\u4e2a\u4eba\u4fe1\u606f\u9700\u53d6\u5f97\u540c\u610f\u6216\u6709\u6cd5\u5b9a\u4e8b\u7531<\/td>\n<\/tr>\n<tr>\n<td>\u300a\u53cd\u4e0d\u6b63\u5f53\u7ade\u4e89\u6cd5\u300b<\/td>\n<td>2019.04<\/td>\n<td>\u7b2c12\u6761&#xff1a;\u7981\u6b62\u5229\u7528\u6280\u672f\u624b\u6bb5\u59a8\u788d\u7f51\u7edc\u4ea7\u54c1\u6b63\u5e38\u8fd0\u884c<\/td>\n<\/tr>\n<tr>\n<td>\u300a\u5211\u6cd5\u300b\u7b2c285\u6761<\/td>\n<td>&#8211;<\/td>\n<td>\u975e\u6cd5\u83b7\u53d6\u8ba1\u7b97\u673a\u4fe1\u606f\u7cfb\u7edf\u6570\u636e\u7f6a&#xff08;\u6700\u9ad87\u5e74&#xff09;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>14.2 robots.txt \u89c4\u8303<\/h4>\n<p><span class=\"token keyword\">from<\/span> urllib<span class=\"token punctuation\">.<\/span>robotparser <span class=\"token keyword\">import<\/span> RobotFileParser<\/p>\n<p><span class=\"token keyword\">def<\/span> <span class=\"token function\">check_robots_txt<\/span><span class=\"token punctuation\">(<\/span>base_url<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">,<\/span> user_agent<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token string\">&#034;*&#034;<\/span><span class=\"token punctuation\">,<\/span> path<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token string\">&#034;\/&#034;<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">bool<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u68c0\u67e5robots.txt\u662f\u5426\u5141\u8bb8\u722c\u53d6&#034;&#034;&#034;<\/span><br \/>\n    rp <span class=\"token operator\">&#061;<\/span> RobotFileParser<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    robots_url <span class=\"token operator\">&#061;<\/span> <span class=\"token string-interpolation\"><span class=\"token string\">f&#034;<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>base_url<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">\/robots.txt&#034;<\/span><\/span><br \/>\n    rp<span class=\"token punctuation\">.<\/span>set_url<span class=\"token punctuation\">(<\/span>robots_url<span class=\"token punctuation\">)<\/span><\/p>\n<p>    <span class=\"token keyword\">try<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        rp<span class=\"token punctuation\">.<\/span>read<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        can_fetch <span class=\"token operator\">&#061;<\/span> rp<span class=\"token punctuation\">.<\/span>can_fetch<span class=\"token punctuation\">(<\/span>user_agent<span class=\"token punctuation\">,<\/span> path<span class=\"token punctuation\">)<\/span><br \/>\n        crawl_delay <span class=\"token operator\">&#061;<\/span> rp<span class=\"token punctuation\">.<\/span>crawl_delay<span class=\"token punctuation\">(<\/span>user_agent<span class=\"token punctuation\">)<\/span><\/p>\n<p>        <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;URL: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>path<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u5141\u8bb8\u722c\u53d6: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>can_fetch<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u8bf7\u6c42\u95f4\u9694: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>crawl_delay<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">\u79d2&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>        <span class=\"token keyword\">return<\/span> can_fetch<br \/>\n    <span class=\"token keyword\">except<\/span> Exception <span class=\"token keyword\">as<\/span> e<span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u8bfb\u53d6robots.txt\u5931\u8d25: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>e<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">True<\/span><\/p>\n<h4>14.3 \u722c\u866b\u5408\u89c4\u8fb9\u754c<\/h4>\n<p>\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510<br \/>\n\u2502                  \u722c\u866b\u884c\u4e3a\u5408\u89c4\u5149\u8c31                                \u2502<br \/>\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524<br \/>\n\u2502                                                               \u2502<br \/>\n\u2502  [\u5408\u89c4\u533a\u57df]                       [\u8fdd\u6cd5\u533a\u57df]                   \u2502<br \/>\n\u2502  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-&#043;     &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-&#043;  \u2502<br \/>\n\u2502  | \u9075\u5b88robots.txt          |     | \u7ed5\u8fc7\u767b\u5f55\u8ba4\u8bc1            |  \u2502<br \/>\n\u2502  | \u5408\u7406\u8bf7\u6c42\u9891\u7387            |     | \u6279\u91cf\u6293\u53d6\u4e2a\u4eba\u4fe1\u606f        |  \u2502<br \/>\n\u2502  | \u6293\u53d6\u516c\u5f00\u6570\u636e            |     | \u7834\u89e3\u52a0\u5bc6\u63a5\u53e3            |  \u2502<br \/>\n\u2502  | \u6807\u6ce8\u6570\u636e\u6765\u6e90            |     | \u5e72\u6270\u7f51\u7ad9\u8fd0\u884c            |  \u2502<br \/>\n\u2502  | \u7528\u4e8e\u5185\u90e8\u5206\u6790            |     | \u5546\u4e1a\u7ade\u4e89\u725f\u5229            |  \u2502<br \/>\n\u2502  | \u5b66\u672f\u7814\u7a76\u7528\u9014            |     | \u51fa\u552e\u4e2a\u4eba\u4fe1\u606f            |  \u2502<br \/>\n\u2502  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-&#043;     &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-&#043;  \u2502<br \/>\n\u2502                                                               \u2502<br \/>\n\u2502  [\u7070\u8272\u5730\u5e26 &#8211; \u9700\u8c28\u614e\u8bc4\u4f30]                                      \u2502<br \/>\n\u2502  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-&#043;   \u2502<br \/>\n\u2502  | \u6293\u53d6\u975e\u516c\u5f00\u4f46\u53ef\u8bbf\u95ee\u7684\u6570\u636e&#xff08;\u9700\u767b\u5f55\u4f46\u65e0\u6743\u9650\u63a7\u5236&#xff09;          |   \u2502<br \/>\n\u2502  | \u5927\u89c4\u6a21\u6293\u53d6\u7528\u4e8e\u5546\u4e1a\u5206\u6790                                 |   \u2502<br \/>\n\u2502  | \u7a81\u7834\u53cd\u722c\u63aa\u65bd&#xff08;\u6280\u672f\u5bf9\u6297\u672c\u8eab\u53ef\u80fd\u8fdd\u6cd5&#xff09;                   |   \u2502<br \/>\n\u2502  | \u6293\u53d6\u5185\u5bb9\u6d89\u53ca\u7248\u6743\u4f5c\u54c1                                   |   \u2502<br \/>\n\u2502  &#043;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-&#043;   \u2502<br \/>\n\u2502                                                               \u2502<br \/>\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/p>\n<h4>14.4 \u5178\u578b\u6848\u4f8b\u5206\u6790<\/h4>\n<table>\n<tr>\u6848\u4f8b\u5e74\u4efd\u884c\u4e3a\u5224\u51b3\u542f\u793a<\/tr>\n<tbody>\n<tr>\n<td>\u5fae\u8109\u5b9d\u722c\u866b\u6848<\/td>\n<td>2019<\/td>\n<td>\u6279\u91cf\u722c\u53d6\u7528\u6237\u6570\u636e\u5e76\u51fa\u552e<\/td>\n<td>\u6709\u671f\u5f92\u52113\u5e74<\/td>\n<td>\u4e2a\u4eba\u4fe1\u606f\u4e0d\u53ef\u968f\u610f\u6293\u53d6<\/td>\n<\/tr>\n<tr>\n<td>\u67d0\u6570\u636e\u516c\u53f8\u6848<\/td>\n<td>2020<\/td>\n<td>\u7834\u89e3\u53cd\u722c\u83b7\u53d6\u7ade\u54c1\u6570\u636e<\/td>\n<td>\u6784\u6210\u4e0d\u6b63\u5f53\u7ade\u4e89<\/td>\n<td>\u5546\u4e1a\u7ade\u4e89\u722c\u866b\u98ce\u9669\u6781\u9ad8<\/td>\n<\/tr>\n<tr>\n<td>\u65b0\u6d6a\u8bc9\u8109\u8109\u6848<\/td>\n<td>2019<\/td>\n<td>\u8d85\u6388\u6743\u8303\u56f4\u6293\u53d6\u7528\u6237\u4fe1\u606f<\/td>\n<td>\u8d54\u507f&#043;\u505c\u6b62\u4fb5\u6743<\/td>\n<td>\u5f00\u653e\u5e73\u53f0\u4e0d\u7b49\u4e8e\u65e0\u9650\u6293\u53d6<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u751f\u4ea7\u8e29\u5751\u63d0\u9192&#xff1a;2025\u5e74\u6267\u6cd5\u8d8b\u52bf\u660e\u663e\u6536\u7d27\u3002\u5373\u4f7f\u6293\u53d6\u7684\u662f&#034;\u516c\u5f00&#034;\u6570\u636e&#xff0c;\u5982\u679c\u6d89\u53ca\u4e2a\u4eba\u4fe1\u606f&#xff08;\u624b\u673a\u53f7\u3001\u8eab\u4efd\u8bc1\u7b49&#xff09;&#xff0c;\u5373\u4f7f\u7f51\u7ad9\u672a\u505a\u8bbf\u95ee\u9650\u5236&#xff0c;\u4e5f\u53ef\u80fd\u89e6\u72af\u300a\u4e2a\u4eba\u4fe1\u606f\u4fdd\u62a4\u6cd5\u300b\u3002\u5efa\u8bae\u5728\u722c\u866b\u9879\u76ee\u4e2d\u5f15\u5165\u6cd5\u52a1\u5ba1\u6838\u73af\u8282\u3002<\/p>\n<hr \/>\n<h3>15. \u9a8c\u8bc1\u7801\u4e13\u9879\u7a81\u7834<\/h3>\n<h4>15.1 \u9a8c\u8bc1\u7801\u7c7b\u578b\u4e0e\u8bc6\u522b\u65b9\u6848<\/h4>\n<table>\n<tr>\u9a8c\u8bc1\u7801\u7c7b\u578b\u539f\u7406\u96be\u5ea6\u63a8\u8350\u65b9\u6848\u6210\u529f\u7387<\/tr>\n<tbody>\n<tr>\n<td>\u6570\u5b57\u5b57\u6bcd\u9a8c\u8bc1\u7801<\/td>\n<td>\u56fe\u7247&#043;\u566a\u70b9<\/td>\n<td>\u4e2d<\/td>\n<td>ddddocr\/Tesseract<\/td>\n<td>85-95%<\/td>\n<\/tr>\n<tr>\n<td>\u6ed1\u5757\u9a8c\u8bc1\u7801<\/td>\n<td>\u62fc\u56fe\u7f3a\u53e3\u5339\u914d<\/td>\n<td>\u9ad8<\/td>\n<td>OpenCV\u6a21\u677f\u5339\u914d<\/td>\n<td>90-98%<\/td>\n<\/tr>\n<tr>\n<td>\u70b9\u9009\u6587\u5b57\u9a8c\u8bc1\u7801<\/td>\n<td>OCR&#043;\u5750\u6807\u5b9a\u4f4d<\/td>\n<td>\u5f88\u9ad8<\/td>\n<td>ddddocr&#043;\u5750\u6807\u8ba1\u7b97<\/td>\n<td>70-85%<\/td>\n<\/tr>\n<tr>\n<td>\u70b9\u9009\u56fe\u6807\u9a8c\u8bc1\u7801<\/td>\n<td>\u56fe\u50cf\u8bc6\u522b&#043;\u5b9a\u4f4d<\/td>\n<td>\u5f88\u9ad8<\/td>\n<td>CNN\u6a21\u578b<\/td>\n<td>60-80%<\/td>\n<\/tr>\n<tr>\n<td>\u884c\u4e3a\u9a8c\u8bc1\u7801&#xff08;\u6781\u9a8c&#xff09;<\/td>\n<td>\u9f20\u6807\u8f68\u8ff9\u5206\u6790<\/td>\n<td>\u6781\u9ad8<\/td>\n<td>\u4e13\u4e1a\u6253\u7801\u5e73\u53f0<\/td>\n<td>90%\u4ee5\u4e0a<\/td>\n<\/tr>\n<tr>\n<td>reCAPTCHA v3<\/td>\n<td>\u884c\u4e3a\u8bc4\u5206<\/td>\n<td>\u6781\u9ad8<\/td>\n<td>\u771f\u4eba\u6253\u7801\/\u517bCookie<\/td>\n<td>80%\u4ee5\u4e0a<\/td>\n<\/tr>\n<tr>\n<td>hCaptcha<\/td>\n<td>\u56fe\u50cf\u5206\u7c7b<\/td>\n<td>\u5f88\u9ad8<\/td>\n<td>\u6253\u7801\u5e73\u53f0<\/td>\n<td>75-90%<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>15.2 \u6ed1\u5757\u9a8c\u8bc1\u7801\u8bc6\u522b<\/h4>\n<p><span class=\"token keyword\">import<\/span> cv2<br \/>\n<span class=\"token keyword\">import<\/span> numpy <span class=\"token keyword\">as<\/span> np<br \/>\n<span class=\"token keyword\">import<\/span> requests<br \/>\n<span class=\"token keyword\">import<\/span> random<br \/>\n<span class=\"token keyword\">import<\/span> time<\/p>\n<p><span class=\"token keyword\">def<\/span> <span class=\"token function\">find_slider_gap<\/span><span class=\"token punctuation\">(<\/span>bg_bytes<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">bytes<\/span><span class=\"token punctuation\">,<\/span> piece_bytes<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">bytes<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">int<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;<br \/>\n    \u4f7f\u7528OpenCV\u6a21\u677f\u5339\u914d\u627e\u5230\u6ed1\u5757\u7f3a\u53e3\u4f4d\u7f6e<br \/>\n    &#034;&#034;&#034;<\/span><br \/>\n    bg_array <span class=\"token operator\">&#061;<\/span> np<span class=\"token punctuation\">.<\/span>asarray<span class=\"token punctuation\">(<\/span><span class=\"token builtin\">bytearray<\/span><span class=\"token punctuation\">(<\/span>bg_bytes<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> dtype<span class=\"token operator\">&#061;<\/span>np<span class=\"token punctuation\">.<\/span>uint8<span class=\"token punctuation\">)<\/span><br \/>\n    piece_array <span class=\"token operator\">&#061;<\/span> np<span class=\"token punctuation\">.<\/span>asarray<span class=\"token punctuation\">(<\/span><span class=\"token builtin\">bytearray<\/span><span class=\"token punctuation\">(<\/span>piece_bytes<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> dtype<span class=\"token operator\">&#061;<\/span>np<span class=\"token punctuation\">.<\/span>uint8<span class=\"token punctuation\">)<\/span><\/p>\n<p>    bg_img <span class=\"token operator\">&#061;<\/span> cv2<span class=\"token punctuation\">.<\/span>imdecode<span class=\"token punctuation\">(<\/span>bg_array<span class=\"token punctuation\">,<\/span> cv2<span class=\"token punctuation\">.<\/span>IMREAD_COLOR<span class=\"token punctuation\">)<\/span><br \/>\n    piece_img <span class=\"token operator\">&#061;<\/span> cv2<span class=\"token punctuation\">.<\/span>imdecode<span class=\"token punctuation\">(<\/span>piece_array<span class=\"token punctuation\">,<\/span> cv2<span class=\"token punctuation\">.<\/span>IMREAD_COLOR<span class=\"token punctuation\">)<\/span><\/p>\n<p>    bg_gray <span class=\"token operator\">&#061;<\/span> cv2<span class=\"token punctuation\">.<\/span>cvtColor<span class=\"token punctuation\">(<\/span>bg_img<span class=\"token punctuation\">,<\/span> cv2<span class=\"token punctuation\">.<\/span>COLOR_BGR2GRAY<span class=\"token punctuation\">)<\/span><br \/>\n    piece_gray <span class=\"token operator\">&#061;<\/span> cv2<span class=\"token punctuation\">.<\/span>cvtColor<span class=\"token punctuation\">(<\/span>piece_img<span class=\"token punctuation\">,<\/span> cv2<span class=\"token punctuation\">.<\/span>COLOR_BGR2GRAY<span class=\"token punctuation\">)<\/span><\/p>\n<p>    bg_edge <span class=\"token operator\">&#061;<\/span> cv2<span class=\"token punctuation\">.<\/span>Canny<span class=\"token punctuation\">(<\/span>bg_gray<span class=\"token punctuation\">,<\/span> <span class=\"token number\">100<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">200<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    piece_edge <span class=\"token operator\">&#061;<\/span> cv2<span class=\"token punctuation\">.<\/span>Canny<span class=\"token punctuation\">(<\/span>piece_gray<span class=\"token punctuation\">,<\/span> <span class=\"token number\">100<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">200<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>    result <span class=\"token operator\">&#061;<\/span> cv2<span class=\"token punctuation\">.<\/span>matchTemplate<span class=\"token punctuation\">(<\/span>bg_edge<span class=\"token punctuation\">,<\/span> piece_edge<span class=\"token punctuation\">,<\/span> cv2<span class=\"token punctuation\">.<\/span>TM_CCOEFF_NORMED<span class=\"token punctuation\">)<\/span><br \/>\n    _<span class=\"token punctuation\">,<\/span> max_val<span class=\"token punctuation\">,<\/span> _<span class=\"token punctuation\">,<\/span> max_loc <span class=\"token operator\">&#061;<\/span> cv2<span class=\"token punctuation\">.<\/span>minMaxLoc<span class=\"token punctuation\">(<\/span>result<span class=\"token punctuation\">)<\/span><\/p>\n<p>    gap_x <span class=\"token operator\">&#061;<\/span> max_loc<span class=\"token punctuation\">[<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">]<\/span><br \/>\n    <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u7f3a\u53e3\u4f4d\u7f6e: x&#061;<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>gap_x<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">, \u5339\u914d\u7f6e\u4fe1\u5ea6: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>max_val<span class=\"token punctuation\">:<\/span><span class=\"token format-spec\">.3f<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n    <span class=\"token keyword\">return<\/span> gap_x<\/p>\n<p><span class=\"token keyword\">def<\/span> <span class=\"token function\">generate_track<\/span><span class=\"token punctuation\">(<\/span>distance<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">int<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">list<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;<br \/>\n    \u751f\u6210\u6a21\u62df\u4eba\u7c7b\u62d6\u62fd\u7684\u8f68\u8ff9&#xff08;\u52a0\u901f -&gt; \u51cf\u901f -&gt; \u5fae\u8c03&#xff09;<br \/>\n    &#034;&#034;&#034;<\/span><br \/>\n    track <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">]<\/span><br \/>\n    current <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0<\/span><br \/>\n    mid <span class=\"token operator\">&#061;<\/span> distance <span class=\"token operator\">*<\/span> <span class=\"token number\">4<\/span> <span class=\"token operator\">\/<\/span> <span class=\"token number\">5<\/span><br \/>\n    t <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0.2<\/span><br \/>\n    v <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">0<\/span><\/p>\n<p>    <span class=\"token keyword\">while<\/span> current <span class=\"token operator\">&lt;<\/span> distance<span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> current <span class=\"token operator\">&lt;<\/span> mid<span class=\"token punctuation\">:<\/span><br \/>\n            a <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">2<\/span> <span class=\"token operator\">&#043;<\/span> random<span class=\"token punctuation\">.<\/span>uniform<span class=\"token punctuation\">(<\/span><span class=\"token operator\">&#8211;<\/span><span class=\"token number\">0.5<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">0.5<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">else<\/span><span class=\"token punctuation\">:<\/span><br \/>\n            a <span class=\"token operator\">&#061;<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token number\">3<\/span> <span class=\"token operator\">&#043;<\/span> random<span class=\"token punctuation\">.<\/span>uniform<span class=\"token punctuation\">(<\/span><span class=\"token operator\">&#8211;<\/span><span class=\"token number\">0.5<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">0.5<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>        v0 <span class=\"token operator\">&#061;<\/span> v<br \/>\n        v <span class=\"token operator\">&#061;<\/span> v0 <span class=\"token operator\">&#043;<\/span> a <span class=\"token operator\">*<\/span> t<br \/>\n        move <span class=\"token operator\">&#061;<\/span> v0 <span class=\"token operator\">*<\/span> t <span class=\"token operator\">&#043;<\/span> <span class=\"token number\">0.5<\/span> <span class=\"token operator\">*<\/span> a <span class=\"token operator\">*<\/span> t <span class=\"token operator\">*<\/span> t<\/p>\n<p>        current <span class=\"token operator\">&#043;&#061;<\/span> move<br \/>\n        track<span class=\"token punctuation\">.<\/span>append<span class=\"token punctuation\">(<\/span><span class=\"token builtin\">round<\/span><span class=\"token punctuation\">(<\/span>move<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>    <span class=\"token comment\"># \u56de\u9000\u5fae\u8c03&#xff08;\u6a21\u62df\u4eba\u7c7b\u884c\u4e3a&#xff09;<\/span><br \/>\n    track<span class=\"token punctuation\">.<\/span>append<span class=\"token punctuation\">(<\/span><span class=\"token operator\">&#8211;<\/span>random<span class=\"token punctuation\">.<\/span>randint<span class=\"token punctuation\">(<\/span><span class=\"token number\">1<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">3<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    track<span class=\"token punctuation\">.<\/span>append<span class=\"token punctuation\">(<\/span>random<span class=\"token punctuation\">.<\/span>randint<span class=\"token punctuation\">(<\/span><span class=\"token number\">1<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">2<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>    <span class=\"token keyword\">return<\/span> track<\/p>\n<h4>15.3 \u6253\u7801\u5e73\u53f0\u96c6\u6210<\/h4>\n<p><span class=\"token keyword\">import<\/span> requests<br \/>\n<span class=\"token keyword\">import<\/span> base64<br \/>\n<span class=\"token keyword\">import<\/span> time<\/p>\n<p><span class=\"token keyword\">class<\/span> <span class=\"token class-name\">CaptchaSolver<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u9a8c\u8bc1\u7801\u8bc6\u522b\u670d\u52a1 &#8211; \u652f\u6301\u672c\u5730OCR\u548c\u6253\u7801\u5e73\u53f0&#034;&#034;&#034;<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">__init__<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> api_key<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">None<\/span><span class=\"token punctuation\">,<\/span> api_user<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token boolean\">None<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>api_key <span class=\"token operator\">&#061;<\/span> api_key<br \/>\n        self<span class=\"token punctuation\">.<\/span>api_user <span class=\"token operator\">&#061;<\/span> api_user<\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">solve_local<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> image_bytes<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">bytes<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u672c\u5730ddddocr\u8bc6\u522b&#034;&#034;&#034;<\/span><br \/>\n        <span class=\"token keyword\">import<\/span> ddddocr<br \/>\n        ocr <span class=\"token operator\">&#061;<\/span> ddddocr<span class=\"token punctuation\">.<\/span>DdddOcr<span class=\"token punctuation\">(<\/span>show_ad<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">False<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> ocr<span class=\"token punctuation\">.<\/span>classification<span class=\"token punctuation\">(<\/span>image_bytes<span class=\"token punctuation\">)<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">solve_remote<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> image_bytes<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">bytes<\/span><span class=\"token punctuation\">,<\/span> captcha_type<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token string\">&#034;1901&#034;<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u8fdc\u7a0b\u6253\u7801\u5e73\u53f0\u8bc6\u522b&#034;&#034;&#034;<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> <span class=\"token keyword\">not<\/span> self<span class=\"token punctuation\">.<\/span>api_key<span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">raise<\/span> ValueError<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;\u672a\u914d\u7f6e\u6253\u7801\u5e73\u53f0API Key&#034;<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>        img_base64 <span class=\"token operator\">&#061;<\/span> base64<span class=\"token punctuation\">.<\/span>b64encode<span class=\"token punctuation\">(<\/span>image_bytes<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>decode<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>        data <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token string\">&#034;user&#034;<\/span><span class=\"token punctuation\">:<\/span> self<span class=\"token punctuation\">.<\/span>api_user<span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token string\">&#034;pass2&#034;<\/span><span class=\"token punctuation\">:<\/span> self<span class=\"token punctuation\">.<\/span>api_key<span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token string\">&#034;softid&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;your_software_id&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token string\">&#034;codetype&#034;<\/span><span class=\"token punctuation\">:<\/span> captcha_type<span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token string\">&#034;file_base64&#034;<\/span><span class=\"token punctuation\">:<\/span> img_base64<span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><\/p>\n<p>        response <span class=\"token operator\">&#061;<\/span> requests<span class=\"token punctuation\">.<\/span>post<span class=\"token punctuation\">(<\/span><br \/>\n            <span class=\"token string\">&#034;http:\/\/upload.chaojiying.net\/Upload\/Processing.php&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            data<span class=\"token operator\">&#061;<\/span>data<span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token punctuation\">)<\/span><br \/>\n        result <span class=\"token operator\">&#061;<\/span> response<span class=\"token punctuation\">.<\/span>json<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>        <span class=\"token keyword\">if<\/span> result<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;err_no&#034;<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#061;&#061;<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">return<\/span> result<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;pic_str&#034;<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">else<\/span><span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">raise<\/span> Exception<span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u8bc6\u522b\u5931\u8d25: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>result<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><\/p>\n<hr \/>\n<h3>16. \u9ad8\u5e76\u53d1\u4e0e\u6027\u80fd\u4f18\u5316<\/h3>\n<h4>16.1 asyncio \u5f02\u6b65\u722c\u866b<\/h4>\n<p><span class=\"token keyword\">import<\/span> asyncio<br \/>\n<span class=\"token keyword\">import<\/span> aiohttp<br \/>\n<span class=\"token keyword\">import<\/span> time<br \/>\n<span class=\"token keyword\">from<\/span> typing <span class=\"token keyword\">import<\/span> List<span class=\"token punctuation\">,<\/span> Dict<\/p>\n<p><span class=\"token keyword\">class<\/span> <span class=\"token class-name\">AsyncCrawler<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u9ad8\u6027\u80fd\u5f02\u6b65\u722c\u866b&#034;&#034;&#034;<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">__init__<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> concurrency<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">int<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">50<\/span><span class=\"token punctuation\">,<\/span> timeout<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">int<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">30<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>concurrency <span class=\"token operator\">&#061;<\/span> concurrency<br \/>\n        self<span class=\"token punctuation\">.<\/span>timeout <span class=\"token operator\">&#061;<\/span> timeout<br \/>\n        self<span class=\"token punctuation\">.<\/span>semaphore <span class=\"token operator\">&#061;<\/span> asyncio<span class=\"token punctuation\">.<\/span>Semaphore<span class=\"token punctuation\">(<\/span>concurrency<span class=\"token punctuation\">)<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>results<span class=\"token punctuation\">:<\/span> List<span class=\"token punctuation\">[<\/span>Dict<span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">]<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>stats <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span><span class=\"token string\">&#034;success&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;failed&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;total_time&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token keyword\">async<\/span> <span class=\"token keyword\">def<\/span> <span class=\"token function\">fetch<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> session<span class=\"token punctuation\">:<\/span> aiohttp<span class=\"token punctuation\">.<\/span>ClientSession<span class=\"token punctuation\">,<\/span> url<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> Dict<span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u5355\u4e2a\u8bf7\u6c42&#034;&#034;&#034;<\/span><br \/>\n        <span class=\"token keyword\">async<\/span> <span class=\"token keyword\">with<\/span> self<span class=\"token punctuation\">.<\/span>semaphore<span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">try<\/span><span class=\"token punctuation\">:<\/span><br \/>\n                <span class=\"token keyword\">async<\/span> <span class=\"token keyword\">with<\/span> session<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><br \/>\n                    url<span class=\"token punctuation\">,<\/span><br \/>\n                    timeout<span class=\"token operator\">&#061;<\/span>aiohttp<span class=\"token punctuation\">.<\/span>ClientTimeout<span class=\"token punctuation\">(<\/span>total<span class=\"token operator\">&#061;<\/span>self<span class=\"token punctuation\">.<\/span>timeout<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                <span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">as<\/span> response<span class=\"token punctuation\">:<\/span><br \/>\n                    html <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">await<\/span> response<span class=\"token punctuation\">.<\/span>text<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n                    self<span class=\"token punctuation\">.<\/span>stats<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;success&#034;<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#043;&#061;<\/span> <span class=\"token number\">1<\/span><br \/>\n                    <span class=\"token keyword\">return<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n                        <span class=\"token string\">&#034;url&#034;<\/span><span class=\"token punctuation\">:<\/span> url<span class=\"token punctuation\">,<\/span><br \/>\n                        <span class=\"token string\">&#034;status&#034;<\/span><span class=\"token punctuation\">:<\/span> response<span class=\"token punctuation\">.<\/span>status<span class=\"token punctuation\">,<\/span><br \/>\n                        <span class=\"token string\">&#034;length&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">len<\/span><span class=\"token punctuation\">(<\/span>html<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                        <span class=\"token string\">&#034;html&#034;<\/span><span class=\"token punctuation\">:<\/span> html<span class=\"token punctuation\">,<\/span><br \/>\n                    <span class=\"token punctuation\">}<\/span><br \/>\n            <span class=\"token keyword\">except<\/span> Exception <span class=\"token keyword\">as<\/span> e<span class=\"token punctuation\">:<\/span><br \/>\n                self<span class=\"token punctuation\">.<\/span>stats<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;failed&#034;<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#043;&#061;<\/span> <span class=\"token number\">1<\/span><br \/>\n                <span class=\"token keyword\">return<\/span> <span class=\"token punctuation\">{<\/span><span class=\"token string\">&#034;url&#034;<\/span><span class=\"token punctuation\">:<\/span> url<span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;error&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">(<\/span>e<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token keyword\">async<\/span> <span class=\"token keyword\">def<\/span> <span class=\"token function\">crawl_all<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> urls<span class=\"token punctuation\">:<\/span> List<span class=\"token punctuation\">[<\/span><span class=\"token builtin\">str<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> List<span class=\"token punctuation\">[<\/span>Dict<span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u6279\u91cf\u722c\u53d6&#034;&#034;&#034;<\/span><br \/>\n        start_time <span class=\"token operator\">&#061;<\/span> time<span class=\"token punctuation\">.<\/span>time<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>        connector <span class=\"token operator\">&#061;<\/span> aiohttp<span class=\"token punctuation\">.<\/span>TCPConnector<span class=\"token punctuation\">(<\/span><br \/>\n            limit<span class=\"token operator\">&#061;<\/span>self<span class=\"token punctuation\">.<\/span>concurrency<span class=\"token punctuation\">,<\/span><br \/>\n            limit_per_host<span class=\"token operator\">&#061;<\/span><span class=\"token number\">10<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            ttl_dns_cache<span class=\"token operator\">&#061;<\/span><span class=\"token number\">300<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            enable_cleanup_closed<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">True<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token punctuation\">)<\/span><\/p>\n<p>        <span class=\"token keyword\">async<\/span> <span class=\"token keyword\">with<\/span> aiohttp<span class=\"token punctuation\">.<\/span>ClientSession<span class=\"token punctuation\">(<\/span><br \/>\n            connector<span class=\"token operator\">&#061;<\/span>connector<span class=\"token punctuation\">,<\/span><br \/>\n            headers<span class=\"token operator\">&#061;<\/span><span class=\"token punctuation\">{<\/span><br \/>\n                <span class=\"token string\">&#034;User-Agent&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;Mozilla\/5.0 (Windows NT 10.0; Win64; x64) &#034;<\/span><br \/>\n                              <span class=\"token string\">&#034;AppleWebKit\/537.36 Chrome\/131.0.0.0 Safari\/537.36&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">as<\/span> session<span class=\"token punctuation\">:<\/span><br \/>\n            tasks <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span>self<span class=\"token punctuation\">.<\/span>fetch<span class=\"token punctuation\">(<\/span>session<span class=\"token punctuation\">,<\/span> url<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">for<\/span> url <span class=\"token keyword\">in<\/span> urls<span class=\"token punctuation\">]<\/span><br \/>\n            self<span class=\"token punctuation\">.<\/span>results <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">await<\/span> asyncio<span class=\"token punctuation\">.<\/span>gather<span class=\"token punctuation\">(<\/span><span class=\"token operator\">*<\/span>tasks<span class=\"token punctuation\">)<\/span><\/p>\n<p>        self<span class=\"token punctuation\">.<\/span>stats<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;total_time&#034;<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#061;<\/span> time<span class=\"token punctuation\">.<\/span>time<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span> start_time<br \/>\n        <span class=\"token keyword\">return<\/span> self<span class=\"token punctuation\">.<\/span>results<\/p>\n<p><span class=\"token comment\"># \u6027\u80fd\u5bf9\u6bd4\u6d4b\u8bd5<\/span><br \/>\n<span class=\"token keyword\">async<\/span> <span class=\"token keyword\">def<\/span> <span class=\"token function\">benchmark<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    urls <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;https:\/\/httpbin.org\/get?id&#061;<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>i<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span> <span class=\"token keyword\">for<\/span> i <span class=\"token keyword\">in<\/span> <span class=\"token builtin\">range<\/span><span class=\"token punctuation\">(<\/span><span class=\"token number\">100<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">]<\/span><\/p>\n<p>    crawler <span class=\"token operator\">&#061;<\/span> AsyncCrawler<span class=\"token punctuation\">(<\/span>concurrency<span class=\"token operator\">&#061;<\/span><span class=\"token number\">50<\/span><span class=\"token punctuation\">)<\/span><br \/>\n    results <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">await<\/span> crawler<span class=\"token punctuation\">.<\/span>crawl_all<span class=\"token punctuation\">(<\/span>urls<span class=\"token punctuation\">)<\/span><\/p>\n<p>    <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u5f02\u6b65\u722c\u53d6\u7edf\u8ba1: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>crawler<span class=\"token punctuation\">.<\/span>stats<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n    <span class=\"token comment\"># \u9884\u671f: 100\u4e2a\u8bf7\u6c42\u7ea62-3\u79d2\u5b8c\u6210<\/span><\/p>\n<h4>16.2 \u751f\u4ea7\u73af\u5883\u90e8\u7f72<\/h4>\n<p><span class=\"token comment\"># docker-compose.yml &#8211; \u722c\u866b\u96c6\u7fa4\u90e8\u7f72<\/span><br \/>\n<span class=\"token key atrule\">version<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#039;3.8&#039;<\/span><\/p>\n<p><span class=\"token key atrule\">services<\/span><span class=\"token punctuation\">:<\/span><br \/>\n  <span class=\"token key atrule\">redis<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token key atrule\">image<\/span><span class=\"token punctuation\">:<\/span> redis<span class=\"token punctuation\">:<\/span>7<span class=\"token punctuation\">&#8211;<\/span>alpine<br \/>\n    <span class=\"token key atrule\">ports<\/span><span class=\"token punctuation\">:<\/span><br \/>\n      <span class=\"token punctuation\">&#8211;<\/span> <span class=\"token string\">&#034;6379:6379&#034;<\/span><br \/>\n    <span class=\"token key atrule\">command<\/span><span class=\"token punctuation\">:<\/span> redis<span class=\"token punctuation\">&#8211;<\/span>server <span class=\"token punctuation\">&#8211;<\/span><span class=\"token punctuation\">&#8211;<\/span>requirepass crawler_pass<br \/>\n    <span class=\"token key atrule\">volumes<\/span><span class=\"token punctuation\">:<\/span><br \/>\n      <span class=\"token punctuation\">&#8211;<\/span> redis_data<span class=\"token punctuation\">:<\/span>\/data<\/p>\n<p>  <span class=\"token key atrule\">crawler-worker-1<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token key atrule\">build<\/span><span class=\"token punctuation\">:<\/span> .\/crawler<br \/>\n    <span class=\"token key atrule\">environment<\/span><span class=\"token punctuation\">:<\/span><br \/>\n      <span class=\"token punctuation\">&#8211;<\/span> REDIS_URL&#061;redis<span class=\"token punctuation\">:<\/span>\/\/<span class=\"token punctuation\">:<\/span>crawler_pass&#064;redis<span class=\"token punctuation\">:<\/span>6379\/0<br \/>\n      <span class=\"token punctuation\">&#8211;<\/span> SPIDER_NAME&#061;books<br \/>\n      <span class=\"token punctuation\">&#8211;<\/span> CONCURRENT_REQUESTS&#061;32<br \/>\n    <span class=\"token key atrule\">depends_on<\/span><span class=\"token punctuation\">:<\/span><br \/>\n      <span class=\"token punctuation\">&#8211;<\/span> redis<br \/>\n    <span class=\"token key atrule\">deploy<\/span><span class=\"token punctuation\">:<\/span><br \/>\n      <span class=\"token key atrule\">resources<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token key atrule\">limits<\/span><span class=\"token punctuation\">:<\/span><br \/>\n          <span class=\"token key atrule\">cpus<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#039;2&#039;<\/span><br \/>\n          <span class=\"token key atrule\">memory<\/span><span class=\"token punctuation\">:<\/span> 2G<\/p>\n<p>  <span class=\"token key atrule\">crawler-worker-2<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token key atrule\">build<\/span><span class=\"token punctuation\">:<\/span> .\/crawler<br \/>\n    <span class=\"token key atrule\">environment<\/span><span class=\"token punctuation\">:<\/span><br \/>\n      <span class=\"token punctuation\">&#8211;<\/span> REDIS_URL&#061;redis<span class=\"token punctuation\">:<\/span>\/\/<span class=\"token punctuation\">:<\/span>crawler_pass&#064;redis<span class=\"token punctuation\">:<\/span>6379\/0<br \/>\n      <span class=\"token punctuation\">&#8211;<\/span> SPIDER_NAME&#061;books<br \/>\n      <span class=\"token punctuation\">&#8211;<\/span> CONCURRENT_REQUESTS&#061;32<br \/>\n    <span class=\"token key atrule\">depends_on<\/span><span class=\"token punctuation\">:<\/span><br \/>\n      <span class=\"token punctuation\">&#8211;<\/span> redis<\/p>\n<p>  <span class=\"token key atrule\">mongo<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token key atrule\">image<\/span><span class=\"token punctuation\">:<\/span> mongo<span class=\"token punctuation\">:<\/span><span class=\"token number\">7<\/span><br \/>\n    <span class=\"token key atrule\">ports<\/span><span class=\"token punctuation\">:<\/span><br \/>\n      <span class=\"token punctuation\">&#8211;<\/span> <span class=\"token string\">&#034;27017:27017&#034;<\/span><br \/>\n    <span class=\"token key atrule\">environment<\/span><span class=\"token punctuation\">:<\/span><br \/>\n      <span class=\"token punctuation\">&#8211;<\/span> MONGO_INITDB_ROOT_USERNAME&#061;crawler<br \/>\n      <span class=\"token punctuation\">&#8211;<\/span> MONGO_INITDB_ROOT_PASSWORD&#061;mongo_pass_2025<br \/>\n    <span class=\"token key atrule\">volumes<\/span><span class=\"token punctuation\">:<\/span><br \/>\n      <span class=\"token punctuation\">&#8211;<\/span> mongo_data<span class=\"token punctuation\">:<\/span>\/data\/db<\/p>\n<p>  <span class=\"token key atrule\">proxy-api<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token key atrule\">build<\/span><span class=\"token punctuation\">:<\/span> .\/proxy_pool<br \/>\n    <span class=\"token key atrule\">ports<\/span><span class=\"token punctuation\">:<\/span><br \/>\n      <span class=\"token punctuation\">&#8211;<\/span> <span class=\"token string\">&#034;8080:8080&#034;<\/span><br \/>\n    <span class=\"token key atrule\">depends_on<\/span><span class=\"token punctuation\">:<\/span><br \/>\n      <span class=\"token punctuation\">&#8211;<\/span> redis<\/p>\n<p><span class=\"token key atrule\">volumes<\/span><span class=\"token punctuation\">:<\/span><br \/>\n  <span class=\"token key atrule\">redis_data<\/span><span class=\"token punctuation\">:<\/span><br \/>\n  <span class=\"token key atrule\">mongo_data<\/span><span class=\"token punctuation\">:<\/span><\/p>\n<p>; supervisord.conf &#8211; \u8fdb\u7a0b\u7ba1\u7406\u914d\u7f6e<br \/>\n[program:crawler-worker]<br \/>\ncommand&#061;scrapy crawl %(ENV_SPIDER_NAME)s<br \/>\ndirectory&#061;\/app<br \/>\nuser&#061;crawler<br \/>\nautostart&#061;true<br \/>\nautorestart&#061;true<br \/>\nstartsecs&#061;10<br \/>\nstopwaitsecs&#061;60<br \/>\nredirect_stderr&#061;true<br \/>\nstdout_logfile&#061;\/var\/log\/crawler\/%(program_name)s.log<br \/>\nstdout_logfile_maxbytes&#061;50MB<br \/>\nstdout_logfile_backups&#061;5<br \/>\nenvironment&#061;<br \/>\n    PYTHONUNBUFFERED&#061;&#034;1&#034;,<br \/>\n    SCRAPY_SETTINGS_MODULE&#061;&#034;crawler.settings&#034;<\/p>\n<p>[program:proxy-pool]<br \/>\ncommand&#061;uvicorn proxy_pool:app &#8211;host 0.0.0.0 &#8211;port 8080<br \/>\ndirectory&#061;\/app<br \/>\nuser&#061;crawler<br \/>\nautostart&#061;true<br \/>\nautorestart&#061;true<br \/>\nredirect_stderr&#061;true<br \/>\nstdout_logfile&#061;\/var\/log\/crawler\/proxy_pool.log<\/p>\n<p>\u9762\u8bd5\u52a0\u5206\u63d0\u793a&#xff1a;\u751f\u4ea7\u73af\u5883\u722c\u866b\u90e8\u7f72\u7684\u4e09\u4ef6\u5957\u662f Docker&#xff08;\u73af\u5883\u9694\u79bb&#xff09;&#043; Supervisor&#xff08;\u8fdb\u7a0b\u5b88\u62a4&#xff09;&#043; Prometheus&#043;Grafana&#xff08;\u76d1\u63a7\u544a\u8b66&#xff09;\u3002\u5173\u952e\u76d1\u63a7\u6307\u6807\u5305\u62ec&#xff1a;\u8bf7\u6c42\u6210\u529f\u7387\u3001\u54cd\u5e94\u65f6\u95f4P99\u3001\u961f\u5217\u79ef\u538b\u91cf\u3001\u5185\u5b58\u4f7f\u7528\u7387\u3002<\/p>\n<hr \/>\n<h3>17. \u5b9e\u6218\u9879\u76ee<\/h3>\n<h4>17.1 \u7535\u5546\u5546\u54c1\u6570\u636e\u91c7\u96c6&#xff08;\u542b\u53cd\u53cd\u722c&#xff09;<\/h4>\n<p><span class=\"token triple-quoted-string string\">&#034;&#034;&#034;<br \/>\n\u7535\u5546\u5546\u54c1\u6570\u636e\u91c7\u96c6\u5b8c\u6574\u793a\u4f8b<br \/>\n\u6280\u672f\u6808: curl_cffi &#043; lxml &#043; MongoDB &#043; \u4ee3\u7406\u6c60<br \/>\n&#034;&#034;&#034;<\/span><br \/>\n<span class=\"token keyword\">import<\/span> json<br \/>\n<span class=\"token keyword\">import<\/span> time<br \/>\n<span class=\"token keyword\">import<\/span> random<br \/>\n<span class=\"token keyword\">from<\/span> curl_cffi <span class=\"token keyword\">import<\/span> requests <span class=\"token keyword\">as<\/span> cffi_requests<br \/>\n<span class=\"token keyword\">from<\/span> lxml <span class=\"token keyword\">import<\/span> etree<br \/>\n<span class=\"token keyword\">from<\/span> urllib<span class=\"token punctuation\">.<\/span>parse <span class=\"token keyword\">import<\/span> urljoin<br \/>\n<span class=\"token keyword\">import<\/span> pymongo<\/p>\n<p><span class=\"token keyword\">class<\/span> <span class=\"token class-name\">EcommerceCrawler<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u7535\u5546\u722c\u866b &#8211; \u5e26\u5b8c\u6574\u53cd\u53cd\u722c\u7b56\u7565&#034;&#034;&#034;<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">__init__<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token comment\"># 1. \u521d\u59cb\u5316Session&#xff08;TLS\u6307\u7eb9\u4f2a\u88c5&#xff09;<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>session <span class=\"token operator\">&#061;<\/span> cffi_requests<span class=\"token punctuation\">.<\/span>Session<span class=\"token punctuation\">(<\/span><br \/>\n            impersonate<span class=\"token operator\">&#061;<\/span><span class=\"token string\">&#034;chrome136&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            verify<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">True<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token punctuation\">)<\/span><\/p>\n<p>        <span class=\"token comment\"># 2. MongoDB\u5b58\u50a8<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>mongo <span class=\"token operator\">&#061;<\/span> pymongo<span class=\"token punctuation\">.<\/span>MongoClient<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;mongodb:\/\/localhost:27017&#034;<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>db <span class=\"token operator\">&#061;<\/span> self<span class=\"token punctuation\">.<\/span>mongo<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;ecommerce&#034;<\/span><span class=\"token punctuation\">]<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>collection <span class=\"token operator\">&#061;<\/span> self<span class=\"token punctuation\">.<\/span>db<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;products&#034;<\/span><span class=\"token punctuation\">]<\/span><\/p>\n<p>        <span class=\"token comment\"># 3. \u4ee3\u7406\u6c60<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>proxies <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span><br \/>\n            <span class=\"token string\">&#034;http:\/\/proxy1.example.com:8080&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token string\">&#034;http:\/\/proxy2.example.com:8080&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token punctuation\">]<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">get_headers<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">dict<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u751f\u6210\u968f\u673aHeaders&#034;&#034;&#034;<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token string\">&#034;User-Agent&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;Mozilla\/5.0 (Windows NT 10.0; Win64; x64) &#034;<\/span><br \/>\n                          <span class=\"token string\">&#034;AppleWebKit\/537.36 Chrome\/131.0.0.0 Safari\/537.36&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token string\">&#034;Accept&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;text\/html,application\/xhtml&#043;xml,*\/*;q&#061;0.8&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token string\">&#034;Accept-Language&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;zh-CN,zh;q&#061;0.9,en;q&#061;0.8&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token string\">&#034;Referer&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;https:\/\/www.example.com\/&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">fetch_page<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> url<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">,<\/span> max_retries<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">int<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">3<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u5e26\u91cd\u8bd5\u7684\u9875\u9762\u83b7\u53d6&#034;&#034;&#034;<\/span><br \/>\n        <span class=\"token keyword\">for<\/span> attempt <span class=\"token keyword\">in<\/span> <span class=\"token builtin\">range<\/span><span class=\"token punctuation\">(<\/span>max_retries<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">try<\/span><span class=\"token punctuation\">:<\/span><br \/>\n                proxy <span class=\"token operator\">&#061;<\/span> random<span class=\"token punctuation\">.<\/span>choice<span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">.<\/span>proxies<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">if<\/span> self<span class=\"token punctuation\">.<\/span>proxies <span class=\"token keyword\">else<\/span> <span class=\"token boolean\">None<\/span><br \/>\n                response <span class=\"token operator\">&#061;<\/span> self<span class=\"token punctuation\">.<\/span>session<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><br \/>\n                    url<span class=\"token punctuation\">,<\/span><br \/>\n                    headers<span class=\"token operator\">&#061;<\/span>self<span class=\"token punctuation\">.<\/span>get_headers<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                    proxies<span class=\"token operator\">&#061;<\/span><span class=\"token punctuation\">{<\/span><span class=\"token string\">&#034;http&#034;<\/span><span class=\"token punctuation\">:<\/span> proxy<span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;https&#034;<\/span><span class=\"token punctuation\">:<\/span> proxy<span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">if<\/span> proxy <span class=\"token keyword\">else<\/span> <span class=\"token boolean\">None<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                    timeout<span class=\"token operator\">&#061;<\/span><span class=\"token number\">30<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                <span class=\"token punctuation\">)<\/span><\/p>\n<p>                <span class=\"token keyword\">if<\/span> response<span class=\"token punctuation\">.<\/span>status_code <span class=\"token operator\">&#061;&#061;<\/span> <span class=\"token number\">200<\/span><span class=\"token punctuation\">:<\/span><br \/>\n                    <span class=\"token keyword\">return<\/span> response<span class=\"token punctuation\">.<\/span>text<br \/>\n                <span class=\"token keyword\">elif<\/span> response<span class=\"token punctuation\">.<\/span>status_code <span class=\"token operator\">&#061;&#061;<\/span> <span class=\"token number\">429<\/span><span class=\"token punctuation\">:<\/span><br \/>\n                    wait_time <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">(<\/span>attempt <span class=\"token operator\">&#043;<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">*<\/span> <span class=\"token number\">30<\/span><br \/>\n                    <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u88ab\u9650\u6d41&#xff0c;\u7b49\u5f85<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>wait_time<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">\u79d2&#8230;&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n                    time<span class=\"token punctuation\">.<\/span>sleep<span class=\"token punctuation\">(<\/span>wait_time<span class=\"token punctuation\">)<\/span><\/p>\n<p>            <span class=\"token keyword\">except<\/span> Exception <span class=\"token keyword\">as<\/span> e<span class=\"token punctuation\">:<\/span><br \/>\n                <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u8bf7\u6c42\u5931\u8d25(\u7b2c<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>attempt<span class=\"token operator\">&#043;<\/span><span class=\"token number\">1<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">\u6b21): <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>e<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n                time<span class=\"token punctuation\">.<\/span>sleep<span class=\"token punctuation\">(<\/span><span class=\"token number\">5<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>        <span class=\"token keyword\">return<\/span> <span class=\"token boolean\">None<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">parse_product<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> html<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">,<\/span> url<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">dict<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u89e3\u6790\u5546\u54c1\u9875\u9762&#034;&#034;&#034;<\/span><br \/>\n        tree <span class=\"token operator\">&#061;<\/span> etree<span class=\"token punctuation\">.<\/span>HTML<span class=\"token punctuation\">(<\/span>html<span class=\"token punctuation\">)<\/span><\/p>\n<p>        product <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token string\">&#034;url&#034;<\/span><span class=\"token punctuation\">:<\/span> url<span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token string\">&#034;title&#034;<\/span><span class=\"token punctuation\">:<\/span> self<span class=\"token punctuation\">.<\/span>_safe_text<span class=\"token punctuation\">(<\/span>tree<span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#039;\/\/h1[&#064;class&#061;&#034;title&#034;]\/text()&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token string\">&#034;price&#034;<\/span><span class=\"token punctuation\">:<\/span> self<span class=\"token punctuation\">.<\/span>_safe_text<span class=\"token punctuation\">(<\/span>tree<span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#039;\/\/span[&#064;class&#061;&#034;price&#034;]\/text()&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token string\">&#034;sales&#034;<\/span><span class=\"token punctuation\">:<\/span> self<span class=\"token punctuation\">.<\/span>_safe_text<span class=\"token punctuation\">(<\/span>tree<span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#039;\/\/span[&#064;class&#061;&#034;sales-count&#034;]\/text()&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token string\">&#034;shop_name&#034;<\/span><span class=\"token punctuation\">:<\/span> self<span class=\"token punctuation\">.<\/span>_safe_text<span class=\"token punctuation\">(<\/span>tree<span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#039;\/\/a[&#064;class&#061;&#034;shop-name&#034;]\/text()&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token string\">&#034;crawled_at&#034;<\/span><span class=\"token punctuation\">:<\/span> time<span class=\"token punctuation\">.<\/span>strftime<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;%Y-%m-%d %H:%M:%S&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><\/p>\n<p>        <span class=\"token keyword\">return<\/span> <span class=\"token punctuation\">{<\/span>k<span class=\"token punctuation\">:<\/span> v <span class=\"token keyword\">for<\/span> k<span class=\"token punctuation\">,<\/span> v <span class=\"token keyword\">in<\/span> product<span class=\"token punctuation\">.<\/span>items<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">if<\/span> v<span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token decorator annotation punctuation\">&#064;staticmethod<\/span><br \/>\n    <span class=\"token keyword\">def<\/span> <span class=\"token function\">_safe_text<\/span><span class=\"token punctuation\">(<\/span>tree<span class=\"token punctuation\">,<\/span> xpath<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        result <span class=\"token operator\">&#061;<\/span> tree<span class=\"token punctuation\">.<\/span>xpath<span class=\"token punctuation\">(<\/span>xpath<span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">return<\/span> result<span class=\"token punctuation\">[<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">.<\/span>strip<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">if<\/span> result <span class=\"token keyword\">else<\/span> <span class=\"token string\">&#034;&#034;<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">save_product<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> product<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">dict<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u4fdd\u5b58\u5546\u54c1\u6570\u636e&#xff08;\u53bb\u91cd\u66f4\u65b0&#xff09;&#034;&#034;&#034;<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>collection<span class=\"token punctuation\">.<\/span>update_one<span class=\"token punctuation\">(<\/span><br \/>\n            <span class=\"token punctuation\">{<\/span><span class=\"token string\">&#034;url&#034;<\/span><span class=\"token punctuation\">:<\/span> product<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;url&#034;<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token punctuation\">{<\/span><span class=\"token string\">&#034;$set&#034;<\/span><span class=\"token punctuation\">:<\/span> product<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            upsert<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">True<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token comment\"># \u4f7f\u7528\u793a\u4f8b<\/span><br \/>\n<span class=\"token comment\"># crawler &#061; EcommerceCrawler()<\/span><\/p>\n<h4>17.2 \u65b0\u95fb\u805a\u5408\u722c\u866b<\/h4>\n<p><span class=\"token keyword\">import<\/span> asyncio<br \/>\n<span class=\"token keyword\">import<\/span> httpx<br \/>\n<span class=\"token keyword\">from<\/span> lxml <span class=\"token keyword\">import<\/span> etree<br \/>\n<span class=\"token keyword\">from<\/span> datetime <span class=\"token keyword\">import<\/span> datetime<br \/>\n<span class=\"token keyword\">from<\/span> typing <span class=\"token keyword\">import<\/span> List<span class=\"token punctuation\">,<\/span> Dict<\/p>\n<p><span class=\"token keyword\">class<\/span> <span class=\"token class-name\">NewsAggregator<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u591a\u6e90\u65b0\u95fb\u805a\u5408\u722c\u866b&#034;&#034;&#034;<\/span><\/p>\n<p>    SOURCES <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n        <span class=\"token string\">&#034;\u6f8e\u6e43\u65b0\u95fb&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token string\">&#034;url&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;https:\/\/www.thepaper.cn\/&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token string\">&#034;title_xpath&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#039;\/\/h2\/a\/text()&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token string\">&#034;link_xpath&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#039;\/\/h2\/a\/&#064;href&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token string\">&#034;36\u6c2a&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token string\">&#034;url&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;https:\/\/36kr.com\/newsflashes&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token string\">&#034;title_xpath&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#039;\/\/a[&#064;class&#061;&#034;item-title&#034;]\/text()&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token string\">&#034;link_xpath&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#039;\/\/a[&#064;class&#061;&#034;item-title&#034;]\/&#064;href&#039;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    <span class=\"token punctuation\">}<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">__init__<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>results<span class=\"token punctuation\">:<\/span> List<span class=\"token punctuation\">[<\/span>Dict<span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">]<\/span><\/p>\n<p>    <span class=\"token keyword\">async<\/span> <span class=\"token keyword\">def<\/span> <span class=\"token function\">crawl_source<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> client<span class=\"token punctuation\">:<\/span> httpx<span class=\"token punctuation\">.<\/span>AsyncClient<span class=\"token punctuation\">,<\/span><br \/>\n                           name<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">,<\/span> config<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">dict<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> List<span class=\"token punctuation\">[<\/span>Dict<span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u722c\u53d6\u5355\u4e2a\u65b0\u95fb\u6e90&#034;&#034;&#034;<\/span><br \/>\n        <span class=\"token keyword\">try<\/span><span class=\"token punctuation\">:<\/span><br \/>\n            response <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">await<\/span> client<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><br \/>\n                config<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;url&#034;<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">,<\/span> timeout<span class=\"token operator\">&#061;<\/span><span class=\"token number\">15<\/span><span class=\"token punctuation\">,<\/span> follow_redirects<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">True<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            <span class=\"token punctuation\">)<\/span><\/p>\n<p>            tree <span class=\"token operator\">&#061;<\/span> etree<span class=\"token punctuation\">.<\/span>HTML<span class=\"token punctuation\">(<\/span>response<span class=\"token punctuation\">.<\/span>text<span class=\"token punctuation\">)<\/span><br \/>\n            items <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">]<\/span><\/p>\n<p>            titles <span class=\"token operator\">&#061;<\/span> tree<span class=\"token punctuation\">.<\/span>xpath<span class=\"token punctuation\">(<\/span>config<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;title_xpath&#034;<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">)<\/span><br \/>\n            links <span class=\"token operator\">&#061;<\/span> tree<span class=\"token punctuation\">.<\/span>xpath<span class=\"token punctuation\">(<\/span>config<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;link_xpath&#034;<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>            <span class=\"token keyword\">for<\/span> title<span class=\"token punctuation\">,<\/span> link <span class=\"token keyword\">in<\/span> <span class=\"token builtin\">zip<\/span><span class=\"token punctuation\">(<\/span>titles<span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">:<\/span><span class=\"token number\">20<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">,<\/span> links<span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">:<\/span><span class=\"token number\">20<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n                items<span class=\"token punctuation\">.<\/span>append<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span><br \/>\n                    <span class=\"token string\">&#034;source&#034;<\/span><span class=\"token punctuation\">:<\/span> name<span class=\"token punctuation\">,<\/span><br \/>\n                    <span class=\"token string\">&#034;title&#034;<\/span><span class=\"token punctuation\">:<\/span> title<span class=\"token punctuation\">.<\/span>strip<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                    <span class=\"token string\">&#034;url&#034;<\/span><span class=\"token punctuation\">:<\/span> link <span class=\"token keyword\">if<\/span> link<span class=\"token punctuation\">.<\/span>startswith<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#034;http&#034;<\/span><span class=\"token punctuation\">)<\/span><br \/>\n                           <span class=\"token keyword\">else<\/span> <span class=\"token string-interpolation\"><span class=\"token string\">f&#034;<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>config<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#039;url&#039;<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">.<\/span>rstrip<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;\/&#039;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>link<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">,<\/span><br \/>\n                    <span class=\"token string\">&#034;crawled_at&#034;<\/span><span class=\"token punctuation\">:<\/span> datetime<span class=\"token punctuation\">.<\/span>now<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>isoformat<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>            <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;[<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>name<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">] \u83b7\u53d6\u5230 <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span><span class=\"token builtin\">len<\/span><span class=\"token punctuation\">(<\/span>items<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\"> \u6761\u65b0\u95fb&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n            <span class=\"token keyword\">return<\/span> items<\/p>\n<p>        <span class=\"token keyword\">except<\/span> Exception <span class=\"token keyword\">as<\/span> e<span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;[<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>name<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">] \u722c\u53d6\u5931\u8d25: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>e<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n            <span class=\"token keyword\">return<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">]<\/span><\/p>\n<p>    <span class=\"token keyword\">async<\/span> <span class=\"token keyword\">def<\/span> <span class=\"token function\">crawl_all<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> List<span class=\"token punctuation\">[<\/span>Dict<span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u5e76\u53d1\u722c\u53d6\u6240\u6709\u6e90&#034;&#034;&#034;<\/span><br \/>\n        <span class=\"token keyword\">async<\/span> <span class=\"token keyword\">with<\/span> httpx<span class=\"token punctuation\">.<\/span>AsyncClient<span class=\"token punctuation\">(<\/span><br \/>\n            headers<span class=\"token operator\">&#061;<\/span><span class=\"token punctuation\">{<\/span><span class=\"token string\">&#034;User-Agent&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;Mozilla\/5.0 Chrome\/131.0.0.0&#034;<\/span><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            http2<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">True<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">as<\/span> client<span class=\"token punctuation\">:<\/span><br \/>\n            tasks <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span><br \/>\n                self<span class=\"token punctuation\">.<\/span>crawl_source<span class=\"token punctuation\">(<\/span>client<span class=\"token punctuation\">,<\/span> name<span class=\"token punctuation\">,<\/span> config<span class=\"token punctuation\">)<\/span><br \/>\n                <span class=\"token keyword\">for<\/span> name<span class=\"token punctuation\">,<\/span> config <span class=\"token keyword\">in<\/span> self<span class=\"token punctuation\">.<\/span>SOURCES<span class=\"token punctuation\">.<\/span>items<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n            <span class=\"token punctuation\">]<\/span><br \/>\n            results <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">await<\/span> asyncio<span class=\"token punctuation\">.<\/span>gather<span class=\"token punctuation\">(<\/span><span class=\"token operator\">*<\/span>tasks<span class=\"token punctuation\">)<\/span><br \/>\n            self<span class=\"token punctuation\">.<\/span>results <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span>item <span class=\"token keyword\">for<\/span> sublist <span class=\"token keyword\">in<\/span> results <span class=\"token keyword\">for<\/span> item <span class=\"token keyword\">in<\/span> sublist<span class=\"token punctuation\">]<\/span><br \/>\n            <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u603b\u8ba1\u83b7\u53d6 <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span><span class=\"token builtin\">len<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">.<\/span>results<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\"> \u6761\u65b0\u95fb&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n            <span class=\"token keyword\">return<\/span> self<span class=\"token punctuation\">.<\/span>results<\/p>\n<h4>17.3 \u5b66\u672f\u8bba\u6587\u6279\u91cf\u4e0b\u8f7d<\/h4>\n<p><span class=\"token keyword\">import<\/span> requests<br \/>\n<span class=\"token keyword\">import<\/span> os<br \/>\n<span class=\"token keyword\">import<\/span> time<br \/>\n<span class=\"token keyword\">import<\/span> hashlib<br \/>\n<span class=\"token keyword\">from<\/span> lxml <span class=\"token keyword\">import<\/span> etree<\/p>\n<p><span class=\"token keyword\">class<\/span> <span class=\"token class-name\">PaperDownloader<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u5b66\u672f\u8bba\u6587\u4e0b\u8f7d\u5668&#xff08;\u4ee5ArXiv\u4e3a\u4f8b&#xff09;&#034;&#034;&#034;<\/span><\/p>\n<p>    BASE_URL <span class=\"token operator\">&#061;<\/span> <span class=\"token string\">&#034;https:\/\/arxiv.org&#034;<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">__init__<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> download_dir<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token string\">&#034;.\/papers&#034;<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>download_dir <span class=\"token operator\">&#061;<\/span> download_dir<br \/>\n        os<span class=\"token punctuation\">.<\/span>makedirs<span class=\"token punctuation\">(<\/span>download_dir<span class=\"token punctuation\">,<\/span> exist_ok<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">True<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>session <span class=\"token operator\">&#061;<\/span> requests<span class=\"token punctuation\">.<\/span>Session<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        self<span class=\"token punctuation\">.<\/span>session<span class=\"token punctuation\">.<\/span>headers<span class=\"token punctuation\">.<\/span>update<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span><br \/>\n            <span class=\"token string\">&#034;User-Agent&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;Mozilla\/5.0 Research Bot\/1.0&#034;<\/span><br \/>\n        <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">search_papers<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> query<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">,<\/span> max_results<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">int<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">50<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">list<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u641c\u7d22\u8bba\u6587&#034;&#034;&#034;<\/span><br \/>\n        params <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">{<\/span><span class=\"token string\">&#034;query&#034;<\/span><span class=\"token punctuation\">:<\/span> query<span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;searchtype&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;all&#034;<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;start&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">}<\/span><br \/>\n        papers <span class=\"token operator\">&#061;<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">]<\/span><\/p>\n<p>        <span class=\"token keyword\">while<\/span> <span class=\"token builtin\">len<\/span><span class=\"token punctuation\">(<\/span>papers<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&lt;<\/span> max_results<span class=\"token punctuation\">:<\/span><br \/>\n            response <span class=\"token operator\">&#061;<\/span> self<span class=\"token punctuation\">.<\/span>session<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><br \/>\n                <span class=\"token string-interpolation\"><span class=\"token string\">f&#034;<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>self<span class=\"token punctuation\">.<\/span>BASE_URL<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">\/search\/&#034;<\/span><\/span><span class=\"token punctuation\">,<\/span> params<span class=\"token operator\">&#061;<\/span>params<br \/>\n            <span class=\"token punctuation\">)<\/span><br \/>\n            tree <span class=\"token operator\">&#061;<\/span> etree<span class=\"token punctuation\">.<\/span>HTML<span class=\"token punctuation\">(<\/span>response<span class=\"token punctuation\">.<\/span>text<span class=\"token punctuation\">)<\/span><br \/>\n            items <span class=\"token operator\">&#061;<\/span> tree<span class=\"token punctuation\">.<\/span>xpath<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;\/\/li[&#064;class&#061;&#034;arxiv-result&#034;]&#039;<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>            <span class=\"token keyword\">for<\/span> item <span class=\"token keyword\">in<\/span> items<span class=\"token punctuation\">:<\/span><br \/>\n                title <span class=\"token operator\">&#061;<\/span> item<span class=\"token punctuation\">.<\/span>xpath<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;.\/\/p[&#064;class&#061;&#034;title&#034;]\/text()&#039;<\/span><span class=\"token punctuation\">)<\/span><br \/>\n                pdf_link <span class=\"token operator\">&#061;<\/span> item<span class=\"token punctuation\">.<\/span>xpath<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;.\/\/a[contains(text(),&#034;PDF&#034;)]\/&#064;href&#039;<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>                <span class=\"token keyword\">if<\/span> title <span class=\"token keyword\">and<\/span> pdf_link<span class=\"token punctuation\">:<\/span><br \/>\n                    papers<span class=\"token punctuation\">.<\/span>append<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">{<\/span><br \/>\n                        <span class=\"token string\">&#034;title&#034;<\/span><span class=\"token punctuation\">:<\/span> title<span class=\"token punctuation\">[<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">.<\/span>strip<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                        <span class=\"token string\">&#034;pdf_url&#034;<\/span><span class=\"token punctuation\">:<\/span> pdf_link<span class=\"token punctuation\">[<\/span><span class=\"token number\">0<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token keyword\">if<\/span> pdf_link <span class=\"token keyword\">else<\/span> <span class=\"token string\">&#034;&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n                    <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>            next_page <span class=\"token operator\">&#061;<\/span> tree<span class=\"token punctuation\">.<\/span>xpath<span class=\"token punctuation\">(<\/span><span class=\"token string\">&#039;\/\/a[&#064;class&#061;&#034;next&#034;]\/text()&#039;<\/span><span class=\"token punctuation\">)<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> <span class=\"token keyword\">not<\/span> next_page <span class=\"token keyword\">or<\/span> <span class=\"token builtin\">len<\/span><span class=\"token punctuation\">(<\/span>papers<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&gt;&#061;<\/span> max_results<span class=\"token punctuation\">:<\/span><br \/>\n                <span class=\"token keyword\">break<\/span><br \/>\n            params<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;start&#034;<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#043;&#061;<\/span> <span class=\"token number\">25<\/span><br \/>\n            time<span class=\"token punctuation\">.<\/span>sleep<span class=\"token punctuation\">(<\/span><span class=\"token number\">3<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>        <span class=\"token keyword\">return<\/span> papers<span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">:<\/span>max_results<span class=\"token punctuation\">]<\/span><\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">download_pdf<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> pdf_url<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u4e0b\u8f7dPDF\u6587\u4ef6&#034;&#034;&#034;<\/span><br \/>\n        filename <span class=\"token operator\">&#061;<\/span> hashlib<span class=\"token punctuation\">.<\/span>md5<span class=\"token punctuation\">(<\/span>pdf_url<span class=\"token punctuation\">.<\/span>encode<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span>hexdigest<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">:<\/span><span class=\"token number\">12<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token operator\">&#043;<\/span> <span class=\"token string\">&#034;.pdf&#034;<\/span><br \/>\n        filepath <span class=\"token operator\">&#061;<\/span> os<span class=\"token punctuation\">.<\/span>path<span class=\"token punctuation\">.<\/span>join<span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">.<\/span>download_dir<span class=\"token punctuation\">,<\/span> filename<span class=\"token punctuation\">)<\/span><\/p>\n<p>        <span class=\"token keyword\">if<\/span> os<span class=\"token punctuation\">.<\/span>path<span class=\"token punctuation\">.<\/span>exists<span class=\"token punctuation\">(<\/span>filepath<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">return<\/span> filepath<\/p>\n<p>        response <span class=\"token operator\">&#061;<\/span> self<span class=\"token punctuation\">.<\/span>session<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span>pdf_url<span class=\"token punctuation\">,<\/span> timeout<span class=\"token operator\">&#061;<\/span><span class=\"token number\">60<\/span><span class=\"token punctuation\">,<\/span> stream<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">True<\/span><span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">if<\/span> response<span class=\"token punctuation\">.<\/span>status_code <span class=\"token operator\">&#061;&#061;<\/span> <span class=\"token number\">200<\/span><span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">with<\/span> <span class=\"token builtin\">open<\/span><span class=\"token punctuation\">(<\/span>filepath<span class=\"token punctuation\">,<\/span> <span class=\"token string\">&#034;wb&#034;<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">as<\/span> f<span class=\"token punctuation\">:<\/span><br \/>\n                <span class=\"token keyword\">for<\/span> chunk <span class=\"token keyword\">in<\/span> response<span class=\"token punctuation\">.<\/span>iter_content<span class=\"token punctuation\">(<\/span>chunk_size<span class=\"token operator\">&#061;<\/span><span class=\"token number\">8192<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n                    f<span class=\"token punctuation\">.<\/span>write<span class=\"token punctuation\">(<\/span>chunk<span class=\"token punctuation\">)<\/span><br \/>\n            <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u5df2\u4e0b\u8f7d: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>filepath<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><\/p>\n<p>        <span class=\"token keyword\">return<\/span> filepath<\/p>\n<p>    <span class=\"token keyword\">def<\/span> <span class=\"token function\">batch_download<\/span><span class=\"token punctuation\">(<\/span>self<span class=\"token punctuation\">,<\/span> query<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">,<\/span> max_papers<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">int<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">20<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n        <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u6279\u91cf\u641c\u7d22\u5e76\u4e0b\u8f7d&#034;&#034;&#034;<\/span><br \/>\n        <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u641c\u7d22\u8bba\u6587: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>query<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n        papers <span class=\"token operator\">&#061;<\/span> self<span class=\"token punctuation\">.<\/span>search_papers<span class=\"token punctuation\">(<\/span>query<span class=\"token punctuation\">,<\/span> max_papers<span class=\"token punctuation\">)<\/span><\/p>\n<p>        <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u627e\u5230 <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span><span class=\"token builtin\">len<\/span><span class=\"token punctuation\">(<\/span>papers<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\"> \u7bc7\u8bba\u6587&#xff0c;\u5f00\u59cb\u4e0b\u8f7d&#8230;&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n        <span class=\"token keyword\">for<\/span> i<span class=\"token punctuation\">,<\/span> paper <span class=\"token keyword\">in<\/span> <span class=\"token builtin\">enumerate<\/span><span class=\"token punctuation\">(<\/span>papers<span class=\"token punctuation\">,<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;[<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>i<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">\/<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span><span class=\"token builtin\">len<\/span><span class=\"token punctuation\">(<\/span>papers<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">] <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>paper<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#039;title&#039;<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">:<\/span><span class=\"token format-spec\">60]<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#8230;&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n            <span class=\"token keyword\">if<\/span> paper<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;pdf_url&#034;<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">:<\/span><br \/>\n                self<span class=\"token punctuation\">.<\/span>download_pdf<span class=\"token punctuation\">(<\/span>paper<span class=\"token punctuation\">[<\/span><span class=\"token string\">&#034;pdf_url&#034;<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">)<\/span><br \/>\n            time<span class=\"token punctuation\">.<\/span>sleep<span class=\"token punctuation\">(<\/span><span class=\"token number\">3<\/span><span class=\"token punctuation\">)<\/span><\/p>\n<h3>18. 2025-2026\u722c\u866b\u65b0\u6280\u672f\u8d8b\u52bf<\/h3>\n<h4>18.1 AI\u8f85\u52a9\u9006\u5411&#xff08;LLM\u5206\u6790JS&#xff09;<\/h4>\n<p>2025\u5e74\u51fa\u73b0\u4e86\u4e00\u4e2a\u9769\u547d\u6027\u7684\u8d8b\u52bf&#xff1a;\u4f7f\u7528\u5927\u8bed\u8a00\u6a21\u578b\u8f85\u52a9JS\u9006\u5411\u5206\u6790\u3002<\/p>\n<p><span class=\"token triple-quoted-string string\">&#034;&#034;&#034;<br \/>\n\u4f7f\u7528LLM\u8f85\u52a9JS\u9006\u5411\u5206\u6790\u7684\u5de5\u4f5c\u6d41<br \/>\n\u5c06\u6df7\u6dc6\u7684JS\u4ee3\u7801\u7247\u6bb5\u53d1\u9001\u7ed9LLM&#xff0c;\u83b7\u53d6\u7b97\u6cd5\u8fd8\u539f\u5efa\u8bae<br \/>\n&#034;&#034;&#034;<\/span><\/p>\n<p><span class=\"token keyword\">def<\/span> <span class=\"token function\">prepare_js_for_analysis<\/span><span class=\"token punctuation\">(<\/span>js_code<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">,<\/span> max_tokens<span class=\"token punctuation\">:<\/span> <span class=\"token builtin\">int<\/span> <span class=\"token operator\">&#061;<\/span> <span class=\"token number\">4000<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&#8211;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token builtin\">str<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u9884\u5904\u7406JS\u4ee3\u7801&#xff0c;\u6784\u5efa\u53d1\u9001\u7ed9LLM\u7684prompt&#034;&#034;&#034;<\/span><br \/>\n    prompt <span class=\"token operator\">&#061;<\/span> <span class=\"token string-interpolation\"><span class=\"token string\">f&#034;&#034;&#034;<br \/>\n\u4f60\u662f\u4e00\u4e2aJavaScript\u9006\u5411\u5de5\u7a0b\u4e13\u5bb6\u3002\u8bf7\u5206\u6790\u4ee5\u4e0b\u6df7\u6dc6\u7684JS\u4ee3\u7801&#xff0c;<br \/>\n\u8fd8\u539f\u5176\u6838\u5fc3\u7b97\u6cd5\u903b\u8f91&#xff0c;\u5e76\u7ed9\u51faPython\u5b9e\u73b0\u3002<\/p>\n<p>\u8981\u6c42&#xff1a;<br \/>\n1. \u8bc6\u522b\u4f7f\u7528\u7684\u52a0\u5bc6\u7b97\u6cd5&#xff08;MD5\/SHA\/AES\/RSA\u7b49&#xff09;<br \/>\n2. \u627e\u51fa\u5173\u952e\u53c2\u6570\u548c\u5bc6\u94a5<br \/>\n3. \u7ed9\u51fa\u7b49\u4ef7\u7684Python\u4ee3\u7801<\/p>\n<p>\u6df7\u6dc6JS\u4ee3\u7801&#xff1a;<br \/>\n<\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>js_code<span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">:<\/span><span class=\"token format-spec\">max_tokens]<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\"><br \/>\n&#034;&#034;&#034;<\/span><\/span><br \/>\n    <span class=\"token keyword\">return<\/span> prompt<\/p>\n<p><span class=\"token comment\"># \u5de5\u4f5c\u6d41\u7a0b\u793a\u4f8b:<\/span><br \/>\n<span class=\"token comment\"># 1. \u901a\u8fc7DevTools\u5b9a\u4f4d\u5230\u52a0\u5bc6\u51fd\u6570<\/span><br \/>\n<span class=\"token comment\"># 2. \u590d\u5236\u6df7\u6dc6\u540e\u7684\u51fd\u6570\u4ee3\u7801<\/span><br \/>\n<span class=\"token comment\"># 3. \u6784\u9020prompt\u53d1\u9001\u7ed9LLM<\/span><br \/>\n<span class=\"token comment\"># 4. \u83b7\u53d6LLM\u8fd4\u56de\u7684Python\u5b9e\u73b0<\/span><br \/>\n<span class=\"token comment\"># 5. \u672c\u5730\u9a8c\u8bc1\u5e76\u8c03\u8bd5<\/span><\/p>\n<h4>18.2 \u65e0\u6d4f\u89c8\u5668\u722c\u866b\u65b0\u6280\u672f<\/h4>\n<table>\n<tr>\u5de5\u5177\u539f\u7406\u4f18\u52bf\u5c40\u9650<\/tr>\n<tbody>\n<tr>\n<td>curl_cffi<\/td>\n<td>TLS\u6307\u7eb9\u6a21\u62df<\/td>\n<td>\u65e0\u9700\u6d4f\u89c8\u5668&#xff0c;\u901f\u5ea6\u5feb<\/td>\n<td>\u4e0d\u6267\u884cJS<\/td>\n<\/tr>\n<tr>\n<td>tls-client<\/td>\n<td>Go\u5e95\u5c42TLS\u6a21\u62df<\/td>\n<td>\u8de8\u5e73\u53f0&#xff0c;\u9ad8\u6027\u80fd<\/td>\n<td>\u4e0d\u6267\u884cJS<\/td>\n<\/tr>\n<tr>\n<td>nodriver<\/td>\n<td>CDP\u534f\u8bae\u7cbe\u7b80\u7248<\/td>\n<td>\u6bd4Selenium\u8f7b\u91cf<\/td>\n<td>\u4ecd\u9700Chromium<\/td>\n<\/tr>\n<tr>\n<td>botasaurus<\/td>\n<td>\u9ad8\u7ea7\u722c\u866b\u6846\u67b6<\/td>\n<td>\u81ea\u52a8\u53cd\u53cd\u722c<\/td>\n<td>\u76f8\u5bf9\u8f83\u65b0<\/td>\n<\/tr>\n<tr>\n<td>crawl4ai<\/td>\n<td>AI\u9a71\u52a8\u722c\u866b<\/td>\n<td>\u667a\u80fd\u5185\u5bb9\u63d0\u53d6<\/td>\n<td>\u9700\u8981GPU<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h4>18.3 tls-client&#xff1a;Go\u5e95\u5c42TLS\u6a21\u62df<\/h4>\n<p><span class=\"token comment\"># pip install tls-client<\/span><br \/>\n<span class=\"token keyword\">import<\/span> tls_client<\/p>\n<p><span class=\"token comment\"># \u6a21\u62df\u6d4f\u89c8\u5668TLS\u6307\u7eb9<\/span><br \/>\nsession <span class=\"token operator\">&#061;<\/span> tls_client<span class=\"token punctuation\">.<\/span>Session<span class=\"token punctuation\">(<\/span><br \/>\n    client_identifier<span class=\"token operator\">&#061;<\/span><span class=\"token string\">&#034;chrome_131&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    random_tls_extension_order<span class=\"token operator\">&#061;<\/span><span class=\"token boolean\">True<\/span><span class=\"token punctuation\">,<\/span><br \/>\n<span class=\"token punctuation\">)<\/span><\/p>\n<p>response <span class=\"token operator\">&#061;<\/span> session<span class=\"token punctuation\">.<\/span>get<span class=\"token punctuation\">(<\/span><br \/>\n    <span class=\"token string\">&#034;https:\/\/target-website.com\/api\/data&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    headers<span class=\"token operator\">&#061;<\/span><span class=\"token punctuation\">{<\/span><span class=\"token string\">&#034;User-Agent&#034;<\/span><span class=\"token punctuation\">:<\/span> <span class=\"token string\">&#034;Mozilla\/5.0 Chrome\/131.0.0.0&#034;<\/span><span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span><br \/>\n    proxy_url<span class=\"token operator\">&#061;<\/span><span class=\"token string\">&#034;http:\/\/proxy:8080&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n<span class=\"token punctuation\">)<\/span><\/p>\n<p><span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;Status: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span>response<span class=\"token punctuation\">.<\/span>status_code<span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><\/p>\n<h4>18.4 crawl4ai&#xff1a;AI\u9a71\u52a8\u7684\u722c\u866b<\/h4>\n<p><span class=\"token comment\"># pip install crawl4ai<\/span><br \/>\n<span class=\"token comment\"># crawl4ai \u662f2025\u5e74\u65b0\u5174\u7684AI\u9a71\u52a8\u722c\u866b\u6846\u67b6<\/span><\/p>\n<p><span class=\"token keyword\">from<\/span> crawl4ai <span class=\"token keyword\">import<\/span> AsyncWebCrawler<br \/>\n<span class=\"token keyword\">from<\/span> crawl4ai<span class=\"token punctuation\">.<\/span>extraction <span class=\"token keyword\">import<\/span> LLMExtraction<br \/>\n<span class=\"token keyword\">import<\/span> asyncio<\/p>\n<p><span class=\"token keyword\">async<\/span> <span class=\"token keyword\">def<\/span> <span class=\"token function\">ai_crawl<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">:<\/span><br \/>\n    <span class=\"token triple-quoted-string string\">&#034;&#034;&#034;\u4f7f\u7528AI\u8fdb\u884c\u667a\u80fd\u5185\u5bb9\u63d0\u53d6&#034;&#034;&#034;<\/span><br \/>\n    <span class=\"token keyword\">async<\/span> <span class=\"token keyword\">with<\/span> AsyncWebCrawler<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">as<\/span> crawler<span class=\"token punctuation\">:<\/span><br \/>\n        result <span class=\"token operator\">&#061;<\/span> <span class=\"token keyword\">await<\/span> crawler<span class=\"token punctuation\">.<\/span>arun<span class=\"token punctuation\">(<\/span><br \/>\n            url<span class=\"token operator\">&#061;<\/span><span class=\"token string\">&#034;https:\/\/example.com\/products&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n            wait_until<span class=\"token operator\">&#061;<\/span><span class=\"token string\">&#034;networkidle&#034;<\/span><span class=\"token punctuation\">,<\/span><br \/>\n        <span class=\"token punctuation\">)<\/span><\/p>\n<p>        <span class=\"token keyword\">if<\/span> result<span class=\"token punctuation\">.<\/span>success<span class=\"token punctuation\">:<\/span><br \/>\n            <span class=\"token keyword\">print<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string-interpolation\"><span class=\"token string\">f&#034;\u9875\u9762\u957f\u5ea6: <\/span><span class=\"token interpolation\"><span class=\"token punctuation\">{<\/span><span class=\"token builtin\">len<\/span><span class=\"token punctuation\">(<\/span>result<span class=\"token punctuation\">.<\/span>html<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">}<\/span><\/span><span class=\"token string\">&#034;<\/span><\/span><span class=\"token punctuation\">)<\/span><br \/>\n            <span class=\"token comment\"># \u53ef\u8fdb\u4e00\u6b65\u4f7f\u7528LLM\u8fdb\u884c\u7ed3\u6784\u5316\u63d0\u53d6<\/span><\/p>\n<p><span class=\"token comment\"># asyncio.run(ai_crawl())<\/span><\/p>\n<h4>18.5 \u6280\u672f\u8d8b\u52bf\u603b\u7ed3<\/h4>\n<p>\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510<br \/>\n\u2502            2025-2026 \u722c\u866b\u6280\u672f\u6f14\u8fdb\u8def\u7ebf                               \u2502<br \/>\n\u251c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524<br \/>\n\u2502                                                                  \u2502<br \/>\n\u2502  \u6d4f\u89c8\u5668\u81ea\u52a8\u5316\u6f14\u8fdb:                                                \u2502<br \/>\n\u2502  Selenium &#8211;&gt; Playwright\u4e3b\u6d41 &#8211;&gt; AI Agent\u722c\u866b                    \u2502<br \/>\n\u2502                                                                  \u2502<br \/>\n\u2502  \u53cd\u68c0\u6d4b\u6280\u672f\u6f14\u8fdb:                                                  \u2502<br \/>\n\u2502  \u624b\u52a8\u9006\u5411JS &#8211;&gt; curl_cffi\u6d41\u884c &#8211;&gt; AI\u8f85\u52a9\u9006\u5411                     \u2502<br \/>\n\u2502                                                                  \u2502<br \/>\n\u2502  \u67b6\u6784\u6f14\u8fdb:                                                       \u2502<br \/>\n\u2502  \u5355\u673a\u90e8\u7f72 &#8211;&gt; \u5206\u5e03\u5f0f\u96c6\u7fa4 &#8211;&gt; \u8fb9\u7f18\u8ba1\u7b97\u5bf9\u6297                        \u2502<br \/>\n\u2502                                                                  \u2502<br \/>\n\u2502  \u5173\u952e\u53d8\u5316:                                                        \u2502<br \/>\n\u2502  &#8211; TLS\u6307\u7eb9\u68c0\u6d4b\u6210\u4e3a\u4e3b\u6d41\u53cd\u722c\u624b\u6bb5                                    \u2502<br \/>\n\u2502  &#8211; LLM\u88ab\u7528\u4e8eJS\u9006\u5411\u5206\u6790\u548c\u667a\u80fd\u5185\u5bb9\u63d0\u53d6                              \u2502<br \/>\n\u2502  &#8211; \u65e0\u5934\u6d4f\u89c8\u5668\u68c0\u6d4b\u4e0e\u53cd\u68c0\u6d4b\u7684\u535a\u5f08\u6301\u7eed\u5347\u7ea7                            \u2502<br \/>\n\u2502  &#8211; \u6d4f\u89c8\u5668\u6307\u7eb9\u68c0\u6d4b\u7ef4\u5ea6\u6269\u5c55\u5230WebGL\/Audio\/Fonts                      \u2502<br \/>\n\u2502  &#8211; \u5408\u89c4\u8981\u6c42\u65e5\u76ca\u4e25\u683c&#xff0c;\u722c\u866b\u6cd5\u5f8b\u98ce\u9669\u4e0a\u5347                              \u2502<br \/>\n\u2502                                                                  \u2502<br \/>\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518<\/p>\n<h3>\u9644\u5f55&#xff1a;\u722c\u866b\u6280\u672f\u9009\u578b\u901f\u67e5\u8868<\/h3>\n<table>\n<tr>\u573a\u666f\u63a8\u8350\u6280\u672f\u6808\u7406\u7531<\/tr>\n<tbody>\n<tr>\n<td>\u7b80\u5355\u9759\u6001\u9875\u9762<\/td>\n<td>requests &#043; lxml<\/td>\n<td>\u5feb\u901f\u5f00\u53d1&#xff0c;\u6027\u80fd\u591f\u7528<\/td>\n<\/tr>\n<tr>\n<td>\u4e2d\u7b49\u89c4\u6a21\u9879\u76ee<\/td>\n<td>Scrapy &#043; MongoDB<\/td>\n<td>\u6846\u67b6\u6210\u719f&#xff0c;\u6269\u5c55\u6027\u597d<\/td>\n<\/tr>\n<tr>\n<td>\u53cdTLS\u68c0\u6d4b<\/td>\n<td>curl_cffi<\/td>\n<td>\u4e00\u884c\u4ee3\u7801\u6a21\u62df\u6d4f\u89c8\u5668\u6307\u7eb9<\/td>\n<\/tr>\n<tr>\n<td>SPA\u52a8\u6001\u9875\u9762<\/td>\n<td>Playwright<\/td>\n<td>\u81ea\u52a8\u7b49\u5f85&#xff0c;API\u62e6\u622a<\/td>\n<\/tr>\n<tr>\n<td>\u5927\u89c4\u6a21\u5206\u5e03\u5f0f<\/td>\n<td>Scrapy-Redis &#043; Kafka<\/td>\n<td>\u9ad8\u541e\u5410&#xff0c;\u53ef\u6269\u5c55<\/td>\n<\/tr>\n<tr>\n<td>APP\u6570\u636e<\/td>\n<td>mitmproxy &#043; Frida<\/td>\n<td>\u6293\u5305&#043;Hook<\/td>\n<\/tr>\n<tr>\n<td>\u9a8c\u8bc1\u7801\u7a81\u7834<\/td>\n<td>ddddocr &#043; \u6253\u7801\u5e73\u53f0<\/td>\n<td>\u672c\u5730\u8bc6\u522b&#043;\u8fdc\u7a0b\u515c\u5e95<\/td>\n<\/tr>\n<tr>\n<td>JS\u9006\u5411<\/td>\n<td>DevTools &#043; LLM\u8f85\u52a9<\/td>\n<td>\u4f20\u7edf\u65b9\u6cd5&#043;AI\u52a0\u901f<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u514d\u8d23\u58f0\u660e&#xff1a;\u672c\u6307\u5357\u4e2d\u7684\u6240\u6709\u6280\u672f\u548c\u4ee3\u7801\u4ec5\u4f9b\u5b66\u4e60\u548c\u7814\u7a76\u76ee\u7684\u4f7f\u7528\u3002\u4f7f\u7528\u722c\u866b\u6280\u672f\u65f6&#xff0c;\u8bf7\u52a1\u5fc5\u9075\u5b88\u76f8\u5173\u6cd5\u5f8b\u6cd5\u89c4\u3001\u7f51\u7ad9\u670d\u52a1\u6761\u6b3e\u548c robots.txt \u534f\u8bae\u3002\u4efb\u4f55\u56e0\u4e0d\u5f53\u4f7f\u7528\u672c\u6307\u5357\u5185\u5bb9\u800c\u4ea7\u751f\u7684\u6cd5\u5f8b\u95ee\u9898&#xff0c;\u7531\u4f7f\u7528\u8005\u81ea\u884c\u627f\u62c5\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Python \u722c\u866b\u6280\u672f\u5168\u6808\u6307\u5357 \u9762\u5411\u8bfb\u8005&#xff1a;\u6709\u4e00\u5b9a Python \u57fa\u7840\u7684\u6570\u636e\u5f00\u53d1\u5de5\u7a0b\u5e08 \u7248\u672c\u8bf4\u660e&#xff1a;\u878d\u5165 2025-2026 \u5e74\u6700\u65b0\u6280\u672f\u52a8\u6001&#xff0c;\u8986\u76d6 curl_cffi\u3001Playwright \u65b0\u7248\u3001AI \u8f85\u52a9\u9006\u5411\u7b49\u524d\u6cbf\u5185\u5bb9 \u76ee\u5f55<br \/>\n\u722c\u866b\u5168\u666f\u6982\u8ff0HTTP\u534f\u8bae\u4e0e\u7f51\u7edc\u57fa\u7840Python\u722c\u866b\u57fa\u7840\u5e93HTML\u89e3\u6790\u4e0e\u6570\u636e\u63d0\u53d6\u4e3b\u6d41\u722c\u866b\u6846\u67b6\u8be6\u89e3\u52a8\u6001\u9875\u9762\u722c\u53d6\u53cd\u722c\u866b\u6280\u672f\u5168\u89e3\u53cd\u53cd\u722c\u866b\u5b9e\u6218\u9006\u5411\u5de5\u7a0b\u57fa\u7840JS\u9006\u5411\u6df1\u5ea6\u5b9e\u6218APP\u722c\u866b\u4e0e\u6293\u5305\u5206\u5e03\u5f0f\u722c\u866b\u67b6\u6784\u6570\u636e\u5b58\u50a8\u4e0e\u6e05\u6d17\u6cd5\u5f8b\u5408\u89c4<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[10187,81,190,677],"topic":[],"class_list":["post-97387","post","type-post","status-publish","format-standard","hentry","category-server","tag-codingplan","tag-python","tag-190","tag-677"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v20.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Python \u722c\u866b\u6280\u672f\u5168\u6808\u6307\u5357 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.wsisp.com\/helps\/97387.html\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Python \u722c\u866b\u6280\u672f\u5168\u6808\u6307\u5357 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"og:description\" content=\"Python \u722c\u866b\u6280\u672f\u5168\u6808\u6307\u5357 \u9762\u5411\u8bfb\u8005&#xff1a;\u6709\u4e00\u5b9a Python \u57fa\u7840\u7684\u6570\u636e\u5f00\u53d1\u5de5\u7a0b\u5e08 \u7248\u672c\u8bf4\u660e&#xff1a;\u878d\u5165 2025-2026 \u5e74\u6700\u65b0\u6280\u672f\u52a8\u6001&#xff0c;\u8986\u76d6 curl_cffi\u3001Playwright \u65b0\u7248\u3001AI \u8f85\u52a9\u9006\u5411\u7b49\u524d\u6cbf\u5185\u5bb9 \u76ee\u5f55 \u722c\u866b\u5168\u666f\u6982\u8ff0HTTP\u534f\u8bae\u4e0e\u7f51\u7edc\u57fa\u7840Python\u722c\u866b\u57fa\u7840\u5e93HTML\u89e3\u6790\u4e0e\u6570\u636e\u63d0\u53d6\u4e3b\u6d41\u722c\u866b\u6846\u67b6\u8be6\u89e3\u52a8\u6001\u9875\u9762\u722c\u53d6\u53cd\u722c\u866b\u6280\u672f\u5168\u89e3\u53cd\u53cd\u722c\u866b\u5b9e\u6218\u9006\u5411\u5de5\u7a0b\u57fa\u7840JS\u9006\u5411\u6df1\u5ea6\u5b9e\u6218APP\u722c\u866b\u4e0e\u6293\u5305\u5206\u5e03\u5f0f\u722c\u866b\u67b6\u6784\u6570\u636e\u5b58\u50a8\u4e0e\u6e05\u6d17\u6cd5\u5f8b\u5408\u89c4\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.wsisp.com\/helps\/97387.html\" \/>\n<meta property=\"og:site_name\" content=\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"article:published_time\" content=\"2026-08-29T03:40:45+00:00\" \/>\n<meta name=\"author\" content=\"admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"29 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/97387.html\",\"url\":\"https:\/\/www.wsisp.com\/helps\/97387.html\",\"name\":\"Python \u722c\u866b\u6280\u672f\u5168\u6808\u6307\u5357 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"isPartOf\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\"},\"datePublished\":\"2026-08-29T03:40:45+00:00\",\"dateModified\":\"2026-08-29T03:40:45+00:00\",\"author\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/97387.html#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.wsisp.com\/helps\/97387.html\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/97387.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.wsisp.com\/helps\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Python \u722c\u866b\u6280\u672f\u5168\u6808\u6307\u5357\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\",\"url\":\"https:\/\/www.wsisp.com\/helps\/\",\"name\":\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"description\":\"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\",\"name\":\"admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"contentUrl\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"caption\":\"admin\"},\"sameAs\":[\"http:\/\/wp.wsisp.com\"],\"url\":\"https:\/\/www.wsisp.com\/helps\/author\/admin\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Python \u722c\u866b\u6280\u672f\u5168\u6808\u6307\u5357 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.wsisp.com\/helps\/97387.html","og_locale":"zh_CN","og_type":"article","og_title":"Python \u722c\u866b\u6280\u672f\u5168\u6808\u6307\u5357 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","og_description":"Python \u722c\u866b\u6280\u672f\u5168\u6808\u6307\u5357 \u9762\u5411\u8bfb\u8005&#xff1a;\u6709\u4e00\u5b9a Python \u57fa\u7840\u7684\u6570\u636e\u5f00\u53d1\u5de5\u7a0b\u5e08 \u7248\u672c\u8bf4\u660e&#xff1a;\u878d\u5165 2025-2026 \u5e74\u6700\u65b0\u6280\u672f\u52a8\u6001&#xff0c;\u8986\u76d6 curl_cffi\u3001Playwright \u65b0\u7248\u3001AI \u8f85\u52a9\u9006\u5411\u7b49\u524d\u6cbf\u5185\u5bb9 \u76ee\u5f55 \u722c\u866b\u5168\u666f\u6982\u8ff0HTTP\u534f\u8bae\u4e0e\u7f51\u7edc\u57fa\u7840Python\u722c\u866b\u57fa\u7840\u5e93HTML\u89e3\u6790\u4e0e\u6570\u636e\u63d0\u53d6\u4e3b\u6d41\u722c\u866b\u6846\u67b6\u8be6\u89e3\u52a8\u6001\u9875\u9762\u722c\u53d6\u53cd\u722c\u866b\u6280\u672f\u5168\u89e3\u53cd\u53cd\u722c\u866b\u5b9e\u6218\u9006\u5411\u5de5\u7a0b\u57fa\u7840JS\u9006\u5411\u6df1\u5ea6\u5b9e\u6218APP\u722c\u866b\u4e0e\u6293\u5305\u5206\u5e03\u5f0f\u722c\u866b\u67b6\u6784\u6570\u636e\u5b58\u50a8\u4e0e\u6e05\u6d17\u6cd5\u5f8b\u5408\u89c4","og_url":"https:\/\/www.wsisp.com\/helps\/97387.html","og_site_name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","article_published_time":"2026-08-29T03:40:45+00:00","author":"admin","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"admin","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"29 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.wsisp.com\/helps\/97387.html","url":"https:\/\/www.wsisp.com\/helps\/97387.html","name":"Python \u722c\u866b\u6280\u672f\u5168\u6808\u6307\u5357 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","isPartOf":{"@id":"https:\/\/www.wsisp.com\/helps\/#website"},"datePublished":"2026-08-29T03:40:45+00:00","dateModified":"2026-08-29T03:40:45+00:00","author":{"@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41"},"breadcrumb":{"@id":"https:\/\/www.wsisp.com\/helps\/97387.html#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.wsisp.com\/helps\/97387.html"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.wsisp.com\/helps\/97387.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.wsisp.com\/helps"},{"@type":"ListItem","position":2,"name":"Python \u722c\u866b\u6280\u672f\u5168\u6808\u6307\u5357"}]},{"@type":"WebSite","@id":"https:\/\/www.wsisp.com\/helps\/#website","url":"https:\/\/www.wsisp.com\/helps\/","name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","description":"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41","name":"admin","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/","url":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","contentUrl":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","caption":"admin"},"sameAs":["http:\/\/wp.wsisp.com"],"url":"https:\/\/www.wsisp.com\/helps\/author\/admin"}]}},"_links":{"self":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/97387","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/comments?post=97387"}],"version-history":[{"count":0,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/97387\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media?parent=97387"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/categories?post=97387"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/tags?post=97387"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/topic?post=97387"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}