<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>爬虫 on farmer3-c Blog</title><link>https://farmer3-c.github.io/tags/%E7%88%AC%E8%99%AB/</link><description>Recent content in 爬虫 on farmer3-c Blog</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Tue, 20 Jan 2026 22:18:28 +0800</lastBuildDate><atom:link href="https://farmer3-c.github.io/tags/%E7%88%AC%E8%99%AB/index.xml" rel="self" type="application/rss+xml"/><item><title>爬取中国工商银行人民币即期外汇牌价数据</title><link>https://farmer3-c.github.io/posts/post-2026-01-20/</link><pubDate>Tue, 20 Jan 2026 22:18:28 +0800</pubDate><guid>https://farmer3-c.github.io/posts/post-2026-01-20/</guid><description>&lt;h2 id="爬取单日数据"&gt;爬取单日数据&lt;/h2&gt;
&lt;h4 id="前期准备"&gt;前期准备&lt;/h4&gt;
&lt;p&gt;我要爬取的网站是&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;https://www.icbc.com.cn/ICBC/%e9%87%91%e8%9e%8d%e4%bf%a1%e6%81%af/%e8%a1%8c%e6%83%85%e6%95%b0%e6%8d%ae/%e4%ba%ba%e6%b0%91%e5%b8%81%e5%8d%b3%e6%9c%9f%e5%a4%96%e6%b1%87%e7%89%8c%e4%bb%b7/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;数据是这样的：币种、银行买入价、银行卖出价、发布时间&lt;/p&gt;
&lt;p&gt;&lt;img alt="1" loading="lazy" src="https://farmer3-c.github.io/img/in-post/python_img/%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE%202026-01-25%20114748.png"&gt;&lt;/p&gt;
&lt;p&gt;环境：python 3.12.2&lt;/p&gt;
&lt;h4 id="寻找网络请求接口"&gt;寻找网络请求接口&lt;/h4&gt;
&lt;p&gt;在浏览器中按F12打开开发者工具，然后点击Network，勾选 Preserve log&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;选择 Fetch / XHR&lt;/p&gt;
&lt;p&gt;&lt;code&gt;XMLHttpRequest (XHR)&lt;/code&gt; 和 &lt;code&gt;Fetch API&lt;/code&gt;都是网页向服务器发起 HTTP 请求的机制。Fetch API 是一种现代的、基于 Promise 的替代方案，用于取代老旧的、基于回调的 XHR，它提供了更简洁的语法和更适合现代网页开发的功能。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;手动操作页面：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt; 选择一个日期（比如 2021-01-25）
点击【查询】
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Network 列表里 新出现的 POST 请求&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://farmer3-c.github.io/img/in-post/python_img/%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE%202026-01-25%20161550.png"&gt;
可以确定工商银行新版 PAPI 的“历史外汇牌价接口”：&lt;code&gt;POST https://papi.icbc.com.cn/exchanges/ns/history&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="如何使用接口"&gt;如何使用接口&lt;/h4&gt;
&lt;h6 id="请求方式"&gt;请求方式&lt;/h6&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;POST&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Content-Type: application/json&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h6 id="请求体"&gt;请求体&lt;/h6&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;date&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2021-01-13&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;currType&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;serverType&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;👉 这个接口不支持“时间区间”&lt;/p&gt;
&lt;p&gt;👉 需要一天一天请求&lt;/p&gt;
&lt;h4 id="编写代码"&gt;编写代码&lt;/h4&gt;
&lt;details&gt;
&lt;summary&gt;点击展开/折叠代码&lt;/summary&gt;
&lt;div markdown="1"&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://papi.icbc.com.cn/exchanges/ns/history&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;User-Agent&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Mozilla/5.0 (Windows NT 10.0; Win64; x64)&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Content-Type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;application/json&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Origin&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://www.icbc.com.cn&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Referer&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://www.icbc.com.cn/ICBC/&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;9&lt;/span&gt;&lt;span class="si"&gt;%87%&lt;/span&gt;&lt;span class="s2"&gt;91&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;8&lt;/span&gt;&lt;span class="si"&gt;%9E&lt;/span&gt;&lt;span class="s2"&gt;%8D&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;4%BF%A1&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;6&lt;/span&gt;&lt;span class="si"&gt;%81%&lt;/span&gt;&lt;span class="s2"&gt;AF/&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;8%A1%8C&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;6&lt;/span&gt;&lt;span class="si"&gt;%83%&lt;/span&gt;&lt;span class="s2"&gt;85&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;6&lt;/span&gt;&lt;span class="si"&gt;%95%&lt;/span&gt;&lt;span class="s2"&gt;B0&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;6%8D%AE/&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;4%BA%BA&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;6%B0&lt;/span&gt;&lt;span class="si"&gt;%91%&lt;/span&gt;&lt;span class="s2"&gt;E5%B8&lt;/span&gt;&lt;span class="si"&gt;%81%&lt;/span&gt;&lt;span class="s2"&gt;E5%8D%B3&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;6%9C&lt;/span&gt;&lt;span class="si"&gt;%9F%E&lt;/span&gt;&lt;span class="s2"&gt;5%A4&lt;/span&gt;&lt;span class="si"&gt;%96%&lt;/span&gt;&lt;span class="s2"&gt;E6%B1&lt;/span&gt;&lt;span class="si"&gt;%87%&lt;/span&gt;&lt;span class="s2"&gt;E7&lt;/span&gt;&lt;span class="si"&gt;%89%&lt;/span&gt;&lt;span class="s2"&gt;8C&lt;/span&gt;&lt;span class="si"&gt;%E&lt;/span&gt;&lt;span class="s2"&gt;4%BB%B7/&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;date&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2021-01-13&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;currType&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;serverType&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;h6 id="报错ssl-unsafe_legacy_renegotiation_disabled"&gt;报错：&lt;code&gt;[SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED]&lt;/code&gt;&lt;/h6&gt;
&lt;ul&gt;
&lt;li&gt;当前的 Python + OpenSSL 与工行 PAPI 服务器的 TLS 协商不兼容&lt;/li&gt;
&lt;li&gt;更准确地说：
请求触发了“不安全的旧式 TLS 重新协商”，而 Python 默认已经禁止它&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;为什么浏览器能访问，我的 Python 不能？&lt;/strong&gt;
浏览器（Chrome / Edge）：&lt;/p&gt;</description><content:encoded><![CDATA[<h2 id="爬取单日数据">爬取单日数据</h2>
<h4 id="前期准备">前期准备</h4>
<p>我要爬取的网站是</p>
<pre><code>https://www.icbc.com.cn/ICBC/%e9%87%91%e8%9e%8d%e4%bf%a1%e6%81%af/%e8%a1%8c%e6%83%85%e6%95%b0%e6%8d%ae/%e4%ba%ba%e6%b0%91%e5%b8%81%e5%8d%b3%e6%9c%9f%e5%a4%96%e6%b1%87%e7%89%8c%e4%bb%b7/
</code></pre>
<p>数据是这样的：币种、银行买入价、银行卖出价、发布时间</p>
<p><img alt="1" loading="lazy" src="/img/in-post/python_img/%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE%202026-01-25%20114748.png"></p>
<p>环境：python 3.12.2</p>
<h4 id="寻找网络请求接口">寻找网络请求接口</h4>
<p>在浏览器中按F12打开开发者工具，然后点击Network，勾选 Preserve log</p>
<ul>
<li>
<p>选择 Fetch / XHR</p>
<p><code>XMLHttpRequest (XHR)</code> 和 <code>Fetch API</code>都是网页向服务器发起 HTTP 请求的机制。Fetch API 是一种现代的、基于 Promise 的替代方案，用于取代老旧的、基于回调的 XHR，它提供了更简洁的语法和更适合现代网页开发的功能。</p>
</li>
<li>
<p>手动操作页面：</p>
<pre><code>  选择一个日期（比如 2021-01-25）

  点击【查询】
</code></pre>
</li>
<li>
<p>Network 列表里 新出现的 POST 请求</p>
<p><img loading="lazy" src="/img/in-post/python_img/%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE%202026-01-25%20161550.png">
可以确定工商银行新版 PAPI 的“历史外汇牌价接口”：<code>POST https://papi.icbc.com.cn/exchanges/ns/history</code></p>
</li>
</ul>
<h4 id="如何使用接口">如何使用接口</h4>
<h6 id="请求方式">请求方式</h6>
<ul>
<li>
<p>POST</p>
</li>
<li>
<p>Content-Type: application/json</p>
</li>
</ul>
<h6 id="请求体">请求体</h6>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;date&#34;</span><span class="p">:</span> <span class="s2">&#34;2021-01-13&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;currType&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;serverType&#34;</span><span class="p">:</span> <span class="s2">&#34;1&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>👉 这个接口不支持“时间区间”</p>
<p>👉 需要一天一天请求</p>
<h4 id="编写代码">编写代码</h4>
<details>
<summary>点击展开/折叠代码</summary>
<div markdown="1">
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">requests</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;https://papi.icbc.com.cn/exchanges/ns/history&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">headers</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;User-Agent&#34;</span><span class="p">:</span> <span class="s2">&#34;Mozilla/5.0 (Windows NT 10.0; Win64; x64)&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Content-Type&#34;</span><span class="p">:</span> <span class="s2">&#34;application/json&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Origin&#34;</span><span class="p">:</span> <span class="s2">&#34;https://www.icbc.com.cn&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Referer&#34;</span><span class="p">:</span> <span class="s2">&#34;https://www.icbc.com.cn/ICBC/</span><span class="si">%E</span><span class="s2">9</span><span class="si">%87%</span><span class="s2">91</span><span class="si">%E</span><span class="s2">8</span><span class="si">%9E</span><span class="s2">%8D</span><span class="si">%E</span><span class="s2">4%BF%A1</span><span class="si">%E</span><span class="s2">6</span><span class="si">%81%</span><span class="s2">AF/</span><span class="si">%E</span><span class="s2">8%A1%8C</span><span class="si">%E</span><span class="s2">6</span><span class="si">%83%</span><span class="s2">85</span><span class="si">%E</span><span class="s2">6</span><span class="si">%95%</span><span class="s2">B0</span><span class="si">%E</span><span class="s2">6%8D%AE/</span><span class="si">%E</span><span class="s2">4%BA%BA</span><span class="si">%E</span><span class="s2">6%B0</span><span class="si">%91%</span><span class="s2">E5%B8</span><span class="si">%81%</span><span class="s2">E5%8D%B3</span><span class="si">%E</span><span class="s2">6%9C</span><span class="si">%9F%E</span><span class="s2">5%A4</span><span class="si">%96%</span><span class="s2">E6%B1</span><span class="si">%87%</span><span class="s2">E7</span><span class="si">%89%</span><span class="s2">8C</span><span class="si">%E</span><span class="s2">4%BB%B7/&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">payload</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;date&#34;</span><span class="p">:</span> <span class="s2">&#34;2021-01-13&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;currType&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;serverType&#34;</span><span class="p">:</span> <span class="s2">&#34;1&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">,</span> <span class="n">json</span><span class="o">=</span><span class="n">payload</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">r</span><span class="o">.</span><span class="n">raise_for_status</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">r</span><span class="o">.</span><span class="n">json</span><span class="p">())</span>
</span></span></code></pre></td></tr></table>
</div>
</div></div>
</details>
<h6 id="报错ssl-unsafe_legacy_renegotiation_disabled">报错：<code>[SSL: UNSAFE_LEGACY_RENEGOTIATION_DISABLED]</code></h6>
<ul>
<li>当前的 Python + OpenSSL 与工行 PAPI 服务器的 TLS 协商不兼容</li>
<li>更准确地说：
请求触发了“不安全的旧式 TLS 重新协商”，而 Python 默认已经禁止它</li>
</ul>
<p><strong>为什么浏览器能访问，我的 Python 不能？</strong>
浏览器（Chrome / Edge）：</p>
<pre><code>自带 定制版 TLS 实现

对一些“历史遗留银行系统”做了兼容

会悄悄降级 / 特判
</code></pre>
<p>Python（requests / urllib3）：</p>
<pre><code>用的是 OpenSSL 官方实现

默认严格安全策略

直接拒绝这种 TLS 行为
</code></pre>
<p>👉 银行系统（尤其是国内）</p>
<p>👉 TLS 配置老 + 中间网关</p>
<p>👉 非常容易触发这个问题</p>
<h6 id="解决方案">解决方案</h6>
<ul>
<li>彻底禁用代理，哪怕不用代理工具，也很可能被环境变量污染。</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">os</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&#34;HTTP_PROXY&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&#34;HTTPS_PROXY&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&#34;ALL_PROXY&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>requests 调用时显式指定代理</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">proxies</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;http&#34;</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;https&#34;</span><span class="p">:</span> <span class="kc">None</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 或者直接在代码里禁用</span>
</span></span></code></pre></td></tr></table>
</div>
</div><ul>
<li>SSL Adapter + verify=False</li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="c1"># ===== 2. SSL Adapter：同时解决旧协议和证书验证冲突问题 =====</span>
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">LegacySSLAdapter</span><span class="p">(</span><span class="n">requests</span><span class="o">.</span><span class="n">adapters</span><span class="o">.</span><span class="n">HTTPAdapter</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">init_poolmanager</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">connections</span><span class="p">,</span> <span class="n">maxsize</span><span class="p">,</span> <span class="n">block</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># 创建 SSL 上下文</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span> <span class="o">=</span> <span class="n">create_urllib3_context</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># 解决旧版 SSL 协商问题</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">.</span><span class="n">options</span> <span class="o">|=</span> <span class="mh">0x4</span>  <span class="c1"># OP_LEGACY_SERVER_CONNECT</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># 关闭证书验证（对应 verify=False）</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">.</span><span class="n">check_hostname</span> <span class="o">=</span> <span class="kc">False</span>  <span class="c1"># 先关闭主机名检查</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">.</span><span class="n">verify_mode</span> <span class="o">=</span> <span class="n">ssl</span><span class="o">.</span><span class="n">CERT_NONE</span>  <span class="c1"># 再关闭证书验证</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">poolmanager</span> <span class="o">=</span> <span class="n">PoolManager</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="n">num_pools</span><span class="o">=</span><span class="n">connections</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">maxsize</span><span class="o">=</span><span class="n">maxsize</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">block</span><span class="o">=</span><span class="n">block</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">ssl_context</span><span class="o">=</span><span class="n">ctx</span>
</span></span><span class="line"><span class="cl">        <span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><details>
<summary>点击展开/折叠代码</summary>
<div markdown="1">
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span><span class="lnt">61
</span><span class="lnt">62
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">os</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">requests</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">ssl</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">urllib3.poolmanager</span> <span class="kn">import</span> <span class="n">PoolManager</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">urllib3.util.ssl_</span> <span class="kn">import</span> <span class="n">create_urllib3_context</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===== 1. 彻底禁用代理 =====</span>
</span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&#34;HTTP_PROXY&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&#34;HTTPS_PROXY&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&#34;ALL_PROXY&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===== 2. SSL Adapter：同时解决旧协议和证书验证冲突问题 =====</span>
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">LegacySSLAdapter</span><span class="p">(</span><span class="n">requests</span><span class="o">.</span><span class="n">adapters</span><span class="o">.</span><span class="n">HTTPAdapter</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">init_poolmanager</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">connections</span><span class="p">,</span> <span class="n">maxsize</span><span class="p">,</span> <span class="n">block</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># 创建 SSL 上下文</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span> <span class="o">=</span> <span class="n">create_urllib3_context</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># 解决旧版 SSL 协商问题</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">.</span><span class="n">options</span> <span class="o">|=</span> <span class="mh">0x4</span>  <span class="c1"># OP_LEGACY_SERVER_CONNECT</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># 关闭证书验证（对应 verify=False）</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">.</span><span class="n">check_hostname</span> <span class="o">=</span> <span class="kc">False</span>  <span class="c1"># 先关闭主机名检查</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">.</span><span class="n">verify_mode</span> <span class="o">=</span> <span class="n">ssl</span><span class="o">.</span><span class="n">CERT_NONE</span>  <span class="c1"># 再关闭证书验证</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">poolmanager</span> <span class="o">=</span> <span class="n">PoolManager</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="n">num_pools</span><span class="o">=</span><span class="n">connections</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">maxsize</span><span class="o">=</span><span class="n">maxsize</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">block</span><span class="o">=</span><span class="n">block</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">ssl_context</span><span class="o">=</span><span class="n">ctx</span>
</span></span><span class="line"><span class="cl">        <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">url</span> <span class="o">=</span> <span class="s2">&#34;https://papi.icbc.com.cn/exchanges/ns/history&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">headers</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;User-Agent&#34;</span><span class="p">:</span> <span class="s2">&#34;Mozilla/5.0 (Windows NT 10.0; Win64; x64)&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Content-Type&#34;</span><span class="p">:</span> <span class="s2">&#34;application/json&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Origin&#34;</span><span class="p">:</span> <span class="s2">&#34;https://www.icbc.com.cn&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Referer&#34;</span><span class="p">:</span> <span class="s2">&#34;https://www.icbc.com.cn/ICBC/</span><span class="si">%E</span><span class="s2">9</span><span class="si">%87%</span><span class="s2">91</span><span class="si">%E</span><span class="s2">8</span><span class="si">%9E</span><span class="s2">%8D</span><span class="si">%E</span><span class="s2">4%BF%A1</span><span class="si">%E</span><span class="s2">6</span><span class="si">%81%</span><span class="s2">AF/</span><span class="si">%E</span><span class="s2">8%A1%8C</span><span class="si">%E</span><span class="s2">6</span><span class="si">%83%</span><span class="s2">85</span><span class="si">%E</span><span class="s2">6</span><span class="si">%95%</span><span class="s2">B0</span><span class="si">%E</span><span class="s2">6%8D%AE/</span><span class="si">%E</span><span class="s2">4%BA%BA</span><span class="si">%E</span><span class="s2">6%B0</span><span class="si">%91%</span><span class="s2">E5%B8</span><span class="si">%81%</span><span class="s2">E5%8D%B3</span><span class="si">%E</span><span class="s2">6%9C</span><span class="si">%9F%E</span><span class="s2">5%A4</span><span class="si">%96%</span><span class="s2">E6%B1</span><span class="si">%87%</span><span class="s2">E7</span><span class="si">%89%</span><span class="s2">8C</span><span class="si">%E</span><span class="s2">4%BB%B7/&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">payload</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;date&#34;</span><span class="p">:</span> <span class="s2">&#34;2021-01-13&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;currType&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;serverType&#34;</span><span class="p">:</span> <span class="s2">&#34;1&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">session</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">Session</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">session</span><span class="o">.</span><span class="n">mount</span><span class="p">(</span><span class="s2">&#34;https://&#34;</span><span class="p">,</span> <span class="n">LegacySSLAdapter</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">proxies</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;http&#34;</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;https&#34;</span><span class="p">:</span> <span class="kc">None</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 这里移除了 verify=False，因为已经在适配器里统一配置了</span>
</span></span><span class="line"><span class="cl"><span class="n">r</span> <span class="o">=</span> <span class="n">session</span><span class="o">.</span><span class="n">post</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">url</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">headers</span><span class="o">=</span><span class="n">headers</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">json</span><span class="o">=</span><span class="n">payload</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">timeout</span><span class="o">=</span><span class="mi">15</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">proxies</span><span class="o">=</span><span class="n">proxies</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">r</span><span class="o">.</span><span class="n">status_code</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">r</span><span class="o">.</span><span class="n">text</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></div>
</details>
<p><strong>结果：</strong>
<img alt="2" loading="lazy" src="/img/in-post/python_img/%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE%202026-01-25%20163806.png"></p>
<h2 id="爬取近五年数据">爬取近五年数据</h2>
<details>
<summary>点击展开/折叠代码</summary>
<div markdown="1">
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">  1
</span><span class="lnt">  2
</span><span class="lnt">  3
</span><span class="lnt">  4
</span><span class="lnt">  5
</span><span class="lnt">  6
</span><span class="lnt">  7
</span><span class="lnt">  8
</span><span class="lnt">  9
</span><span class="lnt"> 10
</span><span class="lnt"> 11
</span><span class="lnt"> 12
</span><span class="lnt"> 13
</span><span class="lnt"> 14
</span><span class="lnt"> 15
</span><span class="lnt"> 16
</span><span class="lnt"> 17
</span><span class="lnt"> 18
</span><span class="lnt"> 19
</span><span class="lnt"> 20
</span><span class="lnt"> 21
</span><span class="lnt"> 22
</span><span class="lnt"> 23
</span><span class="lnt"> 24
</span><span class="lnt"> 25
</span><span class="lnt"> 26
</span><span class="lnt"> 27
</span><span class="lnt"> 28
</span><span class="lnt"> 29
</span><span class="lnt"> 30
</span><span class="lnt"> 31
</span><span class="lnt"> 32
</span><span class="lnt"> 33
</span><span class="lnt"> 34
</span><span class="lnt"> 35
</span><span class="lnt"> 36
</span><span class="lnt"> 37
</span><span class="lnt"> 38
</span><span class="lnt"> 39
</span><span class="lnt"> 40
</span><span class="lnt"> 41
</span><span class="lnt"> 42
</span><span class="lnt"> 43
</span><span class="lnt"> 44
</span><span class="lnt"> 45
</span><span class="lnt"> 46
</span><span class="lnt"> 47
</span><span class="lnt"> 48
</span><span class="lnt"> 49
</span><span class="lnt"> 50
</span><span class="lnt"> 51
</span><span class="lnt"> 52
</span><span class="lnt"> 53
</span><span class="lnt"> 54
</span><span class="lnt"> 55
</span><span class="lnt"> 56
</span><span class="lnt"> 57
</span><span class="lnt"> 58
</span><span class="lnt"> 59
</span><span class="lnt"> 60
</span><span class="lnt"> 61
</span><span class="lnt"> 62
</span><span class="lnt"> 63
</span><span class="lnt"> 64
</span><span class="lnt"> 65
</span><span class="lnt"> 66
</span><span class="lnt"> 67
</span><span class="lnt"> 68
</span><span class="lnt"> 69
</span><span class="lnt"> 70
</span><span class="lnt"> 71
</span><span class="lnt"> 72
</span><span class="lnt"> 73
</span><span class="lnt"> 74
</span><span class="lnt"> 75
</span><span class="lnt"> 76
</span><span class="lnt"> 77
</span><span class="lnt"> 78
</span><span class="lnt"> 79
</span><span class="lnt"> 80
</span><span class="lnt"> 81
</span><span class="lnt"> 82
</span><span class="lnt"> 83
</span><span class="lnt"> 84
</span><span class="lnt"> 85
</span><span class="lnt"> 86
</span><span class="lnt"> 87
</span><span class="lnt"> 88
</span><span class="lnt"> 89
</span><span class="lnt"> 90
</span><span class="lnt"> 91
</span><span class="lnt"> 92
</span><span class="lnt"> 93
</span><span class="lnt"> 94
</span><span class="lnt"> 95
</span><span class="lnt"> 96
</span><span class="lnt"> 97
</span><span class="lnt"> 98
</span><span class="lnt"> 99
</span><span class="lnt">100
</span><span class="lnt">101
</span><span class="lnt">102
</span><span class="lnt">103
</span><span class="lnt">104
</span><span class="lnt">105
</span><span class="lnt">106
</span><span class="lnt">107
</span><span class="lnt">108
</span><span class="lnt">109
</span><span class="lnt">110
</span><span class="lnt">111
</span><span class="lnt">112
</span><span class="lnt">113
</span><span class="lnt">114
</span><span class="lnt">115
</span><span class="lnt">116
</span><span class="lnt">117
</span><span class="lnt">118
</span><span class="lnt">119
</span><span class="lnt">120
</span><span class="lnt">121
</span><span class="lnt">122
</span><span class="lnt">123
</span><span class="lnt">124
</span><span class="lnt">125
</span><span class="lnt">126
</span><span class="lnt">127
</span><span class="lnt">128
</span><span class="lnt">129
</span><span class="lnt">130
</span><span class="lnt">131
</span><span class="lnt">132
</span><span class="lnt">133
</span><span class="lnt">134
</span><span class="lnt">135
</span><span class="lnt">136
</span><span class="lnt">137
</span><span class="lnt">138
</span><span class="lnt">139
</span><span class="lnt">140
</span><span class="lnt">141
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">os</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">time</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">ssl</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">requests</span>
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="nn">pandas</span> <span class="k">as</span> <span class="nn">pd</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span><span class="p">,</span> <span class="n">timedelta</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">urllib3.poolmanager</span> <span class="kn">import</span> <span class="n">PoolManager</span>
</span></span><span class="line"><span class="cl"><span class="kn">from</span> <span class="nn">urllib3.util.ssl_</span> <span class="kn">import</span> <span class="n">create_urllib3_context</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 1. 彻底禁用代理</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&#34;HTTP_PROXY&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&#34;HTTPS_PROXY&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl"><span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s2">&#34;ALL_PROXY&#34;</span><span class="p">]</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 2. SSL Adapter（银行专用）</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="k">class</span> <span class="nc">LegacySSLAdapter</span><span class="p">(</span><span class="n">requests</span><span class="o">.</span><span class="n">adapters</span><span class="o">.</span><span class="n">HTTPAdapter</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="k">def</span> <span class="nf">init_poolmanager</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">connections</span><span class="p">,</span> <span class="n">maxsize</span><span class="p">,</span> <span class="n">block</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span> <span class="o">=</span> <span class="n">create_urllib3_context</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">.</span><span class="n">options</span> <span class="o">|=</span> <span class="mh">0x4</span>  <span class="c1"># OP_LEGACY_SERVER_CONNECT</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">.</span><span class="n">check_hostname</span> <span class="o">=</span> <span class="kc">False</span>
</span></span><span class="line"><span class="cl">        <span class="n">ctx</span><span class="o">.</span><span class="n">verify_mode</span> <span class="o">=</span> <span class="n">ssl</span><span class="o">.</span><span class="n">CERT_NONE</span>
</span></span><span class="line"><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">poolmanager</span> <span class="o">=</span> <span class="n">PoolManager</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="n">num_pools</span><span class="o">=</span><span class="n">connections</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">maxsize</span><span class="o">=</span><span class="n">maxsize</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">block</span><span class="o">=</span><span class="n">block</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">ssl_context</span><span class="o">=</span><span class="n">ctx</span>
</span></span><span class="line"><span class="cl">        <span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 3. 请求基础配置</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="n">URL</span> <span class="o">=</span> <span class="s2">&#34;https://papi.icbc.com.cn/exchanges/ns/history&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">HEADERS</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;User-Agent&#34;</span><span class="p">:</span> <span class="s2">&#34;Mozilla/5.0 (Windows NT 10.0; Win64; x64)&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Content-Type&#34;</span><span class="p">:</span> <span class="s2">&#34;application/json&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Origin&#34;</span><span class="p">:</span> <span class="s2">&#34;https://www.icbc.com.cn&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="s2">&#34;Referer&#34;</span><span class="p">:</span> <span class="s2">&#34;https://www.icbc.com.cn/ICBC/&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">PROXIES</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&#34;http&#34;</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span> <span class="s2">&#34;https&#34;</span><span class="p">:</span> <span class="kc">None</span><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 4. 创建 Session</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="n">session</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">Session</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">session</span><span class="o">.</span><span class="n">mount</span><span class="p">(</span><span class="s2">&#34;https://&#34;</span><span class="p">,</span> <span class="n">LegacySSLAdapter</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 5. 单日抓取函数（带重试）</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="k">def</span> <span class="nf">fetch_one_day</span><span class="p">(</span><span class="n">date_str</span><span class="p">,</span> <span class="n">max_retry</span><span class="o">=</span><span class="mi">3</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">    <span class="n">payload</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;date&#34;</span><span class="p">:</span> <span class="n">date_str</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;currType&#34;</span><span class="p">:</span> <span class="s2">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;serverType&#34;</span><span class="p">:</span> <span class="s2">&#34;1&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">attempt</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">max_retry</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">        <span class="k">try</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">r</span> <span class="o">=</span> <span class="n">session</span><span class="o">.</span><span class="n">post</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">                <span class="n">URL</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="n">headers</span><span class="o">=</span><span class="n">HEADERS</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="n">json</span><span class="o">=</span><span class="n">payload</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="n">timeout</span><span class="o">=</span><span class="mi">15</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="n">proxies</span><span class="o">=</span><span class="n">PROXIES</span>
</span></span><span class="line"><span class="cl">            <span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">r</span><span class="o">.</span><span class="n">raise_for_status</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">            <span class="n">data</span> <span class="o">=</span> <span class="n">r</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="n">data</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;code&#34;</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">                <span class="k">return</span> <span class="n">data</span><span class="p">[</span><span class="s2">&#34;data&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;[WARN] </span><span class="si">{</span><span class="n">date_str</span><span class="si">}</span><span class="s2"> 返回异常 code: </span><span class="si">{</span><span class="n">data</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="k">return</span> <span class="kc">None</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;[RETRY </span><span class="si">{</span><span class="n">attempt</span><span class="si">}</span><span class="s2">] </span><span class="si">{</span><span class="n">date_str</span><span class="si">}</span><span class="s2"> 失败: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">2</span> <span class="o">*</span> <span class="n">attempt</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="kc">None</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 6. 时间范围（近 5 年）</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="n">end_date</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">today</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="n">start_date</span> <span class="o">=</span> <span class="n">end_date</span> <span class="o">-</span> <span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">5</span> <span class="o">*</span> <span class="mi">365</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 7. 主循环</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="n">all_rows</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl"><span class="n">missing_dates</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">current</span> <span class="o">=</span> <span class="n">start_date</span>
</span></span><span class="line"><span class="cl"><span class="k">while</span> <span class="n">current</span> <span class="o">&lt;=</span> <span class="n">end_date</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="n">date_str</span> <span class="o">=</span> <span class="n">current</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s2">&#34;%Y-%m-</span><span class="si">%d</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;📅 抓取 </span><span class="si">{</span><span class="n">date_str</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">day_data</span> <span class="o">=</span> <span class="n">fetch_one_day</span><span class="p">(</span><span class="n">date_str</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="ow">not</span> <span class="n">day_data</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="n">missing_dates</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">date_str</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">day_data</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">            <span class="n">all_rows</span><span class="o">.</span><span class="n">append</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;date&#34;</span><span class="p">:</span> <span class="n">date_str</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;currencyENName&#34;</span><span class="p">:</span> <span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;currencyENName&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;currencyCHName&#34;</span><span class="p">:</span> <span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;currencyCHName&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;reference&#34;</span><span class="p">:</span> <span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;reference&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;foreignBuy&#34;</span><span class="p">:</span> <span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;foreignBuy&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;foreignSell&#34;</span><span class="p">:</span> <span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;foreignSell&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;cashBuy&#34;</span><span class="p">:</span> <span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;cashBuy&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">                <span class="s2">&#34;cashSell&#34;</span><span class="p">:</span> <span class="n">item</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&#34;cashSell&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">            <span class="p">})</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mf">0.5</span><span class="p">)</span>  <span class="c1"># 银行接口，别太猛</span>
</span></span><span class="line"><span class="cl">    <span class="n">current</span> <span class="o">+=</span> <span class="n">timedelta</span><span class="p">(</span><span class="n">days</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">session</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 8. DataFrame &amp; CSV</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ===============================</span>
</span></span><span class="line"><span class="cl"><span class="n">df</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">DataFrame</span><span class="p">(</span><span class="n">all_rows</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">csv_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="vm">__file__</span><span class="p">),</span> <span class="s2">&#34;icbc_exchange_5y.csv&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="n">df</span><span class="o">.</span><span class="n">to_csv</span><span class="p">(</span><span class="n">csv_path</span><span class="p">,</span> <span class="n">index</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s2">&#34;utf-8-sig&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">✅ 数据抓取完成&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;📄 CSV 文件：</span><span class="si">{</span><span class="n">csv_path</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;📊 总记录数：</span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">df</span><span class="p">)</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="n">missing_dates</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;⚠️ 缺失日期 (</span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">missing_dates</span><span class="p">)</span><span class="si">}</span><span class="s2">):&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">missing_dates</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;🎉 无缺失日期&#34;</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div></div>
</details>
]]></content:encoded></item></channel></rss>