<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Python on IT 空間</title><link>https://blog.jiatool.com/tags/Python/</link><description>Recent content in Python on IT 空間</description><generator>Hugo -- gohugo.io</generator><language>zh</language><managingEditor>jia@jiatool.com (Jia)</managingEditor><webMaster>jia@jiatool.com (Jia)</webMaster><copyright>&amp;copy;{year}, Jia All Rights Reserved</copyright><lastBuildDate>Sat, 30 Nov 2024 20:40:00 +0800</lastBuildDate><atom:link href="https://blog.jiatool.com/tags/Python/index.xml" rel="self" type="application/rss+xml"/><item><title>[Python爬蟲實例] 591 房屋交易 -「新建案」搜尋與房屋詳情</title><link>https://blog.jiatool.com/posts/newhouse591_spider/</link><pubDate>Sat, 30 Nov 2024 20:40:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sat, 30 Nov 2024 20:40:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/newhouse591_spider/</guid><description>前言 很久之前有寫一篇「591 租屋網 - 搜尋房屋與房屋詳情 」，是針對 591 內的租屋網站進行資料抓取。 不過後來網站有改版，那時的程式寫法就失效了。 最近</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>很久之前有寫一篇「&lt;a href="https://blog.jiatool.com/posts/house591_spider" target="_blank" rel="noopener">
591 租屋網 - 搜尋房屋與房屋詳情
&lt;/a>」，是針對 591 內的租屋網站進行資料抓取。&lt;/p>
&lt;p>不過後來網站有改版，那時的程式寫法就失效了。&lt;br />
最近有再嘗試，雖然有找出發請求的網址，但發現回傳資料有透過 AES 之類的加密方式加密過的，要解開的話還要從它的 JS 程式中尋找 KEY 值，因為太麻煩，我就沒有繼續研究了。&lt;/p>
&lt;p>如果有需求的讀者，可以參考這篇文章：&lt;a href="https://medium.com/jacky-life/4a17936aea1a" target="_blank" rel="noopener">
AWS 雲端 591 租屋爬蟲架構
&lt;/a>，他有針對新版的去做修正，而且還加入資料儲存、mail 通知、定時換 IP 等等機制。&lt;/p>
&lt;br>
&lt;p>今天，改來試試爬取 591 房屋交易網站的「&lt;a href="https://newhouse.591.com.tw/" target="_blank" rel="noopener">
新建案
&lt;/a>」&amp;quot;搜尋建案&amp;quot; 與 &amp;quot;取得房屋詳情&amp;quot;，說明如何發出請求、取得回傳數據資料。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/house591_spider/house.jpg" alt="來源：Unsplash" data-caption="來源：Unsplash" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='550px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:550px;height:;"/>
&lt;figcaption style="text-align: center;">
來源：Unsplash
&lt;/figcaption>
&lt;/figure>
&lt;p>備註：此文僅教育學習，切勿用作商業用途，個人實作皆屬個人行為，本作者不負任何法律責任。&lt;/p>
&lt;br/>
&lt;!--adsense-->
&lt;br>
&lt;h2 id="套件">套件&lt;/h2>
&lt;p>此次 Python 爬蟲主要使用到的套件：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Requests [&lt;a href="https://requests.readthedocs.io/en/master/" target="_blank" rel="noopener">
Doc
&lt;/a>] [&lt;a href="https://github.com/psf/requests" target="_blank" rel="noopener">
GitHub
&lt;/a>]&lt;/p>
&lt;/li>
&lt;li>
&lt;p>BeautifulSoup [&lt;a href="https://www.crummy.com/software/BeautifulSoup/bs4/doc/" target="_blank" rel="noopener">
Doc
&lt;/a>] [&lt;a href="https://code.launchpad.net/beautifulsoup" target="_blank" rel="noopener">
Source
&lt;/a>]&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>安裝&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">pip install requests
pip install beautifulsoup4
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h2 id="搜尋建案">搜尋建案&lt;/h2>
&lt;p>在 591 房屋交易網站的「&lt;a href="https://newhouse.591.com.tw/" target="_blank" rel="noopener">
新建案
&lt;/a>」主頁，我們先直接按搜尋，它會跳到&lt;a href="https://newhouse.591.com.tw/list" target="_blank" rel="noopener">
另一個頁面
&lt;/a>。&lt;/p>
&lt;p>在這個搜尋頁面，上方可以選擇不同的搜尋條件，下方則是房屋搜尋結果列表。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/newhouse591_spider/search_newhouse_page.jpg" alt="591 新建案 搜尋頁面" data-caption="591 新建案 搜尋頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
591 新建案 搜尋頁面
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h3 id="請求路徑與參數">請求路徑與參數&lt;/h3>
&lt;p>進到「&lt;a href="https://newhouse.591.com.tw/list" target="_blank" rel="noopener">
591 新建案
&lt;/a>」的搜尋頁面後，打開瀏覽器的 &lt;strong>開發人員工具&lt;/strong> (F12 或 Ctrl + Shift + i) &amp;gt; &lt;strong>Network&lt;/strong> 分頁，在 &amp;quot;Fetch/XHR&amp;quot; 分類中找找看哪個是搜尋建案結果的請求。&lt;/p>
&lt;p>稍微尋找後，可以確定是 &lt;code>https://newhouse.591.com.tw/home/housing/list-search&lt;/code> 這個請求。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/newhouse591_spider/newhouse_search_url.jpg" alt="591 新建案 搜尋 API 網址" data-caption="591 新建案 搜尋 API 網址" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
591 新建案 搜尋 API 網址
&lt;/figcaption>
&lt;/figure>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/newhouse591_spider/newhouse_search_preview.jpg" alt="591 新建案 API 回傳結果預覽" data-caption="591 新建案 API 回傳結果預覽" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='1000px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:1000px;height:;"/>
&lt;figcaption style="text-align: center;">
591 新建案 API 回傳結果預覽
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>另外，我們可以透過帶入不同的搜尋參數值，來達到對結果做不同的篩選。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/newhouse591_spider/search_filter_condition.jpg" alt="篩選條件參數" data-caption="篩選條件參數" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
篩選條件參數
&lt;/figcaption>
&lt;/figure>
&lt;p>當我們選擇不同條件後，觀察剛剛的請求，會發現它在網址後方帶入不同的參數 (parameters 或稱 query string)，剛好對應我們選擇的條件。&lt;/p>
&lt;p>例如：&lt;code>https://newhouse.591.com.tw/home/housing/list-search?page=1&amp;amp;device=pc&amp;amp;device_id=qdmsxxxxxxxrjy2&amp;amp;sectionid=251,253&amp;amp;total_price=3&amp;amp;regionid=17&lt;/code> 後面這段 &lt;code>page=1&amp;amp;device=pc&amp;amp;device_id=qdmsxxxxxxxrjy2&amp;amp;sectionid=251,253&amp;amp;total_price=3&amp;amp;regionid=17&lt;/code>。&lt;/p>
&lt;br>
&lt;p>以下我將其全部羅列出來，但 &amp;quot;按地區&amp;quot; 和 &amp;quot;按捷運&amp;quot; 有太多種類，就不一一呈現，可以自己選擇後再從 &lt;strong>開發人員工具&lt;/strong> 查看。&lt;/p>
&lt;p>* 以下某些選項在網頁上是可以多選的，則參數的數值用逗號 &lt;code>,&lt;/code> 隔開即可。如 &lt;code>tag=1,4,5&lt;/code> 代表 &amp;quot;特色&amp;quot; 勾選 &lt;code>近捷運&lt;/code>、&lt;code>重劃區&lt;/code>、&lt;code>近公園&lt;/code>。&lt;/p>
&lt;br>
&lt;p>&lt;strong>按地區&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>縣市&lt;/th>
&lt;th>regionid&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>台北市&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>新北市&lt;/td>
&lt;td>3&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>桃園市&lt;/td>
&lt;td>6&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>台中市&lt;/td>
&lt;td>8&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>台南市&lt;/td>
&lt;td>15&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>高雄市&lt;/td>
&lt;td>17&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>如果要更細分 &amp;quot;地區&amp;quot;、&amp;quot;生活圈&amp;quot; 的話，要再加上 &lt;code>sectionid&lt;/code>、&lt;code>shop_id&lt;/code> 參數，如下：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>代表意思&lt;/th>
&lt;th>參數&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>台北市&lt;/td>
&lt;td>&lt;code>regionid=1&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>台北市 &amp;gt; 內湖區&lt;/td>
&lt;td>&lt;code>regionid=1&amp;amp;sectionid=10&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>台北市 &amp;gt; 內湖區 &amp;gt; 內湖科技園區&lt;/td>
&lt;td>&lt;code>regionid=1&amp;amp;sectionid=10&amp;amp;shop_id=164&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>高雄市 &amp;gt; 楠梓區&lt;/td>
&lt;td>&lt;code>regionid=17&amp;amp;sectionid=251&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>高雄市 &amp;gt; 楠梓區 &amp;gt; 高雄大學特區&lt;/td>
&lt;td>&lt;code>regionid=17&amp;amp;sectionid=251&amp;amp;shop_id=385&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>高雄市 &amp;gt; 鳳山區 &amp;gt; 衛武營生活圈&lt;/td>
&lt;td>&lt;code>regionid=17&amp;amp;sectionid=268&amp;amp;shop_id=290&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;br>
&lt;p>&lt;strong>按捷運&lt;/strong>&lt;/p>
&lt;p>要多加 &lt;code>search_type&lt;/code> 代表按捷運篩選。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>捷運&lt;/th>
&lt;th>city&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>台北捷運&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>高雄捷運&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>新北捷運&lt;/td>
&lt;td>3&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>桃園捷運&lt;/td>
&lt;td>4&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>台中捷運&lt;/td>
&lt;td>5&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>同樣如果要更細分 &amp;quot;路線&amp;quot;、&amp;quot;站點&amp;quot; 的話，要再加上 &lt;code>subway_line&lt;/code>、&lt;code>subway_id&lt;/code> 參數，如下：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>代表意思&lt;/th>
&lt;th>參數&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>台北捷運&lt;/td>
&lt;td>&lt;code>search_type=1&amp;amp;city=1&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>台北捷運 &amp;gt; 淡水信義線&lt;/td>
&lt;td>&lt;code>search_type=1&amp;amp;subway_line=2&amp;amp;city=1&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>台北捷運 &amp;gt; 淡水信義線 &amp;gt; 新北投&lt;/td>
&lt;td>&lt;code>search_type=1&amp;amp;subway_line=2&amp;amp;subway_id=4198&amp;amp;city=1&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>高雄捷運 &amp;gt; 高雄紅線 &amp;gt; 凱旋&lt;/td>
&lt;td>&lt;code>search_type=1&amp;amp;city=2&amp;amp;subway_line=1&amp;amp;subway_id=4333&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>台北捷運 &amp;gt; 高雄輕軌 &amp;gt; 五權國小&lt;/td>
&lt;td>&lt;code>search_type=1&amp;amp;city=2&amp;amp;subway_line=3&amp;amp;subway_id=66388&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;br>
&lt;br>
&lt;p>&lt;strong>單價&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>單價&lt;/th>
&lt;th>unit_price&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>50萬/坪以下&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>50-70萬/坪&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>70-80萬/坪&lt;/td>
&lt;td>3&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>80-100萬/坪&lt;/td>
&lt;td>4&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>100-120萬/坪&lt;/td>
&lt;td>5&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>120萬/坪以上&lt;/td>
&lt;td>6&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>* 如果要自訂單價金額範圍，改用 &lt;code>unit_price_min&lt;/code> 和 &lt;code>unit_price_max&lt;/code> 參數(例如 &amp;quot;10-30萬/坪&amp;quot; 要用 &lt;code>unit_price_min=10&amp;amp;unit_price_max=30&lt;/code>)。&lt;/p>
&lt;p>&lt;strong>總價&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>總價&lt;/th>
&lt;th>total_price&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>1500萬以下&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>1500-2000萬&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>2000-3000萬&lt;/td>
&lt;td>3&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>3000-4000萬&lt;/td>
&lt;td>4&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>4000-6000萬&lt;/td>
&lt;td>5&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>6000萬以上&lt;/td>
&lt;td>6&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>* 如果要自訂總價金額範圍，改用 &lt;code>total_price_min&lt;/code> 和 &lt;code>total_price_max&lt;/code> 參數(例如 &amp;quot;500-1000萬&amp;quot; 要用 &lt;code>total_price_min=500&amp;amp;total_price_max=1000&lt;/code>)。&lt;/p>
&lt;p>* 要注意的是 &amp;quot;單價&amp;quot; 與 &amp;quot;總價&amp;quot; 好像會隨著不同的縣市，而代表不同的範圍。例如高雄市 &lt;code>unit_price=1&lt;/code> 是代表 &amp;quot;15萬/坪以下&amp;quot;。&lt;/p>
&lt;br>
&lt;p>&lt;strong>格局&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>格局&lt;/th>
&lt;th>room&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>一房&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>二房&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>三房&lt;/td>
&lt;td>3&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>四房&lt;/td>
&lt;td>4&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>五房及以上&lt;/td>
&lt;td>5&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>型態&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>型態&lt;/th>
&lt;th>shape&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>住宅大樓&lt;/td>
&lt;td>3&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>電梯公寓&lt;/td>
&lt;td>7&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>華廈&lt;/td>
&lt;td>10&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>別墅&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>透天&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>商辦大樓&lt;/td>
&lt;td>8&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>廠辦&lt;/td>
&lt;td>11&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>其他&lt;/td>
&lt;td>9&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>狀態&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>狀態&lt;/th>
&lt;th>build_type&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>預售屋&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>新成屋&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>預推案&lt;/td>
&lt;td>4&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>用途&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>用途&lt;/th>
&lt;th>purpose&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>住家用&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>住商用&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>商業用&lt;/td>
&lt;td>3&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>工商用&lt;/td>
&lt;td>4&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>工業用&lt;/td>
&lt;td>5&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>其他&lt;/td>
&lt;td>6&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>特色&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>特色&lt;/th>
&lt;th>tag&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>近捷運&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>明星學區&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>重劃區&lt;/td>
&lt;td>4&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>充電設備&lt;/td>
&lt;td>piles&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>近公園&lt;/td>
&lt;td>5&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>景觀宅&lt;/td>
&lt;td>6&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>創意空間&lt;/td>
&lt;td>8&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>制震宅&lt;/td>
&lt;td>10&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>低首付&lt;/td>
&lt;td>12&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>超值好房&lt;/td>
&lt;td>100&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>優選建案&lt;/td>
&lt;td>101&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>地上權&lt;/td>
&lt;td>13&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;br/>
&lt;br/>
&lt;p>&lt;strong>排序&lt;/strong>&lt;/p>
&lt;p>也可以透過帶入排序參數 &lt;code>sort&lt;/code>，來對搜尋結果建案作排序。&lt;/p>
&lt;ul>
&lt;li>不過我發現有時候加入排序，搜尋結果好像怪怪的 (直接操作網頁也是)&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>排序&lt;/th>
&lt;th>sort&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>默認排序&lt;/td>
&lt;td>(無)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>金額排序從小到大&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>金額排序從大到小&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>瀏覽人數從多到少&lt;/td>
&lt;td>5&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>瀏覽人數從少到多&lt;/td>
&lt;td>6&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>開案時間從新到舊&lt;/td>
&lt;td>9&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>開案時間從舊到新&lt;/td>
&lt;td>10&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;br/>
&lt;p>&lt;strong>換頁&lt;/strong>&lt;/p>
&lt;p>試著在瀏覽器繼續往下滾動，它會持續載入新資料，觀察請求 &lt;strong>開發人員工具&lt;/strong> &amp;gt; &lt;strong>Network&lt;/strong> 新載入的網址變化：&lt;/p>
&lt;p>&lt;code>https://newhouse.591.com.tw/home/housing/list-search?page=2&amp;amp;device=pc&amp;amp;device_id=qdmsxxxxxxxxxrjy2&amp;amp;regionid=1&lt;/code>&lt;/p>
&lt;p>&lt;code>https://newhouse.591.com.tw/home/housing/list-search?page=3&amp;amp;device=pc&amp;amp;device_id=qdmsxxxxxxxxxrjy2&amp;amp;regionid=1&lt;/code>&lt;/p>
&lt;p>會發現它是透過網址後的 &lt;code>page&lt;/code> 參數，來切換不同頁數，並且每頁有 20 筆資料(建案)。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>頁數&lt;/th>
&lt;th>page&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>第一頁&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>第二頁&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>第三頁&lt;/td>
&lt;td>3&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>第 X 頁&lt;/td>
&lt;td>X&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>* 當然要它的 &amp;quot;總頁數&amp;quot; 有達到你指定的頁數才會有資料，至於怎麼知道 &amp;quot;總頁數&amp;quot;？可以從回傳資料裡找到，下面我們接著來看~&lt;/p>
&lt;br/>
&lt;h3 id="回傳資料">回傳資料&lt;/h3>
&lt;p>回傳資料主要有 &lt;code>bluekai_data&lt;/code> 和 &lt;code>data&lt;/code> 欄位。&lt;/p>
&lt;p>仔細觀察可以發現 &lt;code>bluekai_data&lt;/code> 可能是我們設定的篩選條件，但實際測試又不太一樣，反正不重要，我們不用理它。&lt;/p>
&lt;p>而 &lt;code>data&lt;/code> 欄位包含 建案基本資料(&lt;code>items&lt;/code>) 與 總頁數(&lt;code>total_page&lt;/code>)、當前頁數(&lt;code>page&lt;/code>)、總筆數(&lt;code>total&lt;/code>)、當頁筆數(&lt;code>per_page&lt;/code>) 等等資訊，上一節說的 &amp;quot;總頁數&amp;quot; 就可以從這邊取得。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;status&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;data&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;total&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1040&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;online_total&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">241&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;per_page&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">20&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;page&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;total_page&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">52&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;show_surround&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;items&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span> &lt;span class="s2">&amp;#34;建案基本資料...&amp;#34;&lt;/span> &lt;span class="p">]&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;bluekai_data&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;region_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;1&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;section_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;sale_price&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;rental_price&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;unit_price_per_ping&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;room&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;shape&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;mrt_city&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;mrt_line&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;tag&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;newhouse&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;kind&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;page&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;newhouse_list&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br>
&lt;p>而這邊取到的「建案基本資料」，會有像是 &amp;quot;名稱&amp;quot;、&amp;quot;地址&amp;quot;、&amp;quot;總價&amp;quot;、&amp;quot;單價&amp;quot;、&amp;quot;坪數&amp;quot;、&amp;quot;電話&amp;quot;、&amp;quot;特色&amp;quot;、&amp;quot;圖片&amp;quot;&amp;hellip;&amp;hellip;等等資訊，如果還需要進一步的詳細資訊，就要參考下一節的「取得建案詳情」。&lt;/p>
&lt;p>以下是我擷取其中一筆範例：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;hid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">121254&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;build_name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;太平洋之森&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;regionid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;sectionid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;region&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;台北市&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;section&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;中正區&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;addr_number&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;XX路一段123號&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;status&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;community_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">35980&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;build_type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;build_type_val&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;updatetime&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2024-10-01&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;address&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;台北市中正區XX路一段123號&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;address_new&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;中正區 XX路一段123號&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_full&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_full_720&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_full_sky&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;cover&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https:\/\/img2.591.com.tw\/house\/2020\/03\/15\/158426288485027607.jpg!400x300.s2.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;tag&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="s2">&amp;#34;近捷運&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;低公設&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;景觀宅&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;制震宅&amp;#34;&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;purpose_str&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;住家用&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;build_article&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;sale_status&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_upscale&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;active_rank&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;region&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;section&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;service_time&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;service_time_start&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;10:00&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;service_time_end&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;18:00&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_service_time&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;service_time&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;10:00-18:00&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;open_sell_year_month&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;shop_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">80&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;shop_name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;古亭生活圈&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_competitor_status&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;call_num&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;688&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;phone&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;0986-000-000&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;phone_ext&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;21230&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;area&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;3~4坪&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;room&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;三房(45坪),四房(50、66坪)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;price_unit_test&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;110~120&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;total_price_test&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;4388~6000&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;price&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;110~120&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;price_unit&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;萬\/坪&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_video&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;im_status&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;im_reply_avg_time&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">86400&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;im_question&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;entry_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">27&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;question_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">59&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;question&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;我對這個建案感興趣，可以介紹一下嗎?&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;ad_sort&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;expired_ad_sort&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;tel_num&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;688&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_vip&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_article&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>完整回覆資料範例：&lt;a href="https://github.com/it-jia/newhouse591_spider/blob/main/newhouse591_search.json" target="_blank" rel="noopener">
newhouse591_search.json (搜尋建案) | GitHub
&lt;/a>&lt;/p>
&lt;p>* 如果看到類似 &lt;code>\u53f0\u5317\u5e02&lt;/code> 的編碼，可以透過 Unicode 轉換即可。&lt;/p>
&lt;br/>
&lt;h3 id="範例程式">範例程式&lt;/h3>
&lt;p>使用 Python 撰寫 &amp;quot;搜尋建案&amp;quot; 的寫法如下，完整程式碼請至文末參考：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="k">def&lt;/span> &lt;span class="nf">search&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">filter_params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">None&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">sort_param&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">None&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">want_page&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34; 搜尋新建案
&lt;/span>&lt;span class="s2">
&lt;/span>&lt;span class="s2"> :param filter_params: 篩選參數
&lt;/span>&lt;span class="s2"> :param sort_params: 排序參數
&lt;/span>&lt;span class="s2"> :param want_page: 想要抓幾頁
&lt;/span>&lt;span class="s2"> :return total_count: requests 建案總數
&lt;/span>&lt;span class="s2"> :return house_list: requests 搜尋結果建案資料清單
&lt;/span>&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">total_count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="n">house_list&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;span class="n">page&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="c1"># 搜尋建案&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://newhouse.591.com.tw/home/housing/list-search&amp;#39;&lt;/span>
&lt;span class="n">params&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;device=pc&amp;amp;device_id=1234567890&amp;#39;&lt;/span>
&lt;span class="c1"># 篩選參數&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">filter_params&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">params&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;&amp;amp;{key}={value}&amp;#39;&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">filter_params&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">items&lt;/span>&lt;span class="p">()])&lt;/span>
&lt;span class="c1"># 排序參數&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">sort_param&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">params&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;&amp;amp;{key}={value}&amp;#39;&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">sort_param&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">items&lt;/span>&lt;span class="p">()])&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;referer&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">urllib&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">parse&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">quote&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://newhouse.591.com.tw/list?{params}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">while&lt;/span> &lt;span class="n">page&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">want_page&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">page&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;span class="n">params&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;page={page}&amp;amp;{params}&amp;#39;&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;Get 建案資料: {url}&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">params&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;請求失敗&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">break&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">total_count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;data&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;total&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="n">house_list&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extend&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;data&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;items&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="c1"># 判斷是否為最後一頁&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">page&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;data&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;total_page&amp;#39;&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;span class="k">break&lt;/span>
&lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">uniform&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">6&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="c1"># 隨機 delay 一段時間&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">total_count&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">house_list&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;!--adsense-->
&lt;h2 id="取得建案詳情">取得建案詳情&lt;/h2>
&lt;p>當上一步從搜尋結果找一個建案點進去後，會跳到此建案的頁面，呈現關於此建案的詳細資訊。&lt;br />
網址會類似這樣：&lt;a href="https://newhouse.591.com.tw/135743?roster_type=1">https://newhouse.591.com.tw/135743?roster_type=1&lt;/a>&lt;/p>
&lt;p>有關建案的詳細資訊又可以包含「建案資料」、「周邊機能」、「實價登錄」 (其他的各位有需要可以自己試試)，以下會再分別介紹這三個請求 API。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/newhouse591_spider/newhouse_page.jpg" alt="591 新建案 &amp;gt; 建案頁面" data-caption="591 新建案 &amp;gt; 建案頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
591 新建案 &amp;gt; 建案頁面
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="請求路徑與參數-1">請求路徑與參數&lt;/h3>
&lt;p>接下來我們分別從對應的頁面，一樣透過瀏覽器的 &lt;strong>開發人員工具&lt;/strong> (F12 或 Ctrl + Shift + i) &amp;gt; &lt;strong>Network&lt;/strong> 分頁，在 &amp;quot;Fetch/XHR&amp;quot; 分類中可以找到請求這些資料的路徑與參數。&lt;/p>
&lt;p>「建案資料」&lt;br />
url: &lt;code>https://bff.591.com.tw/v1/housing/detail-info?id={house_id}&amp;amp;is_auth=0&lt;/code>&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/newhouse591_spider/newhouse_detail.jpg" alt="591 新建案 &amp;gt; 建案詳情" data-caption="591 新建案 &amp;gt; 建案詳情" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
591 新建案 &amp;gt; 建案詳情
&lt;/figcaption>
&lt;/figure>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/newhouse591_spider/newhouse_detail_api.jpg" alt="591 新建案 &amp;gt; 建案詳情" data-caption="591 新建案 &amp;gt; 建案詳情" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
591 新建案 &amp;gt; 建案詳情
&lt;/figcaption>
&lt;/figure>
&lt;p>「周邊機能」&lt;br />
url: &lt;code>https://bff-newhouse.591.com.tw/v1/detail/surrounding?id={house_id}&amp;amp;is_auth=0&lt;/code>&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/newhouse591_spider/newhouse_surrounding_api.jpg" alt="591 新建案 &amp;gt; 周邊機能" data-caption="591 新建案 &amp;gt; 周邊機能" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
591 新建案 &amp;gt; 周邊機能
&lt;/figcaption>
&lt;/figure>
&lt;p>「實價登錄」&lt;br />
url: &lt;code>https://bff-market.591.com.tw/v1/price/list?community_id={community_id}&amp;amp;split_park=1&amp;amp;page=1&amp;amp;page_size=20&amp;amp;_source=0&lt;/code>&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/newhouse591_spider/newhouse_price_api.jpg" alt="591 新建案 &amp;gt; 實價登錄頁面" data-caption="591 新建案 &amp;gt; 實價登錄頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
591 新建案 &amp;gt; 實價登錄頁面
&lt;/figcaption>
&lt;/figure>
&lt;p>* 比較要注意的是，「實價登錄」網址使用的參數是 &amp;quot;community_id&amp;quot; (而不是 house_id)，所以程式裡面我還有先透過 BeautifulSoup，從網頁中找出 &amp;quot;community_id&amp;quot;。&lt;/p>
&lt;br/>
&lt;h3 id="回傳資料-1">回傳資料&lt;/h3>
&lt;p>回傳資料大致上也是與網頁上的一樣，關於此房屋的詳細資訊，你可以挑出需要的欄位來儲存，或進一步判斷執行其他動作。&lt;/p>
&lt;p>&lt;strong>建案資料&lt;/strong> 回傳資料範例：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;status&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;msg&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;請求成功&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;data&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;hid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">135743&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;regionid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;sectionid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;region&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;台北市&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;section&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;中山區&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;addr_number&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;xxxxxxxx&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;address&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;台北市中山區xxxxxxxx&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;build_name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;xxxx美術館&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;price_unit&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;price_total&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;price&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;build_type_name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;預售屋&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_upscale&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;status&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_online&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;layout&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;purpose_name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;住宅大樓&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;purpose_other_name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;住商用&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;deal_time&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;decorate&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;標準配備&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;reception_address&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;台北市中山區xxxxxxxx&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;park_price&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;base_area&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;build_area&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;terrace&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;ratio&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;35.38%&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;jbrate&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;41.9%&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;park_ratio&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;1:0.81&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;park_planning&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;平面式62個&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;park_piles&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;有充電設備（含預留）&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;park_style&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;暫無&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;manage_cost&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;structural_engine&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;RC鋼筋混凝土結構&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;land_division&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;商二特&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;households&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;1幢，1棟，73戶住家，4戶店面&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;floor&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;地上15層，地下4層&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;sell_time&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;down_pay&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;25%&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;lend_rate&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;75%&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;project_pay&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;direction_rule&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;朝南&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;manage_committee&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;build_intro&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;依現場為主&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;facility&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;remark&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;台北市有一座美術館即將誕生，純粹靜謐與藝術優雅...&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;room_rule&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;fav_num&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">224&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;share_num&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">377&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;meta&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;transportation&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;surrounding&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;building_design&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">],&lt;/span>
&lt;span class="err">...其他&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>周邊機能&lt;/strong> 回傳資料範例：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;status&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;msg&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;success&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;data&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;housing&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;hid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">135743&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;build_name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;xxxx美術館&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;address&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;台北市中山區xxxxxxxx&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;map&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">}&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;facility&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;traffic&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;education&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;distance&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;items&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">278987&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;私立新生幼兒園&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;distance&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">180&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;lat&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">25.0596716&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;lng&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">121.5280426&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;sub_type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;child&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">103&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;臺北市中山區吉林國民小學&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;distance&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">447&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;lat&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">25.05416379999999&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;lng&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">121.5292245&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;sub_type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;grade&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="err">...&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;count&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;grade&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;middle&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;child&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;university&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;life&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;other&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;disgust&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>實價登錄&lt;/strong> 回傳資料範例：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;status&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;data&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;items&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">6584759&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;date&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;113-06-11&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;trans_date&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2024-06-11&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;month&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;113-06&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;address&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;台北中山區xxxxxxxx&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;layout&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;3房&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;layout_v2&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;3房2廳&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;room_search&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;build_area&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;43.30坪&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;build_area_v&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;building_area&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;building_total_price&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;real_park_area&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;unit_price&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;src_unit_price&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;total_price&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;4,777萬&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;total_price_v&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;4,777&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;price_tips&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;context&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_special&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;has_park&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;1&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;unit_has_park&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;0&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;shift_floor&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;5樓&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;total_floor&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;15樓&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;build_purpose_str&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;住宅&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;real_park_total_price&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;395&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;real_park_total_price_v&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;community&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;trans_rep_year&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;113年&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;tag&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span> &lt;span class="s2">&amp;#34;低樓層&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;平面車位&amp;#34;&lt;/span> &lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;park_type_str&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;平面車位&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;match_type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;tips&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;park_count&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;history_trans_count&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_new_tag&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;assoc_type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;business_circle_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;build_date&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;original_shift_floor&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;5&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;original_total_floor&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">15&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="err">...&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;per_page&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">20&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;page&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;total_page&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;total&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">30&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;has_sale_ctrl&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;region_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;meta&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;trans_rep_years&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;address_condition&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;special_num&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">30&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;community_park&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="err">...&lt;/span> &lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>各個完整回覆資料範例：&lt;br />
&lt;a href="https://github.com/it-jia/newhouse591_spider/blob/main/newhouse591_build_detail.json" target="_blank" rel="noopener">
newhouse591_build_detail.json (建案資料) | GitHub
&lt;/a>&lt;br />
&lt;a href="https://github.com/it-jia/newhouse591_spider/blob/main/newhouse591_build_surrounding.json" target="_blank" rel="noopener">
newhouse591_build_surrounding.json (周邊機能) | GitHub
&lt;/a>&lt;br />
&lt;a href="https://github.com/it-jia/newhouse591_spider/blob/main/newhouse591_build_price.json" target="_blank" rel="noopener">
newhouse591_build_price.json (實價登錄) | GitHub
&lt;/a>&lt;/p>
&lt;p>* 如果看到類似 &lt;code>\u53f0\u5317\u5e02&lt;/code> 的編碼，可以透過 Unicode 轉換即可。&lt;/p>
&lt;br/>
&lt;h3 id="範例程式-1">範例程式&lt;/h3>
&lt;p>使用 Python 撰寫 &amp;quot;取得建案詳情&amp;quot; (包含 建案資料、周邊機能、實價登錄) 的寫法如下，完整程式碼請至文末參考：&lt;/p>
&lt;p>* 請求的 headers 內有 &lt;code>deviceid&lt;/code> 參數，原本以為可以不用給，但後來發現不給會導致取不到 &amp;ldquo;房屋詳情 &amp;gt; 周邊機能&amp;rdquo;，不過好像可以給隨意值就行 (可以在完整程式碼內查看)。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_newhouse_detail&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">house_id&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34; 取得建案詳情 (建案資料+周邊機能+實價登錄)
&lt;/span>&lt;span class="s2">
&lt;/span>&lt;span class="s2"> :param house_id: 建案 ID
&lt;/span>&lt;span class="s2"> :return house_detail: requests 建案詳細資料
&lt;/span>&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">house_detail&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;span class="c1"># 建案資料&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://bff.591.com.tw/v1/housing/detail-info?id={house_id}&amp;amp;is_auth=0&amp;#39;&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;referer&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://newhouse.591.com.tw/&amp;#39;&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;Get 建案資料: {url}&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;請求失敗&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">house_detail&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;detail&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;data&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">uniform&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="c1"># 隨機 delay 一段時間&lt;/span>
&lt;span class="c1"># 周邊機能&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://bff-newhouse.591.com.tw/v1/detail/surrounding?id={house_id}&amp;amp;is_auth=0&amp;#39;&lt;/span>
&lt;span class="c1"># https://bff-newhouse.591.com.tw/v1/detail/surrounding?id=120137&amp;amp;is_auth=0&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;referer&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://newhouse.591.com.tw/&amp;#39;&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;Get 周邊機能: {url}&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;請求失敗&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">house_detail&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;surrounding&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;data&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">uniform&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="c1"># 隨機 delay 一段時間&lt;/span>
&lt;span class="c1"># 實價登錄&lt;/span>
&lt;span class="c1"># 要先取得 community_id&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://newhouse.591.com.tw/{house_id}?roster_type=1&amp;#39;&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;請求失敗&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">soup&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">BeautifulSoup&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;html.parser&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">canonical_href&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;section.market a.status-table&amp;#39;&lt;/span>&lt;span class="p">)[&lt;/span>&lt;span class="s1">&amp;#39;href&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="n">community_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">canonical_href&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">split&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;/control/&amp;#34;&lt;/span>&lt;span class="p">)[&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">split&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;?&amp;#34;&lt;/span>&lt;span class="p">)[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="c1"># 抓取實價登錄清單&lt;/span>
&lt;span class="n">price_list&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;span class="n">page&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="k">while&lt;/span> &lt;span class="n">page&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">99&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">page&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://bff-market.591.com.tw/v1/price/list?community_id={community_id}&amp;amp;split_park=1&amp;amp;page={page}&amp;amp;page_size=20&amp;amp;_source=0&amp;#39;&lt;/span>
&lt;span class="c1"># https://bff-market.591.com.tw/v1/price/list?community_id=5935592&amp;amp;split_park=1&amp;amp;page=2&amp;amp;page_size=20&amp;amp;_source=0&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;referer&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://market.591.com.tw/&amp;#39;&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;Get 實價登錄: {url}&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;請求失敗&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">break&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">price_list&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extend&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;data&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;items&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="c1"># 判斷是否為最後一頁&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">page&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;data&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;total_page&amp;#39;&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;span class="k">break&lt;/span>
&lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">uniform&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="c1"># 隨機 delay 一段時間&lt;/span>
&lt;span class="n">house_detail&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;price&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">price_list&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">house_detail&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;!--adsense-->
&lt;h2 id="完整程式碼">完整程式碼&lt;/h2>
&lt;p>我將以上兩種請求整合起來到 class 中，並可以傳入不同的值來篩選，供需要的人參考。&lt;/p>
&lt;p>附上完整程式碼：&lt;a href="https://github.com/it-jia/newhouse591_spider/blob/main/newhouse591_spider.py" target="_blank" rel="noopener">
newhouse591_spider.py | GitHub
&lt;/a>&lt;/p>
&lt;br/>
&lt;!--adsense-->
&lt;br/>
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>這次我們改練習爬取 591 房屋交易網站的「新建案」，分別取得 &amp;quot;搜尋建案&amp;quot; 與 &amp;quot;建案詳情 (建案資料、周邊機能、實價登錄)&amp;quot; 的資訊。&lt;/p>
&lt;br/>
&lt;p>如果你正好是剛開始想學爬蟲的新手、想知道某網站如何爬取資料，歡迎查看 &lt;a href="https://blog.jiatool.com/series/Python%e7%b6%b2%e8%b7%af%e7%88%ac%e8%9f%b2%e5%af%a6%e4%be%8b/" target="_blank" rel="noopener">
Python網路爬蟲實例
&lt;/a>，或追蹤 FB 粉專『&lt;a href="https://www.facebook.com/jiatool" target="_blank" rel="noopener">
IT空間
&lt;/a>』~ 🔔&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;blockquote>
&lt;p>失敗不是終點，而是一個學習和成長的機會。&lt;br />
Failure is not the end, it&amp;rsquo;s an opportunity to learn and grow.&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/newhouse591_spider.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/newhouse591_spider_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Python</category><category>網路爬蟲</category><category>Python網路爬蟲實例</category></item><item><title>使用 RAG 打造個人知識庫，LlamaIndex 搭配 Gemini 模型</title><link>https://blog.jiatool.com/posts/rag_llamaindex_gemini/</link><pubDate>Sat, 13 Apr 2024 21:40:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sat, 13 Apr 2024 21:40:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/rag_llamaindex_gemini/</guid><description>前言 現在各式 LLM (大型語言模型) 滿天飛，你有沒有想過讓模型可以參考你自己的資料來回答呢？ 就像一個屬於你的 AI 知識庫管家，有問必答，還會標示引用文</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>現在各式 LLM (大型語言模型) 滿天飛，你有沒有想過讓模型可以參考你自己的資料來回答呢？&lt;br />
就像一個屬於你的 AI 知識庫管家，有問必答，還會標示引用文件的來源，讓你還可以回去原始文件參考。&lt;/p>
&lt;p>今天要來帶大家使用 Python 中的 LlamaIndex 套件，搭配免費的 Gemini 模型 API，打造屬於你自己的 RAG (Retrieval Augmented Generation) 個人知識庫✨。&lt;/p>
&lt;p>文章前半部會先介紹 RAG 架構 (什麼是 RAG、RAG 流程)，後半部再來使用 LlamaIndex 套件搭配 Gemini API 實際撰寫 RAG 架構程式碼。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/rag_llamaindex_gemini/llamaindex.jpg" alt="LlamaIndex" data-caption="LlamaIndex" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
LlamaIndex
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="什麼是-rag">什麼是 RAG？&lt;/h2>
&lt;p>RAG (Retrieval Augmented Generation，檢索增強生成) 是一種結合檢索搜尋和生成的自然語言處理架構。讓 LLM (大型語言模型)在生成回覆以前，從外部知識庫搜尋相關資料，並使用這些資訊生成更準確、更全面的答案。&lt;/p>
&lt;p>純粹的語言模型僅依賴於訓練語料，而 RAG 則能在生成時動態地加入額外知識，生成更準確、更相關、更具可靠性的輸出。&lt;/p>
&lt;br/>
&lt;p>來一個簡單的比喻，更容易理解：&lt;/p>
&lt;p>想像你是一位學生，要寫一篇關於台灣歷史的報告。&lt;/p>
&lt;p>一般 LLM 就像一個沒有外部資源的學生，只能憑藉自己的記憶和理解來寫報告，這可能會導致報告內容不準確、不全面，甚至出現錯誤。&lt;/p>
&lt;p>而 RAG 架構的學生，會先去圖書館查閱資料，會找到一些有關台灣歷史的資料，然後用這幾個相關資料來彙總、寫報告，這樣可以大大提高報告的準確性和全面性 (而且還能看到資料是從哪本書來的)。&lt;/p>
&lt;br/>
&lt;h3 id="rag-流程">RAG 流程&lt;/h3>
&lt;p>RAG 模型的架構主要可分成以下兩個階段：&lt;/p>
&lt;ol>
&lt;li>索引 (Indexing)：事前準備。從來源取得資料，並為其建立索引後儲存起來。&lt;/li>
&lt;li>檢索和生成 (Retrieval and generation)：使用者發問後，會從索引中搜尋相關資料，然後將其傳遞給模型並生成回覆。&lt;/li>
&lt;/ol>
&lt;p>對應我下方自己畫的流程圖，灰色部分(A~C)就是「索引」、藍色部分(1~5) 就是「檢索和生成」。&lt;/p>
&lt;br/>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/rag_llamaindex_gemini/rag_process.jpg" alt="RAG 流程" data-caption="RAG 流程" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
RAG 流程
&lt;/figcaption>
&lt;/figure>
&lt;h4 id="索引-indexing-階段">索引 (Indexing) 階段&lt;/h4>
&lt;ul>
&lt;li>A：將我們準備好的資料 (有可能是 公司內部文件、產品常見問答集、專業文獻、特定領域的專業知識 等等) 切分成較小的區塊(chunk)。因為區塊內容太多較難搜尋，而且 LLM 模型也有字數限制。&lt;/li>
&lt;li>B：將區塊的內容透過 Embedding model 轉換成向量(一組數字)，因為後續能比對資料間的向量距離，來判斷其相似程度。&lt;/li>
&lt;li>C：將轉換好的向量 (連同原始資料) 儲存至向量資料庫。&lt;/li>
&lt;/ul>
&lt;p>此流程只需要做一次就好，或者當原始資料有新增、更新時再執行即可。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/rag_llamaindex_gemini/indexing_process.jpg" alt="索引 (Indexing) 階段 流程 (圖片來源：LangChain 官網)" data-caption="索引 (Indexing) 階段 流程 (圖片來源：LangChain 官網)" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
索引 (Indexing) 階段 流程 (圖片來源：LangChain 官網)
&lt;/figcaption>
&lt;/figure>
&lt;h4 id="檢索和生成-retrieval-and-generation-階段">檢索和生成 (Retrieval and generation) 階段&lt;/h4>
&lt;ul>
&lt;li>1：將使用者的問題一樣透過 Embedding model 轉換成向量。&lt;/li>
&lt;li>2、3：拿問題向量去向量資料庫中找出相關的區塊。&lt;/li>
&lt;li>4、5：將 &amp;quot;相關區塊&amp;quot; 與 &amp;quot;使用者的問題&amp;quot; 一起給 LLM 生成答案。&lt;/li>
&lt;/ul>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/rag_llamaindex_gemini/retrieval_and_generation_process.jpg" alt="索引 (Indexing) 階段 流程 (圖片來源：LangChain 官網)" data-caption="索引 (Indexing) 階段 流程 (圖片來源：LangChain 官網)" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
索引 (Indexing) 階段 流程 (圖片來源：LangChain 官網)
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h3 id="使用-promt-enginerring-提示工程-或-fine-tuning-微調-不行嗎">使用 Promt Enginerring (提示工程) 或 Fine-tuning (微調) 不行嗎？&lt;/h3>
&lt;ul>
&lt;li>
&lt;p>Promt Enginerring (提示工程)：&lt;br />
透過一些提示(Promt)技巧來引導模型，輸出較高品質、正確性的結果。&lt;br />
例如：角色扮演、將複雜的任務拆分為更簡單的子任務、一步步思考&amp;hellip;&amp;hellip;等等。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Fine-tuning (微調)：&lt;br />
在已經預訓練過（pre-trained）的模型基礎上，用自己準備的資料進一步訓練，讓模型的輸出能夠更符合我們的預期。&lt;br />
例如：特定口吻、風格、格式、或加入自己的資料。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;br/>
&lt;p>RAG 相較於「Fine-tuning (微調)」或「Promt Enginerring (提示工程)」有幾點優勢：&lt;/p>
&lt;ul>
&lt;li>節省成本：不用像 Fine-tuning 需要訓練模型，節省時間成本、金錢成本(和硬體成本)。&lt;/li>
&lt;li>資料即時性：Fine-tuning 需要訓練模型，很難即時更新資料。&lt;/li>
&lt;li>資訊正確性：RAG 會參照外部資訊，有效減少虛假訊息，使得回答更加可信、準確。&lt;/li>
&lt;li>可信任性：RAG 回答可引用資訊來源，讓使用者可以審核答案，透明度高。&lt;/li>
&lt;li>安全、隱私性較高：RAG 是查找自己向量資料庫的知識，存取權限方面比較容易管控。相較之下，Fine-tuning 的較容易外洩。&lt;/li>
&lt;/ul>
&lt;br/>
&lt;p>不過其實也不是只能選一種，你可以結合其中兩種、甚至三種，來讓模型達到更好、更符合自己的生成結果。&lt;/p>
&lt;br/>
&lt;h2 id="什麼是-llamaindex">什麼是 LlamaIndex？&lt;/h2>
&lt;p>LlamaIndex 是一個資料框架，提供了抽象元件，可以更容易、更安全的使用 &amp;quot;資料提取&amp;quot;、&amp;quot;索引&amp;quot;、&amp;quot;查詢&amp;quot; 等功能。&lt;br />
適用於基於 LLM 的應用程序，主要是 RAG 架構 (也就是我們上面介紹的)。&lt;/p>
&lt;p>LlamaIndex 支援 Python 和 Typescript，本篇文章會使用 Python 來示範，不過概念上是一樣的。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/rag_llamaindex_gemini/llamaindex.jpg" alt="LlamaIndex" data-caption="LlamaIndex" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
LlamaIndex
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h2 id="撰寫程式">撰寫程式&lt;/h2>
&lt;p>需要先安裝 LlamaIndex 套件本身，以及我們要使用的 Gemini (LlamaIndex 已經有包好的介面可用)：&lt;/p>
&lt;p>* 後來發現 Gemini 的 Embedding 不支援中文&amp;hellip;所以改用 OpenAI 的 Embedding，因此最後的程式碼不需要 &lt;code>llama-index-embeddings-gemini&lt;/code>，可不用安裝。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">pip install llama-index
pip install llama-index-llms-gemini llama-index-embeddings-gemini llama-index-embeddings-openai
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="llm-和-embedding-model">LLM 和 Embedding model&lt;/h3>
&lt;p>在開始建構 RAG 架構之前，我們先來分別試一下 &lt;a href="https://docs.llamaindex.ai/en/stable/module_guides/models/llms/" target="_blank" rel="noopener">
LLM
&lt;/a> 和 &lt;a href="https://docs.llamaindex.ai/en/stable/module_guides/models/embeddings/" target="_blank" rel="noopener">
Embedding model
&lt;/a> 是否都正常。&lt;/p>
&lt;p>* Gemini 各種模型介紹與限制，可以看這篇官方的說明頁面：&lt;a href="https://ai.google.dev/models/gemini">https://ai.google.dev/models/gemini&lt;/a>&lt;br />
* 還沒有取得 Gemini API key 的人，可以參考我之前寫的文章：&lt;a href="https://blog.jiatool.com/posts/gemini_api/#%E5%89%B5%E5%BB%BA-api-key" target="_blank" rel="noopener">
如何使用 Google 的 Gemini 模型 API？
&lt;/a>&lt;br />
* Gemini API Key 可以像官方說明設定在環境變數中(&lt;code>GOOGLE_API_KEY&lt;/code>)，或者我這邊省麻煩直接寫在程式碼裡 (但就要注意不要不小心外洩了)。&lt;/p>
&lt;br/>
&lt;p>首先來試試 Gemini 本身 LLM，基本的 Complete 和 Chat 使用：&lt;/p>
&lt;p>* 以下參考官方提供的範例：&lt;a href="https://github.com/run-llama/llama_index/blob/main/docs/docs/examples/llm/gemini.ipynb">https://github.com/run-llama/llama_index/blob/main/docs/docs/examples/llm/gemini.ipynb&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="kn">from&lt;/span> &lt;span class="nn">llama_index.llms.gemini&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Gemini&lt;/span>
&lt;span class="kn">from&lt;/span> &lt;span class="nn">llama_index.core.llms&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">ChatMessage&lt;/span>
&lt;span class="n">GEMINI_API&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;YOUR_GEMINI_API&amp;gt;&amp;#34;&lt;/span>
&lt;span class="c1"># Complete&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Gemini&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">api_key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">GEMINI_API&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">complete&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;誰是王建民？&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 王建民，是一名台灣職業棒球投手。他曾效力於美國職棒大聯盟（MLB）的紐約洋基隊、華盛頓國民隊......&lt;/span>
&lt;span class="c1"># 如果想要改用最新的 gemini 1.5 pro 或調整參數，可以像這樣設定：&lt;/span>
&lt;span class="c1"># response = Gemini(&lt;/span>
&lt;span class="c1"># api_key=GEMINI_API,&lt;/span>
&lt;span class="c1"># model_name=&amp;#34;models/gemini-1.5-pro-latest&amp;#34;,&lt;/span>
&lt;span class="c1"># temperature=0.6,&lt;/span>
&lt;span class="c1"># max_tokens=1024&lt;/span>
&lt;span class="c1"># ).complete(&amp;#34;誰是王建民？&amp;#34;)&lt;/span>
&lt;span class="c1"># Chat&lt;/span>
&lt;span class="n">messages&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="n">ChatMessage&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">role&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;user&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;誰是王建民？&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;span class="n">ChatMessage&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">role&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;assistant&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;王建民是臺灣職業棒球運動員，擔任投手，在美國職棒大聯盟9個球季累計68勝。&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;span class="n">ChatMessage&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">role&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;user&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;他是哪裡人？&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Gemini&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">api_key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">GEMINI_API&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">chat&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">messages&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># assistant: 臺南市 王建民於1980年3月31日出生於臺灣臺南市。&lt;/span>
&lt;span class="c1"># Streaming complete (串流的方式)&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Gemini&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">api_key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">GEMINI_API&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">stream_complete&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;誰是王建民？&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">r&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">end&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;p>再來試試 Gemini 的 Embedding，將句子轉換為向量：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="c1"># Embedding&lt;/span>
&lt;span class="kn">from&lt;/span> &lt;span class="nn">llama_index.embeddings.gemini&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">GeminiEmbedding&lt;/span>
&lt;span class="n">GEMINI_API&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;YOUR_GEMINI_API&amp;gt;&amp;#34;&lt;/span>
&lt;span class="n">embed_model&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">GeminiEmbedding&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">api_key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">GEMINI_API&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">model_name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;models/embedding-001&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 或者想使用最新的模型&lt;/span>
&lt;span class="c1"># embed_model = GeminiEmbedding(api_key=GEMINI_API, model_name=&amp;#34;models/text-embedding-004&amp;#34;)&lt;/span>
&lt;span class="n">embeddings&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">embed_model&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_text_embedding&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;『IT空間』是一個有關基礎 IT 技術教學與分享的部落格。&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">embeddings&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># [0.042481236, 9.7126205e-05, -0.06401828, -0.03270765, 0.066297136, -0.019318093, ......&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>沒問題~ 測試都正常。 (← 真的嗎&amp;hellip;立旗)&lt;/p>
&lt;br/>
&lt;h3 id="rag">RAG&lt;/h3>
&lt;p>一開始，先給大家看完整程式碼。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">os.path&lt;/span>
&lt;span class="kn">from&lt;/span> &lt;span class="nn">llama_index.core&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="p">(&lt;/span>
&lt;span class="n">Settings&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">VectorStoreIndex&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">SimpleDirectoryReader&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">StorageContext&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">load_index_from_storage&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">)&lt;/span>
&lt;span class="kn">from&lt;/span> &lt;span class="nn">llama_index.llms.gemini&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Gemini&lt;/span>
&lt;span class="c1"># from llama_index.embeddings.gemini import GeminiEmbedding&lt;/span>
&lt;span class="kn">from&lt;/span> &lt;span class="nn">llama_index.embeddings.openai&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">OpenAIEmbedding&lt;/span>
&lt;span class="n">PERSIST_DIR&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;./storage&amp;#34;&lt;/span>
&lt;span class="n">GEMINI_API&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;YOUR_GEMINI_API&amp;gt;&amp;#34;&lt;/span>
&lt;span class="n">OPENAI_API&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;YOUR_OPENAI_API&amp;gt;&amp;#34;&lt;/span>
&lt;span class="c1"># 更改全域配置&lt;/span>
&lt;span class="c1"># Settings.embed_model = GeminiEmbedding(model_name=&amp;#34;models/embedding-001&amp;#34;, api_key=GEMINI_API)&lt;/span>
&lt;span class="n">Settings&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">embed_model&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">OpenAIEmbedding&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">api_key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">OPENAI_API&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">Settings&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">llm&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Gemini&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">api_key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">GEMINI_API&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">path&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exists&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">PERSIST_DIR&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="n">documents&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">SimpleDirectoryReader&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;docs&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">load_data&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">index&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">VectorStoreIndex&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_documents&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">documents&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">index&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">storage_context&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">persist&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">persist_dir&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">PERSIST_DIR&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">storage_context&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">StorageContext&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_defaults&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">persist_dir&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">PERSIST_DIR&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">index&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">load_index_from_storage&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">storage_context&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">query_engine&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">index&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">as_query_engine&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">query_engine&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;動畫《葬送的芙莉蓮》中的芙莉蓮角色是由哪位聲優配音？&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># response = query_engine.query(&amp;#34;葬送的芙莉蓮是什麼？&amp;#34;)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>這程式主要的部分是從官方文件來的：&lt;a href="https://docs.llamaindex.ai/en/stable/getting_started/starter_example/" target="_blank" rel="noopener">
Starter Tutorial (OpenAI)
&lt;/a>&lt;/p>
&lt;p>可以看到，其實透過 LlamaIndex 框架來實作 RAG 架構，根本不用幾行程式碼。&lt;br />
而且如果你是使用 OpenAI API，上方 Gemini 的部分甚至可以省略 (它預設是 OpenAI API)。還有中間 &lt;code>else&lt;/code> 的部分也可以省略 (只是變成你每次執行都還要再 Embedding)，所以實際上所需的程式碼更少。&lt;/p>
&lt;br/>
&lt;br/>
&lt;p>首先，我們先準備好原始資料，並放到 &lt;code>docs&lt;/code> 資料夾內(這名稱是在程式碼內自訂的)。&lt;/p>
&lt;p>我就拿我最近在看、而且前陣子很火紅的日本動畫《葬送的芙莉蓮》當範例。&lt;br />
我們去維基百科複製 &lt;a href="https://zh.wikipedia.org/zh-tw/%e8%91%ac%e9%80%81%e7%9a%84%e8%8a%99%e8%8e%89%e8%93%ae" target="_blank" rel="noopener">
葬送的芙莉蓮
&lt;/a> 的內容，並存到 &lt;code>docs&lt;/code> 資料夾底下的 &lt;code>frieren.txt&lt;/code>。&lt;/p>
&lt;pre>&lt;code>rag
├ docs
│ └ frieren.txt
│
└ llamaindex_rag.py
&lt;/code>&lt;/pre>&lt;br/>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="c1"># 更改全域配置&lt;/span>
&lt;span class="c1"># Settings.embed_model = GeminiEmbedding(model_name=&amp;#34;models/embedding-001&amp;#34;, api_key=GEMINI_API)&lt;/span>
&lt;span class="n">Settings&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">embed_model&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">OpenAIEmbedding&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">api_key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">OPENAI_API&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">Settings&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">llm&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Gemini&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">api_key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">GEMINI_API&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>如同剛剛說的，LlamaIndex 框架預設的 LLM、Embedding model 都是採用 OpenAI API，如果你想要改變全域的配置，需透過 &lt;a href="https://docs.llamaindex.ai/en/stable/module_guides/supporting_modules/settings/" target="_blank" rel="noopener">
&lt;code>Settings&lt;/code> 對象
&lt;/a>。&lt;/p>
&lt;br/>
&lt;p>這邊我原本是打算 LLM 和 Embedding model 都使用 Gemini 的，結果我實際跑起來發覺結果很怪，每次找出來最相近的段落都是那兩個，網路查了才發現，Gemini 的 &lt;code>embedding-001&lt;/code> 好像不支援中文&amp;hellip;&amp;hellip;&lt;br />
而且就算我改嘗試前幾天 Google 發布的新一代文字嵌入模型 &lt;code>text-embedding-004&lt;/code>，也還是不行。&lt;/p>
&lt;p>沒辦法，最後在 Embedding 的部分還是改回使用 OpenAI 的 &lt;code>text-embedding-ada-002&lt;/code>，所以也才同時需要 Gemini 和 OpenAI 的 API Key。&lt;/p>
&lt;p>* OpenAI 的 API key 申請可以參考我之前的文章 (&lt;a href="https://blog.jiatool.com/posts/chatgpt_api/" target="_blank" rel="noopener">
OpenAI ChatGPT API 如何使用？(附上 Python 範例程式)
&lt;/a>)，但因為已經過一年了，實際介面與步驟可能有點不太一樣。&lt;/p>
&lt;br/>
&lt;br/>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">PERSIST_DIR&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;./storage&amp;#34;&lt;/span>
&lt;span class="o">...&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">path&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exists&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">PERSIST_DIR&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="n">documents&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">SimpleDirectoryReader&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;docs&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">load_data&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">index&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">VectorStoreIndex&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_documents&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">documents&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">index&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">storage_context&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">persist&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">persist_dir&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">PERSIST_DIR&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">storage_context&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">StorageContext&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_defaults&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">persist_dir&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">PERSIST_DIR&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">index&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">load_index_from_storage&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">storage_context&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>這邊的 &lt;code>if-else&lt;/code> 是在第一次執行會去讀取 &lt;code>docs&lt;/code> 資料夾下所有的檔案，將內容切割後做 Embedding (轉向量)，並把結果儲存下來，避免每次執行都要花時間、花金錢做 Embedding。&lt;/p>
&lt;p>第二次之後執行，如果 &lt;code>./storage&lt;/code> 資料夾存在，我們就當已經做過 Embedding，直接從 &lt;code>./storage&lt;/code> 讀取向量資料。&lt;/p>
&lt;p>因此如果我們有修改、新增原始資料，需要把 &lt;code>./storage&lt;/code> 資料夾刪除，讓它再重新 Embedding 一次。&lt;/p>
&lt;br/>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">query_engine&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">index&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">as_query_engine&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">query_engine&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;動畫《葬送的芙莉蓮》中的芙莉蓮角色是由哪位聲優配音？&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># response = query_engine.query(&amp;#34;葬送的芙莉蓮是什麼？&amp;#34;)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>從原始資料讀取並轉換成向量之後，我們就可以開始詢問它問題。&lt;/p>
&lt;p>例如我問它「動畫《葬送的芙莉蓮》中的芙莉蓮角色是由哪位聲優配音？」，他會回答「種崎敦美」✨。&lt;br />
非常正確~~🎉&lt;/p>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>以上各個步驟的元件都有很多不同的可以替換，像是 LLM 可以換成 Azure OpenAI、Anthropic 的 Claude 3 Opus、生成超快的 Groq、本地跑 Ollama、甚至自訂 LLM 模型&amp;hellip;&amp;hellip;等等 (&lt;a href="https://docs.llamaindex.ai/en/stable/module_guides/models/llms/modules/" target="_blank" rel="noopener">
詳細支援列表
&lt;/a>)。還有文件載入方面，也可以連接 PDF、CSV、HTML、Google Docs 等等多種來源。&lt;/p>
&lt;p>以上資訊可以在 &lt;a href="https://docs.llamaindex.ai/en/stable/examples/" target="_blank" rel="noopener">
官方文件 Examples
&lt;/a> 和 &lt;a href="https://llamahub.ai/" target="_blank" rel="noopener">
LlamaHub
&lt;/a> 裡面找到。&lt;/p>
&lt;br/>
&lt;p>學習完最基礎的範例後，各位可以從官方文件的 &lt;a href="https://docs.llamaindex.ai/en/stable/getting_started/customization/" target="_blank" rel="noopener">
常見問題 (FAQ)
&lt;/a> 來針對你感興趣的部分，進一步學習、嘗試。或者先去看看官方文件的 &lt;a href="https://docs.llamaindex.ai/en/stable/understanding/" target="_blank" rel="noopener">
Learn
&lt;/a> 有針對以上不同的步驟做詳細的說明。&lt;/p>
&lt;br/>
&lt;p>我後來整理一篇「&lt;a href="https://blog.jiatool.com/posts/rag_query_transformations" target="_blank" rel="noopener">
Query Transformations 技巧幫助 RAG 優化問題，提升檢索效果
&lt;/a>」。&lt;/p>
&lt;p>有時候我們的問題太廣、太模糊，&lt;br />
導致找不出相關資料，甚至找到錯誤的資料，造成回應結果不靠譜。&lt;br />
有一種做法是將問題先請 LLM 做 &amp;ldquo;改寫&amp;rdquo;，再送進去檢索，那就是「查詢轉換 (Query Transformations)」技巧。&lt;/p>
&lt;br/>
&lt;br/>
&lt;p>如果對於 生成式 AI 有興趣的讀者，記得追蹤『&lt;a href="https://www.facebook.com/jiatool" target="_blank" rel="noopener">
IT空間
&lt;/a>』FB 粉專，才不會錯過最新的發文通知呦~🔔&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;blockquote>
&lt;p>如果想的太多，就會做的很少&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/rag_llamaindex_gemini.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/rag_llamaindex_gemini_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>RAG</category><category>LlamaIndex</category><category>LLM</category><category>AI</category><category>人工智慧</category><category>Python</category><category>分享</category></item><item><title>[Python爬蟲實例] Anue 鉅亨網：爬取最新財經新聞</title><link>https://blog.jiatool.com/posts/cnyes_news_spider/</link><pubDate>Sat, 23 Mar 2024 20:40:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sat, 23 Mar 2024 20:40:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/cnyes_news_spider/</guid><description>前言 好久沒有更新 Python網路爬蟲實例系列 文章了，今天換來看財經與投資的相關新聞。 「Anue 鉅亨網」提供國內外財經相關資訊，我們來透過 Python 網</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>好久沒有更新 &lt;a href="https://blog.jiatool.com/series/Python%e7%b6%b2%e8%b7%af%e7%88%ac%e8%9f%b2%e5%af%a6%e4%be%8b/" target="_blank" rel="noopener">
Python網路爬蟲實例系列
&lt;/a> 文章了，今天換來看財經與投資的相關新聞。&lt;/p>
&lt;p>「Anue 鉅亨網」提供國內外財經相關資訊，我們來透過 Python 網路爬蟲抓取&lt;a href="https://news.cnyes.com/news/cat/headline" target="_blank" rel="noopener">
即時頭條新聞
&lt;/a>，掌握最新消息。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/cnyes_news_spider/cnyes_news_page.jpg" alt="圖片來源：Anue鉅亨網 - 即時頭條新聞" data-caption="圖片來源：Anue鉅亨網 - 即時頭條新聞" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
圖片來源：Anue鉅亨網 - 即時頭條新聞
&lt;/figcaption>
&lt;/figure>
&lt;p>備註：此文僅教育學習，切勿用作商業用途，個人實作皆屬個人行為，本作者不負任何法律責任&lt;/p>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="套件">套件&lt;/h2>
&lt;p>此次 Python 爬蟲主要使用到的套件：&lt;/p>
&lt;ul>
&lt;li>Requests [&lt;a href="https://requests.readthedocs.io/en/master/" target="_blank" rel="noopener">
Doc
&lt;/a>] [&lt;a href="https://github.com/psf/requests" target="_blank" rel="noopener">
GitHub
&lt;/a>]&lt;/li>
&lt;/ul>
&lt;p>安裝&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">pip install requests
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="流程說明">流程說明&lt;/h2>
&lt;h3 id="找找新聞如何被載入">找找新聞如何被載入&lt;/h3>
&lt;p>首先進入 Anue 鉅亨網 的 &lt;a href="https://news.cnyes.com/news/cat/headline" target="_blank" rel="noopener">
即時新聞列表
&lt;/a> 網頁，來觀察看看其新聞列表載入方式。&lt;/p>
&lt;p>可以試著將滾輪往下滾，網頁會一直往下，它新聞也會被一直載入進來，推測應該是採用動態載入的方式。&lt;/p>
&lt;p>打開瀏覽器的 &lt;strong>開發人員工具&lt;/strong> (F12 或 Ctrl + Shift + i)，切換到 &amp;quot;Network&amp;quot; &amp;gt; &amp;quot;Fetch/XHR&amp;quot;，往下滾動新聞頁面，會尋找到有個 &lt;code>headline?page=2&amp;amp;limit=30...&lt;/code> 的請求，並且點開後在 &amp;quot;Preview&amp;quot; 分頁查看，就會發現裡面包含新聞的相關資料。&lt;/p>
&lt;p>那就沒錯了，這就是我們想要抓取的部分！💪&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/cnyes_news_spider/get_news_ajax_preview.jpg" alt="請求 &amp;#34;Preview&amp;#34; 分頁，找到我們想要的資料" data-caption="請求 &amp;#34;Preview&amp;#34; 分頁，找到我們想要的資料" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
請求 &amp;#34;Preview&amp;#34; 分頁，找到我們想要的資料
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="請求方式與參數">請求方式與參數&lt;/h3>
&lt;p>切換回 &amp;quot;Headers&amp;quot; 分頁，看一下此資料請求的方式與網址。&lt;br />
使用 &lt;code>GET&lt;/code> 請求方式，網址類似 &lt;code>https://api.cnyes.com/media/api/v1/newslist/category/headline?page=2&amp;amp;limit=30&amp;amp;isCategoryHeadline=1&amp;amp;startAt=1710295609&amp;amp;endAt=1711159609&lt;/code>。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/cnyes_news_spider/get_news_ajax_header.jpg" alt="請求 &amp;#34;Headers&amp;#34; 分頁" data-caption="請求 &amp;#34;Headers&amp;#34; 分頁" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
請求 &amp;#34;Headers&amp;#34; 分頁
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>我們先來觀察網址後方的參數代表甚麼意思。&lt;/p>
&lt;p>&lt;code>page=2&amp;amp;limit=30&amp;amp;isCategoryHeadline=1&amp;amp;startAt=1710295609&amp;amp;endAt=1711159609&lt;/code>&lt;/p>
&lt;p>&lt;code>page&lt;/code> 和 &lt;code>limit&lt;/code> 很明顯就是代表「頁數」跟「一頁幾則新聞」。&lt;br />
(如果不太懂這兩個參數，可以回去看看我之前寫的文章：&lt;a href="https://blog.jiatool.com/posts/web_crawler_page_method" target="_blank" rel="noopener">
(圖解) 網路爬蟲 API 常見的 3 種「翻頁」方式
&lt;/a>)&lt;/p>
&lt;p>&lt;code>isCategoryHeadline&lt;/code> 可以代入 0 或 1，差別是回傳資料的 &lt;code>coverSrc&lt;/code> 欄位裡面有沒有包含新聞封面圖片。&lt;/p>
&lt;p>而 &lt;code>startAt&lt;/code> 和 &lt;code>endAt&lt;/code> 是新聞範圍的時間 (以時間戳格式)，並且有限定指定的時間只能兩年內。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/cnyes_news_spider/parameter_publishat.jpg" alt="新聞時間範圍有限定兩年內" data-caption="新聞時間範圍有限定兩年內" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='350px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:350px;height:;"/>
&lt;figcaption style="text-align: center;">
新聞時間範圍有限定兩年內
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>這些參數就算不代入，也會有預設值，所以以下程式範例只使用到 &lt;code>page&lt;/code> 和 &lt;code>limit&lt;/code> 參數來示範教學。&lt;/p>
&lt;h3 id="回傳內容">回傳內容&lt;/h3>
&lt;p>可以將網址貼到瀏覽器的網址欄位中，查看回傳的資料。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/cnyes_news_spider/news_json_raw.jpg" alt="請求回傳資料" data-caption="請求回傳資料" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
請求回傳資料
&lt;/figcaption>
&lt;/figure>
&lt;p>items 裡欄位代表意思如下表：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>欄位&lt;/th>
&lt;th>代表意思&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>total&lt;/code>&lt;/td>
&lt;td>全部新聞總數&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>per_page&lt;/code>&lt;/td>
&lt;td>一頁新聞數&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>current_page&lt;/code>&lt;/td>
&lt;td>當前頁數&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>last_page&lt;/code>&lt;/td>
&lt;td>最後頁數&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>prev_page_url&lt;/code>&lt;/td>
&lt;td>前一頁網址&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>next_page_url&lt;/code>&lt;/td>
&lt;td>下一頁網址&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>from&lt;/code>&lt;/td>
&lt;td>此頁新聞第一筆&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>to&lt;/code>&lt;/td>
&lt;td>此頁新聞最後一筆&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>data&lt;/code>&lt;/td>
&lt;td>各新聞資訊&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>而 items 裡的 data 新聞資訊，有包含新聞標題、內文、關鍵字、發布時間、分類&amp;hellip;&amp;hellip;等等。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt"> 10
&lt;/span>&lt;span class="lnt"> 11
&lt;/span>&lt;span class="lnt"> 12
&lt;/span>&lt;span class="lnt"> 13
&lt;/span>&lt;span class="lnt"> 14
&lt;/span>&lt;span class="lnt"> 15
&lt;/span>&lt;span class="lnt"> 16
&lt;/span>&lt;span class="lnt"> 17
&lt;/span>&lt;span class="lnt"> 18
&lt;/span>&lt;span class="lnt"> 19
&lt;/span>&lt;span class="lnt"> 20
&lt;/span>&lt;span class="lnt"> 21
&lt;/span>&lt;span class="lnt"> 22
&lt;/span>&lt;span class="lnt"> 23
&lt;/span>&lt;span class="lnt"> 24
&lt;/span>&lt;span class="lnt"> 25
&lt;/span>&lt;span class="lnt"> 26
&lt;/span>&lt;span class="lnt"> 27
&lt;/span>&lt;span class="lnt"> 28
&lt;/span>&lt;span class="lnt"> 29
&lt;/span>&lt;span class="lnt"> 30
&lt;/span>&lt;span class="lnt"> 31
&lt;/span>&lt;span class="lnt"> 32
&lt;/span>&lt;span class="lnt"> 33
&lt;/span>&lt;span class="lnt"> 34
&lt;/span>&lt;span class="lnt"> 35
&lt;/span>&lt;span class="lnt"> 36
&lt;/span>&lt;span class="lnt"> 37
&lt;/span>&lt;span class="lnt"> 38
&lt;/span>&lt;span class="lnt"> 39
&lt;/span>&lt;span class="lnt"> 40
&lt;/span>&lt;span class="lnt"> 41
&lt;/span>&lt;span class="lnt"> 42
&lt;/span>&lt;span class="lnt"> 43
&lt;/span>&lt;span class="lnt"> 44
&lt;/span>&lt;span class="lnt"> 45
&lt;/span>&lt;span class="lnt"> 46
&lt;/span>&lt;span class="lnt"> 47
&lt;/span>&lt;span class="lnt"> 48
&lt;/span>&lt;span class="lnt"> 49
&lt;/span>&lt;span class="lnt"> 50
&lt;/span>&lt;span class="lnt"> 51
&lt;/span>&lt;span class="lnt"> 52
&lt;/span>&lt;span class="lnt"> 53
&lt;/span>&lt;span class="lnt"> 54
&lt;/span>&lt;span class="lnt"> 55
&lt;/span>&lt;span class="lnt"> 56
&lt;/span>&lt;span class="lnt"> 57
&lt;/span>&lt;span class="lnt"> 58
&lt;/span>&lt;span class="lnt"> 59
&lt;/span>&lt;span class="lnt"> 60
&lt;/span>&lt;span class="lnt"> 61
&lt;/span>&lt;span class="lnt"> 62
&lt;/span>&lt;span class="lnt"> 63
&lt;/span>&lt;span class="lnt"> 64
&lt;/span>&lt;span class="lnt"> 65
&lt;/span>&lt;span class="lnt"> 66
&lt;/span>&lt;span class="lnt"> 67
&lt;/span>&lt;span class="lnt"> 68
&lt;/span>&lt;span class="lnt"> 69
&lt;/span>&lt;span class="lnt"> 70
&lt;/span>&lt;span class="lnt"> 71
&lt;/span>&lt;span class="lnt"> 72
&lt;/span>&lt;span class="lnt"> 73
&lt;/span>&lt;span class="lnt"> 74
&lt;/span>&lt;span class="lnt"> 75
&lt;/span>&lt;span class="lnt"> 76
&lt;/span>&lt;span class="lnt"> 77
&lt;/span>&lt;span class="lnt"> 78
&lt;/span>&lt;span class="lnt"> 79
&lt;/span>&lt;span class="lnt"> 80
&lt;/span>&lt;span class="lnt"> 81
&lt;/span>&lt;span class="lnt"> 82
&lt;/span>&lt;span class="lnt"> 83
&lt;/span>&lt;span class="lnt"> 84
&lt;/span>&lt;span class="lnt"> 85
&lt;/span>&lt;span class="lnt"> 86
&lt;/span>&lt;span class="lnt"> 87
&lt;/span>&lt;span class="lnt"> 88
&lt;/span>&lt;span class="lnt"> 89
&lt;/span>&lt;span class="lnt"> 90
&lt;/span>&lt;span class="lnt"> 91
&lt;/span>&lt;span class="lnt"> 92
&lt;/span>&lt;span class="lnt"> 93
&lt;/span>&lt;span class="lnt"> 94
&lt;/span>&lt;span class="lnt"> 95
&lt;/span>&lt;span class="lnt"> 96
&lt;/span>&lt;span class="lnt"> 97
&lt;/span>&lt;span class="lnt"> 98
&lt;/span>&lt;span class="lnt"> 99
&lt;/span>&lt;span class="lnt">100
&lt;/span>&lt;span class="lnt">101
&lt;/span>&lt;span class="lnt">102
&lt;/span>&lt;span class="lnt">103
&lt;/span>&lt;span class="lnt">104
&lt;/span>&lt;span class="lnt">105
&lt;/span>&lt;span class="lnt">106
&lt;/span>&lt;span class="lnt">107
&lt;/span>&lt;span class="lnt">108
&lt;/span>&lt;span class="lnt">109
&lt;/span>&lt;span class="lnt">110
&lt;/span>&lt;span class="lnt">111
&lt;/span>&lt;span class="lnt">112
&lt;/span>&lt;span class="lnt">113
&lt;/span>&lt;span class="lnt">114
&lt;/span>&lt;span class="lnt">115
&lt;/span>&lt;span class="lnt">116
&lt;/span>&lt;span class="lnt">117
&lt;/span>&lt;span class="lnt">118
&lt;/span>&lt;span class="lnt">119
&lt;/span>&lt;span class="lnt">120
&lt;/span>&lt;span class="lnt">121
&lt;/span>&lt;span class="lnt">122
&lt;/span>&lt;span class="lnt">123
&lt;/span>&lt;span class="lnt">124
&lt;/span>&lt;span class="lnt">125
&lt;/span>&lt;span class="lnt">126
&lt;/span>&lt;span class="lnt">127
&lt;/span>&lt;span class="lnt">128
&lt;/span>&lt;span class="lnt">129
&lt;/span>&lt;span class="lnt">130
&lt;/span>&lt;span class="lnt">131
&lt;/span>&lt;span class="lnt">132
&lt;/span>&lt;span class="lnt">133
&lt;/span>&lt;span class="lnt">134
&lt;/span>&lt;span class="lnt">135
&lt;/span>&lt;span class="lnt">136
&lt;/span>&lt;span class="lnt">137
&lt;/span>&lt;span class="lnt">138
&lt;/span>&lt;span class="lnt">139
&lt;/span>&lt;span class="lnt">140
&lt;/span>&lt;span class="lnt">141
&lt;/span>&lt;span class="lnt">142
&lt;/span>&lt;span class="lnt">143
&lt;/span>&lt;span class="lnt">144
&lt;/span>&lt;span class="lnt">145
&lt;/span>&lt;span class="lnt">146
&lt;/span>&lt;span class="lnt">147
&lt;/span>&lt;span class="lnt">148
&lt;/span>&lt;span class="lnt">149
&lt;/span>&lt;span class="lnt">150
&lt;/span>&lt;span class="lnt">151
&lt;/span>&lt;span class="lnt">152
&lt;/span>&lt;span class="lnt">153
&lt;/span>&lt;span class="lnt">154
&lt;/span>&lt;span class="lnt">155
&lt;/span>&lt;span class="lnt">156
&lt;/span>&lt;span class="lnt">157
&lt;/span>&lt;span class="lnt">158
&lt;/span>&lt;span class="lnt">159
&lt;/span>&lt;span class="lnt">160
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;items&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;total&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1007&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;per_page&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">30&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;current_page&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;last_page&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">34&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;next_page_url&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;/media/api/v1/newslist/category/headline?limit=30&amp;amp;page=2&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;prev_page_url&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;from&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;to&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">30&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;data&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;newsId&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">5501189&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;title&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;OpenAI旗下Sora進軍好萊塢電影產業&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;amp;lt;p&amp;amp;gt;市場週五 (22 日) 傳出，OpenAI 計劃進軍電影業，已安排下週與好萊塢工作室和人才機構舉行會議，鼓勵電影製作人和工作室在工作中使用人工智慧。他們已經向一些大牌演員和導演推廣了人工智慧影片製作軟體 Sora。&amp;amp;lt;/p&amp;amp;gt;\n\n&amp;amp;lt;p&amp;amp;gt;OpenAI 試圖電影業人員構建娛樂產業的合作夥伴關係、並鼓勵眾多製片公司將 OpenAI 的新款 AI 影音生成器融入它們的工作中。&amp;amp;lt;/p&amp;amp;gt;\n\n&amp;amp;lt;p&amp;amp;gt;OpenAI 向好萊塢推廣其文字生成影音 AI 服務 Sora，OpenAI CEO Altman 已經在奧斯卡電影節週末出席洛杉磯的多場派對。&amp;amp;lt;/p&amp;amp;gt;\n\n&amp;amp;lt;figure&amp;amp;gt;&amp;amp;lt;img alt=&amp;amp;quot;(圖片：翻攝smartprix)&amp;amp;quot; data-height=&amp;amp;quot;416&amp;amp;quot; data-mime=&amp;amp;quot;image/jpeg&amp;amp;quot; data-ratio=&amp;amp;quot;1.8269230769230769&amp;amp;quot; data-src-m=&amp;amp;quot;https://cimg.cnyes.cool/prod/news/5501189/m/961b1580a9294bfceeccfc6b86fec545.jpg&amp;amp;quot; data-width=&amp;amp;quot;760&amp;amp;quot; src=&amp;amp;quot;https://cimg.cnyes.cool/prod/news/5501189/l/961b1580a9294bfceeccfc6b86fec545.jpg&amp;amp;quot;&amp;amp;gt;\n&amp;amp;lt;figcaption&amp;amp;gt;OpenAI 旗下 Sora 進軍好萊塢，下周將開會 (圖：OpenAI)&amp;amp;lt;/figcaption&amp;amp;gt;\n&amp;amp;lt;/figure&amp;amp;gt;\n\n&amp;amp;lt;p&amp;amp;gt;Sora 是 Open AI 公司繼文本模型 ChatGPT、圖像模型 Dall-E 撼動了全世界之後，於今年 2 月 15 日發布的文生影像模型，可根據文字描述產生 60 秒的影像，這引發好萊塢巨大震撼。&amp;amp;lt;/p&amp;amp;gt;\n\n&amp;amp;lt;p&amp;amp;gt;電影攝影師、動畫師和電影製片對其生成的影音品質大感震驚。Sora 目前只能生成約一分鐘的影片，且缺乏對物理作用的了解，但還在持續學習，而其學習方式正是好萊塢和其他產業的最擔心之處&amp;amp;lt;/p&amp;amp;gt;\n\n&amp;amp;lt;p&amp;amp;gt;好萊塢導演暨製片人派瑞已率先發出警告。他在看過 Sora 影音後已「無限期」暫緩 8 億美元的工作室擴展計畫。&amp;amp;lt;/p&amp;amp;gt;\n\n&amp;amp;lt;p&amp;amp;gt;大華國際投顧阮蕙慈表示，對於投資人來說，Sora 的橫空出世絕對是要留意的重要產業趨勢之一，其影響性又遠大於其他現有的生成式 AI 相關應用。Sora 的誕生，意味著影像生成門檻大幅降低，不僅對廣告、影視、短視頻等相關行業引發巨大變革，而且對於算力、傳輸速度、儲存空間的需求更是現有好幾倍的成長。&amp;amp;lt;/p&amp;amp;gt;\n&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;hasCoverPhoto&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isIndex&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;summary&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;市場週五 (22 日) 傳出，OpenAI 計劃進軍電影業，已安排下週與好萊塢工作室和人才機構舉行會議，鼓勵電影製作人和工作室在工作中使用人工智慧。他們已經向一些大牌演員和導演推廣了人工智慧影片製作軟體 Sora。&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isCategoryHeadline&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[],&lt;/span>
&lt;span class="nt">&amp;#34;video&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;payment&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;feature&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;otherProduct&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[],&lt;/span>
&lt;span class="nt">&amp;#34;source&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isOutsource&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;keyword&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="s2">&amp;#34;Sora&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;OpenAI&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;ChatGPT&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;好萊塢&amp;#34;&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;is24h&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;publishAt&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1711137477&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;coverSrc&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;xs&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;src&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://cimg.cnyes.cool/prod/news/5501189/xs/50120aeff052a284a8c5136c4cb945a5.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;width&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">100&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;height&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">56&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;s&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;src&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://cimg.cnyes.cool/prod/news/5501189/s/50120aeff052a284a8c5136c4cb945a5.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;width&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">180&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;height&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">101&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;m&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;src&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://cimg.cnyes.cool/prod/news/5501189/m/50120aeff052a284a8c5136c4cb945a5.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;width&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">380&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;height&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">214&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;l&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;src&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://cimg.cnyes.cool/prod/news/5501189/l/50120aeff052a284a8c5136c4cb945a5.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;width&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">640&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;height&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">360&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;xl&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;src&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://cimg.cnyes.cool/prod/news/5501189/xl/50120aeff052a284a8c5136c4cb945a5.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;width&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">960&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;height&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">540&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;xxl&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;src&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://cimg.cnyes.cool/prod/news/5501189/xl/50120aeff052a284a8c5136c4cb945a5.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;width&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">960&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;height&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">540&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;abTesting&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;categoryId&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">831&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;categoryName&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;美股雷達&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;columnists&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;fundCategoryAbbr&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[],&lt;/span>
&lt;span class="nt">&amp;#34;etf&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[],&lt;/span>
&lt;span class="nt">&amp;#34;fbShare&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;fbComment&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;fbCommentPluginCount&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;newsId&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">5501177&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;title&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;傳蘋果放棄自研手錶Micro LED計畫 裁員數十位工程師&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;amp;lt;p&amp;amp;gt;根據彭博周五 (22 日) 援引知情人士消息報導，蘋果正逐步結束自研智慧手錶 Micro LED 螢幕計畫，而且已經在重組該團隊並在亞洲和美國裁撤數十位工程師。報導指出，原因是該工作的成本太高、過程也太複雜，因此決定結束這項耗資龐大的研發計畫。&amp;amp;lt;/p&amp;amp;gt;\n\n&amp;amp;lt;p&amp;amp;gt;報導指出，結束手錶螢幕自研計畫的同時，蘋果先前也取消研發自駕汽車的工作。在這兩種情況下，蘋果至少給一些受影響的員工在公司找到其他職缺的機會，倘若內部轉職未果便會遭到資遣命運。&amp;amp;lt;/p&amp;amp;gt;\n\n&amp;amp;lt;p&amp;amp;gt;蘋果目前認為 OLED 是其智慧手錶的最佳解決方案，但知情人士說，該公司仍在考慮在未來的其他專案中使用 microLED。蘋果正在尋找潛在的新供應商和流程，讓該技術能應用在其設備中，儘管這不太可能很快實現。&amp;amp;lt;/p&amp;amp;gt;\n\n&amp;amp;lt;p&amp;amp;gt;對於上述報導，蘋果發言人拒絕置評請求。截稿前，蘋果 (AAPL-US) 周五盤中股價上漲 0.69%，每股暫報 172.56 美元。&amp;amp;lt;/p&amp;amp;gt;\n\n&amp;amp;lt;p&amp;amp;gt;自研計畫是蘋果推動更多內部技術設計的更廣泛努力的一部分。雖然該公司已經在其產品中客製化螢幕，但在很大程度上是基於樂金顯示公司 (LG Display, LGD) 和三星 SDI 等合作夥伴的設計。透過在蘋果內部引入更多這項流程，該公司希望獲得相對於競爭對手的優勢。&amp;amp;lt;/p&amp;amp;gt;\n\n&amp;amp;lt;p&amp;amp;gt;蘋果硬體工程部門大約 7 年前開始了這項工作，後來這個代號為 T159 的計畫幾年前被轉移到了蘋果的硬體技術部門。&amp;amp;lt;/p&amp;amp;gt;\n\n&amp;amp;lt;p&amp;amp;gt;蘋果甚至在總部附近建立了自己的螢幕製造工廠，數百名員工可以在該廠測試 microLED 螢幕的生產。許多裁員都涉及該工廠的人員，以及蘋果在亞洲靠近其供應鏈中心的顯示工程中心。本周對蘋果位於聖克拉拉工廠的訪問顯示，該大樓仍在運行，停車場裡有汽車，少數員工進出大樓。&amp;amp;lt;/p&amp;amp;gt;\n\n&amp;amp;lt;p&amp;amp;gt;最近幾周，有關該計畫轉變的消息首次出現，當時供應商宣布他們正在失去與 microLED 相關的合約，其中包括 AMS-Osram AG。該公司表示，取消收購將迫使其裁員，可能會出售一家製造工廠，並記錄一筆可能接近 10 億美元的減記。&amp;amp;lt;/p&amp;amp;gt;\n\n&amp;amp;lt;p class=&amp;amp;quot;warning&amp;amp;quot;&amp;amp;gt;本篇文章不提供合作夥伴轉載&amp;amp;lt;/p&amp;amp;gt;\n&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;hasCoverPhoto&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isIndex&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;summary&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;根據彭博周五 (22 日) 援引知情人士消息報導，蘋果正逐步結束自研智慧手錶顯示螢幕 Micro LED 計畫，而且已經在重組該團隊並在亞洲和美國裁撤數十位工程師。報導指出，原因是該工作的成本太高、過程也太複雜，因此決定結束這項耗&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isCategoryHeadline&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="s2">&amp;#34;US-AAPL&amp;#34;&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;video&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;payment&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;feature&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;otherProduct&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="s2">&amp;#34;USS:AAPL:STOCK:COMMON&amp;#34;&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;source&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isOutsource&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;keyword&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="s2">&amp;#34;蘋果&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;Micro LED&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;裁員&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;產業&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;開發&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;Apple Watch&amp;#34;&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;is24h&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;publishAt&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1711132206&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;coverSrc&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;xs&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;src&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://cimg.cnyes.cool/prod/news/5501177/xs/f888c80709d77e7ad0f2dfb96bbf8b1d.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;width&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">100&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;height&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">56&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;s&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;src&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://cimg.cnyes.cool/prod/news/5501177/s/f888c80709d77e7ad0f2dfb96bbf8b1d.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;width&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">180&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;height&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">101&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;m&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;src&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://cimg.cnyes.cool/prod/news/5501177/m/f888c80709d77e7ad0f2dfb96bbf8b1d.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;width&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">380&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;height&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">214&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;l&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;src&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://cimg.cnyes.cool/prod/news/5501177/l/f888c80709d77e7ad0f2dfb96bbf8b1d.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;width&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">640&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;height&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">360&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;xl&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;src&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://cimg.cnyes.cool/prod/news/5501177/xl/f888c80709d77e7ad0f2dfb96bbf8b1d.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;width&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">960&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;height&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">539&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;xxl&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;src&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://cimg.cnyes.cool/prod/news/5501177/xxl/f888c80709d77e7ad0f2dfb96bbf8b1d.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;width&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1080&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;height&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">607&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;abTesting&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;categoryId&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">831&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;categoryName&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;美股雷達&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;columnists&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;fundCategoryAbbr&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[],&lt;/span>
&lt;span class="nt">&amp;#34;etf&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[],&lt;/span>
&lt;span class="nt">&amp;#34;fbShare&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;fbComment&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;fbCommentPluginCount&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;market&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;code&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;AAPL&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;蘋果&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;symbol&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;USS:AAPL:STOCK&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="err">...&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;message&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;成功&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;statusCode&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">200&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>* 為了方便觀察，也可以使用 &lt;a href="http://jsoneditoronline.org/" target="_blank" rel="noopener">
JSON Editor Online
&lt;/a> 線上工具來輔助。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/cnyes_news_spider/news_json_jsoneditor.jpg" alt="可以使用 JSON Editor Online 線上工具來輔助觀察" data-caption="可以使用 JSON Editor Online 線上工具來輔助觀察" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
可以使用 JSON Editor Online 線上工具來輔助觀察
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h2 id="完整程式碼">完整程式碼&lt;/h2>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">time&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">random&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="k">class&lt;/span> &lt;span class="nc">CnyesNewsSpider&lt;/span>&lt;span class="p">():&lt;/span>
&lt;span class="k">def&lt;/span> &lt;span class="nf">get_newslist_info&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">page&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">limit&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">30&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34; 房屋詳情
&lt;/span>&lt;span class="s2">
&lt;/span>&lt;span class="s2"> :param page: 頁數
&lt;/span>&lt;span class="s2"> :param limit: 一頁新聞數量
&lt;/span>&lt;span class="s2"> :return newslist_info: 新聞資料
&lt;/span>&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;Origin&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;https://news.cnyes.com/&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;Referer&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;https://news.cnyes.com/&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;user-agent&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;https://api.cnyes.com/media/api/v1/newslist/category/headline?page={page}&amp;amp;limit={limit}&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;請求失敗&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="bp">None&lt;/span>
&lt;span class="n">newslist_info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()[&lt;/span>&lt;span class="s1">&amp;#39;items&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">newslist_info&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">cnyes_news_spider&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">CnyesNewsSpider&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">newslist_info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">cnyes_news_spider&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_newslist_info&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;搜尋結果 &amp;gt; 全部新聞總數：{newslist_info[&amp;#34;total&amp;#34;]}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;搜尋結果 &amp;gt; 一頁新聞數：{newslist_info[&amp;#34;per_page&amp;#34;]}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;搜尋結果 &amp;gt; 當前頁數：{newslist_info[&amp;#34;current_page&amp;#34;]}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;搜尋結果 &amp;gt; 最後頁數：{newslist_info[&amp;#34;last_page&amp;#34;]}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;搜尋結果 &amp;gt; 前一頁網址：{newslist_info[&amp;#34;prev_page_url&amp;#34;]}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;搜尋結果 &amp;gt; 下一頁網址：{newslist_info[&amp;#34;next_page_url&amp;#34;]}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;搜尋結果 &amp;gt; 此頁新聞第一筆：{newslist_info[&amp;#34;from&amp;#34;]}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;搜尋結果 &amp;gt; 此頁新聞最後一筆：{newslist_info[&amp;#34;to&amp;#34;]}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">news&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">newslist_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;data&amp;#34;&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39; ------------ {news[&amp;#34;newsId&amp;#34;]} ------------&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39; 新聞 &amp;gt; URL：https://news.cnyes.com/news/id/{news[&amp;#34;newsId&amp;#34;]}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39; 新聞 &amp;gt; 標題：{news[&amp;#34;title&amp;#34;]}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39; 新聞 &amp;gt; 概要：{news[&amp;#34;summary&amp;#34;]}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># print(f&amp;#39; 新聞 &amp;gt; 內文：{news[&amp;#34;content&amp;#34;]}&amp;#39;)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39; 新聞 &amp;gt; 關鍵字：{news[&amp;#34;keyword&amp;#34;]}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39; 新聞 &amp;gt; 發布時間：{time.strftime(&amp;#34;%Y-%m-&lt;/span>&lt;span class="si">%d&lt;/span>&lt;span class="s1"> %H:%M:%S&amp;#34;, time.localtime(news[&amp;#34;publishAt&amp;#34;]))}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39; 新聞 &amp;gt; 分類：{news[&amp;#34;categoryName&amp;#34;]} (id:{news[&amp;#34;categoryId&amp;#34;]})&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="c1"># 如果要爬取多頁新聞，建議加入隨機 delay 一段時間，避免被反爬蟲偵測&lt;/span>
&lt;span class="c1"># time.sleep(random.uniform(2, 5))&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h2 id="延伸練習">延伸練習&lt;/h2>
&lt;ol>
&lt;li>除了我上面示範的 &lt;code>page&lt;/code> 和 &lt;code>limit&lt;/code> 參數，我們可以發現還有 &lt;code>isCategoryHeadline&lt;/code>、&lt;code>startAt&lt;/code>、&lt;code>endAt&lt;/code>，你能試著將其加入到程式碼內嗎？&lt;/li>
&lt;li>我們上面是抓取「&lt;a href="https://news.cnyes.com/news/cat/headline" target="_blank" rel="noopener">
即時頭條
&lt;/a>」，你有辦法改成只抓「&lt;a href="https://news.cnyes.com/news/cat/tw_stock_news" target="_blank" rel="noopener">
台股新聞
&lt;/a>」這個分類嗎？&lt;/li>
&lt;/ol>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>學習了基本的網路爬蟲，後續還可以把新聞抓下來後，再透過關鍵字，將新聞做個人化的篩選、分類，甚至串接 LINE Notify 推播訊息📣給自己。&lt;/p>
&lt;br/>
&lt;p>我陸續有在寫一些網站的 &lt;a href="https://blog.jiatool.com/series/Python%e7%b6%b2%e8%b7%af%e7%88%ac%e8%9f%b2%e5%af%a6%e4%be%8b/" target="_blank" rel="noopener">
Python網路爬蟲實例
&lt;/a>，如果你正好是剛開始想學爬蟲的新手、想知道某個網站如何爬取資料，又或遇到其他問題，歡迎參考和在底下留言支持我~💬&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;blockquote>
&lt;p>未來從現在開始！&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/cnyes_news_spider.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/cnyes_news_spider_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Python</category><category>網路爬蟲</category><category>Python網路爬蟲實例</category></item><item><title>Bright Data 手把手教學 — 輕鬆取得 Google、Yahoo 搜尋引擎結果 API</title><link>https://blog.jiatool.com/posts/brightdata_serp_api/</link><pubDate>Sat, 23 Dec 2023 21:00:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sat, 23 Dec 2023 21:00:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/brightdata_serp_api/</guid><description>此篇為商業合作文章 前言 Bright Data 跟我之前介紹過的 DataForSEO 、Aves API 一樣，都有提供抓取搜尋引擎結果的服務，因此照理說穩定度應該會比較好，不過 Bright Data 是專注於</description><content:encoded>&lt;div class="alert alert-info" role="alert" data-dir="ltr">此篇為商業合作文章&lt;/div>
&lt;h2 id="前言">前言&lt;/h2>
&lt;p>&lt;a href="https://brightdata.com/" target="_blank" rel="noopener">
Bright Data
&lt;/a> 跟我之前介紹過的 &lt;a href="https://blog.jiatool.com/posts/dataforseo" target="_blank" rel="noopener">
DataForSEO
&lt;/a>、&lt;a href="https://blog.jiatool.com/posts/aves_api" target="_blank" rel="noopener">
Aves API
&lt;/a> 一樣，都有提供抓取搜尋引擎結果的服務，因此照理說穩定度應該會比較好，不過 Bright Data 是專注於商務客戶，所以要提醒目前個人是無法使用的 (不支持個人用途，如打遊戲之類的)。&lt;/p>
&lt;p>Bright Data 的 SERP API 目前支援 Google、Bing、DuckDuckGo、Yandex、Yahoo、百度 和 Naver 搜尋引擎，你可以用來做關鍵字追蹤、比較價格、市場研究、偵測版權侵權、廣告情報等等用途。&lt;/p>
&lt;br/>
&lt;p>底下我會以最多人使用的「Google 搜尋 API」來當範例，一起從註冊、設定、測試到最後程式碼帶大家認識。&lt;/p>
&lt;br/>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/brightdata_serp_api/brightdata_home.jpg" alt="Bright Data 官網" data-caption="Bright Data 官網" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
Bright Data 官網
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;br/>
&lt;h2 id="註冊-bright-data">註冊 Bright Data&lt;/h2>
&lt;p>首先，需要有一組 Bright Data 帳號。&lt;/p>
&lt;div class="notices info" data-title="註冊 bright data">
&lt;p>如果願意透過此連結註冊，我可以獲得一絲絲分潤，就當支持我寫作吧~🫡&lt;/p>
&lt;p>註冊 Bright Data 帳號：&lt;a href="https://get.brightdata.com/fabjye">https://get.brightdata.com/fabjye&lt;/a>&lt;/p>
&lt;p>官方還提供我的讀者優惠~&lt;br />
透過上述連結註冊的新用戶，首次儲值 25 美元再&lt;strong>送 25 美元&lt;/strong>，直接省一半!!&lt;/p>
&lt;/div>
&lt;br/>
&lt;p>需要填寫姓名、工作用 Email、公司規模，就像文章一開始說的，它是面向商務的服務。&lt;br />
(不支持個人用途)&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/brightdata_serp_api/signup.jpg" alt="註冊 Bright Data" data-caption="註冊 Bright Data" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='400px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:400px;height:;"/>
&lt;figcaption style="text-align: center;">
註冊 Bright Data
&lt;/figcaption>
&lt;/figure>
&lt;p>註冊後，在添加付款方式時，將收到 5 美元的額度可以讓你試用。或者可以聯絡你的客戶經理，會贈送一些額度可以讓你 &lt;a href="https://help.brightdata.com/hc/en-us/articles/4425821434769" target="_blank" rel="noopener">
免費試用
&lt;/a>。&lt;/p>
&lt;br/>
&lt;h2 id="serp-api">SERP API&lt;/h2>
&lt;p>&lt;a href="https://get.brightdata.com/fabjye" target="_blank" rel="noopener">
SERP API
&lt;/a> 目前支援以下幾種搜尋，可以看出來涵蓋蠻多的：&lt;/p>
&lt;ul>
&lt;li>Google Search&lt;/li>
&lt;li>Google Images&lt;/li>
&lt;li>Google Videos&lt;/li>
&lt;li>Google Maps&lt;/li>
&lt;li>Google Trends&lt;/li>
&lt;li>Google Reviews&lt;/li>
&lt;li>Google News&lt;/li>
&lt;li>Google Jobs&lt;/li>
&lt;li>Google Shopping&lt;/li>
&lt;li>Google Hotels&lt;/li>
&lt;li>Bing Search&lt;/li>
&lt;li>DuckDuckGo Search&lt;/li>
&lt;li>Yandex Search&lt;/li>
&lt;li>Yahoo Search&lt;/li>
&lt;li>百度 Search&lt;/li>
&lt;li>Naver Search&lt;/li>
&lt;/ul>
&lt;br/>
&lt;h3 id="serp-api-價格">SERP API 價格&lt;/h3>
&lt;p>SERP API 價格官方有詳細說明在 &lt;a href="https://brightdata.com/pricing/serp" target="_blank" rel="noopener">
這個網頁
&lt;/a>，&lt;/p>
&lt;p>依照方案分為四種：PAY AS YOU GO、GROWTH、BUSINESS、ENTERPRISE。&lt;/p>
&lt;p>CPM 指的是每一千次請求 API 的價格。&lt;br />
以方案 GROWTH 為例，$2.30/CPM 就是每一千個請求要 2.3 美金，等同於每個請求 0.0023 美金 (約 0.072 新台幣)。&lt;/p>
&lt;p>GROWTH 和 BUSINESS 方案會有每月最低消費金額 (分別為 500 和 1000 美金)，但它們使用 API 的價格就會再便宜一些些。&lt;/p>
&lt;p>* 以上價格為美金💵&lt;br />
* 針對費用、週期計算有疑慮的讀者，建議可以直接諮詢客戶經理。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/brightdata_serp_api/serp_api_pricing.jpg" alt="SERP API 價格" data-caption="SERP API 價格" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
SERP API 價格
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h3 id="建立新的-serp-api-zone">建立新的 SERP API Zone&lt;/h3>
&lt;p>第一次使用可以先參考 &lt;a href="https://help.brightdata.com/hc/en-us/articles/16063653689489" target="_blank" rel="noopener">
這篇官方文章
&lt;/a> 去設定，或直接跟著我底下的教學來實作。&lt;/p>
&lt;br/>
&lt;p>進到 &amp;quot;&lt;a href="https://brightdata.com/cp/zones" target="_blank" rel="noopener">
My Proxies
&lt;/a>&amp;quot; 頁面，找到 「SERP API」點 &amp;quot;Get started&amp;quot; 來新增一個 Solution。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/brightdata_serp_api/get_started.jpg" alt="My Proxies &amp;gt; SERP API &amp;gt; Get started" data-caption="My Proxies &amp;gt; SERP API &amp;gt; Get started" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
My Proxies &amp;gt; SERP API &amp;gt; Get started
&lt;/figcaption>
&lt;/figure>
&lt;p>接下來，設定一個 Solution 名稱 (在 Bright Data 內也等同 zone 名稱)，注意這個設定後就無法更改 (就只能把它刪除，再建一個新的)，其餘設定都可以之後再更改。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/brightdata_serp_api/add_new_proxy.jpg" alt="設定一個 Solution" data-caption="設定一個 Solution" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
設定一個 Solution
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>SERP API Zone 上方可以看到有三個頁籤，可以自己隨意點點看看：&lt;/p>
&lt;ul>
&lt;li>Access parameters (存取參數)&lt;/li>
&lt;li>Configuration (配置)&lt;/li>
&lt;li>Statistics (統計數據)&lt;/li>
&lt;/ul>
&lt;p>* 有幾個資訊後續 call API 時會用到，我也在這邊先標出來：&amp;quot;host&amp;quot;、&amp;quot;account id&amp;quot;、&amp;quot;password&amp;quot;、&amp;quot;zone&amp;quot;。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/brightdata_serp_api/api_setting.jpg" alt="SERP API Zone 設定" data-caption="SERP API Zone 設定" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
SERP API Zone 設定
&lt;/figcaption>
&lt;/figure>
&lt;p>* Access parameters (存取參數)分頁底下有個 Limit 欄位，可以設定請求量限制，當到達限制後要關閉還是通知你，可以避免不小心意外耗費太多額度。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/brightdata_serp_api/api_limit.jpg" alt="可限制 API 使用，避免超額" data-caption="可限制 API 使用，避免超額" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
可限制 API 使用，避免超額
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h3 id="測試與範例頁面">測試與範例頁面&lt;/h3>
&lt;p>Bright Data 也同樣提供 SERP API 相關測試與參數介紹頁面，在開始撰寫程式前，可以先來這邊透過網頁 UI 的方式嘗試、熟悉各參數與如何使用。&lt;/p>
&lt;p>* 官方介紹中有看到支援 Google、Bing、DuckDuckGo、Yandex、Yahoo、百度 和 Naver 搜尋，不過在這個頁面缺少 百度、Yahoo、Naver，經過我向官方詢問，使用方式與參數都是一樣的，所以如果需要，稍微改一下應該就能使用了。&lt;/p>
&lt;br/>
&lt;h4 id="playground---測試頁面">Playground - 測試頁面&lt;/h4>
&lt;p>在 &lt;a href="https://brightdata.com/cp/zones/serp_playground" target="_blank" rel="noopener">
SERP API Playground
&lt;/a> 測試頁面，透過 UI 介面選擇瀏覽器、設定關鍵字與參數 (下圖橘框處)，並實際查看它查詢後回傳的資料 (網頁與 JSON)，&lt;/p>
&lt;p>而且使用 Playground 是 &amp;quot;免費&amp;quot; 的！！👍&lt;br />
你可以先在這邊先用不同關鍵字、參數去測試，沒問題後再整合進程式裡面。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/brightdata_serp_api/playground.jpg" alt="SERP API Playground 測試頁面" data-caption="SERP API Playground 測試頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
SERP API Playground 測試頁面
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>下方有個 &amp;quot;Generate API code&amp;quot; 按鈕 (上圖藍框處)，可以查看假如依照你目前的參數設定，該如何下查詢指令(或程式碼)。&lt;br />
要注意你 proxy 設定 &amp;quot;同步&amp;quot; 或 &amp;quot;非同步&amp;quot; 請求 (下一個章節會說明)，這邊的範例也會跟著改變。&lt;/p>
&lt;p>但有點可惜的是，&amp;quot;非同步請求&amp;quot; 的程式碼範例只有 Shell 跟 Node.js，而&amp;quot;同步請求&amp;quot; 雖然有 Python 範例，但不是使用我習慣的 Requests 套件，因此我花了一些時間研究與嘗試，後面章節我有將程式碼列出來供大家參考，&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/brightdata_serp_api/generate_api_code.jpg" alt="Generate API code 範例程式" data-caption="Generate API code 範例程式" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
Generate API code 範例程式
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;br/>
&lt;p>* 如果你還沒註冊就等不及的話，可以到 SERP API 介紹網頁中的 &lt;a href="https://brightdata.com/products/serp-api" target="_blank" rel="noopener">
SERP API Live Demo
&lt;/a> 先嘗試，不過就只有讓你測試 Google 搜尋就是了。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/brightdata_serp_api/serp_api_live_demo.jpg" alt="SERP API Live Demo" data-caption="SERP API Live Demo" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='650px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:650px;height:;"/>
&lt;figcaption style="text-align: center;">
SERP API Live Demo
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h4 id="api-guide---參數介紹與指令">API Guide - 參數介紹與指令&lt;/h4>
&lt;p>這個 &lt;a href="https://brightdata.com/cp/serp_api/api/google/search" target="_blank" rel="noopener">
API Guide
&lt;/a> 頁面是介紹 SERP API 支援那些參數，以及該如何下這些參數。對於參數不了解的話，也可以先到這邊來看看。&lt;/p>
&lt;p>同樣這頁也會因為你 proxy 設定 &amp;quot;同步&amp;quot; 或 &amp;quot;非同步&amp;quot; 請求，而有所對應改變。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/brightdata_serp_api/api_guide.jpg" alt="SERP API Guide - 參數介紹與指令" data-caption="SERP API Guide - 參數介紹與指令" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
SERP API Guide - 參數介紹與指令
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h3 id="發送請求">發送請求&lt;/h3>
&lt;p>它的 SERP API 也有分成「同步請求」、「非同步請求」兩種請求方法。&lt;/p>
&lt;p>預設是使用同步請求，使用上最簡單，只需要發送一個請求即可。但對於有大量請求需求的使用者，還是建議使用非同步請求，因為它有比較好的穩定性。&lt;/p>
&lt;br/>
&lt;p>如果想切換 同步/非同步 請求，則在 SERP API Zone &amp;gt; Configuration 的最下面，有個「Asynchronous requests」開關&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/brightdata_serp_api/async_requests_setting.jpg" alt="SERP API 切換 同步/非同步 請求" data-caption="SERP API 切換 同步/非同步 請求" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='550px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:550px;height:;"/>
&lt;figcaption style="text-align: center;">
SERP API 切換 同步/非同步 請求
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>官方範例是使用我不熟悉的套件，但我比較習慣使用 requests 套件，因此底下範例程式是我自己改寫的~✍️&lt;/p>
&lt;br/>
&lt;h4 id="同步請求">同步請求&lt;/h4>
&lt;p>只要發送一個 GET 請求即可取得結果。&lt;/p>
&lt;p>它是透過 proxy 將請求轉給他們，proxy 設定為：&lt;br />
&lt;code>http://brd-customer-{ACCOUNT_ID}-zone-{ZONE}:{PASSWORD}@{HOST}&lt;/code>&lt;br />
完整樣子會像是：&lt;br />
&lt;code>http://brd-customer-oooooooo-zone-serp_api:xxxxxxxx@brd.superproxy.io:22225&lt;/code>&lt;/p>
&lt;br/>
&lt;p>另外，出於資訊安全的考量，進行 HTTPS 連線時 Python 會檢查伺服器的 SSL 憑證是否有效，因此還需要安裝 SSL 憑證，否則會出現像下圖那樣的錯誤，可以參考官方文章：&lt;a href="https://help.brightdata.com/hc/en-us/articles/4413322250001" target="_blank" rel="noopener">
如何安裝 SSL 憑證
&lt;/a>&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/brightdata_serp_api/disabling_ssl_verification.png" alt="遇到 SSL 憑證問題" data-caption="遇到 SSL 憑證問題" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
遇到 SSL 憑證問題
&lt;/figcaption>
&lt;/figure>
&lt;p>那假如只是要測試，我們可以 &amp;ldquo;忽略憑證&amp;rdquo; (&lt;code>verify=False&lt;/code>，參考 &lt;a href="https://stackoverflow.com/questions/51925384" target="_blank" rel="noopener">
這篇文章
&lt;/a>)，如同下方範例程式馬。&lt;/p>
&lt;br/>
&lt;p>參數說明可以 &lt;a href="https://help.brightdata.com/hc/en-us/articles/16063645923473-API" target="_blank" rel="noopener">
參考這篇
&lt;/a>，或者如果已經登入，可以在後台的 &lt;a href="https://brightdata.com/cp/serp_api/api/google/search" target="_blank" rel="noopener">
API Guide 頁面
&lt;/a> 去查看各種查詢與參數該如何下。&lt;/p>
&lt;br/>
&lt;br/>
&lt;p>Python 程式碼範例：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://www.google.com.tw/search&amp;#39;&lt;/span>
&lt;span class="n">params&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;q&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Google Gemini&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 搜尋關鍵字&lt;/span>
&lt;span class="s2">&amp;#34;gl&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;tw&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;num&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;100&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;brd_json&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;1&amp;#34;&lt;/span> &lt;span class="c1"># 回傳 JSON 格式，預設是 html&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">proxy_url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;http://brd-customer-{ACCOUNT_ID}-zone-{ZONE}:{PASSWORD}@{HOST}&amp;#34;&lt;/span>
&lt;span class="n">proxies&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;http&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">proxy_url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;https&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">proxy_url&lt;/span>&lt;span class="p">}&lt;/span>
&lt;span class="c1"># 使用 verify=False 忽略 SSL 憑證&lt;/span>
&lt;span class="c1"># 為了安全，建議還是安裝 SSL 憑證：https://help.brightdata.com/hc/en-us/articles/4413322250001&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">params&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">proxies&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">proxies&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">verify&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">False&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;p>* 各個狀 SERP API 錯誤訊息意思如&lt;a href="https://help.brightdata.com/hc/en-us/articles/4413230015505" target="_blank" rel="noopener">
這個官方清單
&lt;/a>。&lt;/p>
&lt;br/>
&lt;h4 id="非同步請求">非同步請求&lt;/h4>
&lt;p>在說明用法之前，我們要先去產生一組 API Token (&lt;a href="https://help.brightdata.com/hc/en-us/articles/4413411462417" target="_blank" rel="noopener">
官方說明文章
&lt;/a>)。&lt;/p>
&lt;p>到後台的 &lt;a href="https://brightdata.com/cp/setting/users" target="_blank" rel="noopener">
Account Settings &amp;gt; User access
&lt;/a> 頁面，點擊最下方 API tokens 的右邊 &amp;quot;Add token&amp;quot; 按鈕。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/brightdata_serp_api/account_add_token.jpg" alt="Account Setting &amp;gt; Add token" data-caption="Account Setting &amp;gt; Add token" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
Account Setting &amp;gt; Add token
&lt;/figcaption>
&lt;/figure>
&lt;p>並指定要給哪一位 User 使用，Permission 就選擇 &amp;quot;User&amp;quot; 即可，期限可以指定日期或勾選下方的&amp;quot;Unlimited (無期限)&amp;quot;。&lt;/p>
&lt;p>* 因為這關係到權限，可能會需要去信箱收驗證信。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/brightdata_serp_api/add_api_token.jpg" alt="Add API token" data-caption="Add API token" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
Add API token
&lt;/figcaption>
&lt;/figure>
&lt;p>它產生的 API Token 要複製起來，不然之後忘記就要重新產生了。&lt;/p>
&lt;br/>
&lt;br/>
&lt;p>再來到你的 SERP API Zone 中 Configuration 分頁，最下方將「Asynchronous requests」開關打開。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/brightdata_serp_api/async_requests_setting.jpg" alt="SERP API 切換 同步/非同步 請求" data-caption="SERP API 切換 同步/非同步 請求" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='550px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:550px;height:;"/>
&lt;figcaption style="text-align: center;">
SERP API 切換 同步/非同步 請求
&lt;/figcaption>
&lt;/figure>
&lt;p>這邊的 &amp;quot;Web Hook URL&amp;quot; 和 &amp;quot;Web Hook Request Method&amp;quot; 你可以設定，讓任務完成後會主動來呼叫你，或者像我下面將要說明的 — 由我們自己去取得結果，那就不需要填這兩個欄位了。&lt;/p>
&lt;p>記得要 Save。&lt;/p>
&lt;br/>
&lt;br/>
&lt;p>好了，終於要來講 &amp;quot;非同步請求&amp;quot; 該怎麼使用了。&lt;/p>
&lt;p>它與 &amp;quot;同步請求&amp;quot; 使用方式有所不同，&amp;quot;非同步請求&amp;quot; 使用上分為兩個請求：&lt;/p>
&lt;ol>
&lt;li>設定任務&lt;/li>
&lt;li>取得任務的查詢結果&lt;/li>
&lt;/ol>
&lt;br/>
&lt;p>先使用 POST 請求「設定任務」，指定查詢參數、回傳格式。&lt;br />
如果成功的話，會在收到回覆的 Header 看到一個 &amp;quot;&lt;code>x-response-id&lt;/code>&amp;quot;，這個代表 Response ID，也就是下一步要使用的。&lt;/p>
&lt;p>第二步，送出 GET 請求「取得任務的查詢結果」，帶上第一步取得的 &lt;code>x-response-id&lt;/code>。&lt;br />
如果查詢任務已完成，會收到 &lt;code>Status Code = 200&lt;/code>，Body 內容即是查詢結果資料；如果查詢任務還沒完成，收到 &lt;code>Status Code = 404&lt;/code> (Not Found)，那就要等個幾秒再試一次。&lt;/p>
&lt;p>可以直接參考下方範例程式碼，或參考 &lt;a href="https://help.brightdata.com/hc/en-us/articles/18191740593169" target="_blank" rel="noopener">
這篇官方說明
&lt;/a>。&lt;/p>
&lt;p>* 當然只有 &amp;quot;設定任務&amp;quot; 請求會收費 (如果成功的話)。&lt;br />
* 查詢結果最多會存在伺服器 24 小時，這段時間你還是可以使用 Response ID 去取得查詢結果。&lt;/p>
&lt;br/>
&lt;br/>
&lt;p>Python 程式碼範例：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="c1"># 記得要先去後台開啟 Asynchronous requests&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://api.brightdata.com/serp/req?customer={ACCOUNT_ID}&amp;amp;zone={ZONE}&amp;#39;&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;Content-Type&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;application/json&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;Authorization&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;Bearer {API_TOKEN}&amp;#39;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;country&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;tw&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;query&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;q&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Google Gemini&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 搜尋關鍵字&lt;/span>
&lt;span class="s2">&amp;#34;gl&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;tw&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;num&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;100&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="s2">&amp;#34;brd_json&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;json&amp;#34;&lt;/span> &lt;span class="c1"># 回傳 JSON 格式，預設是 html&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">post&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">json&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">response_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;x-response-id&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;response id: {response_id}&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 等待它完成查詢&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://api.brightdata.com/serp/get_result?customer={ACCOUNT_ID}&amp;amp;zone={ZONE}&amp;amp;response_id={response_id}&amp;#39;&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;Authorization&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;Bearer {API_TOKEN}&amp;#39;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;p>* 各個狀 SERP API 錯誤訊息意思如&lt;a href="https://help.brightdata.com/hc/en-us/articles/4413230015505" target="_blank" rel="noopener">
這個官方清單
&lt;/a>。&lt;/p>
&lt;br/>
&lt;h3 id="查詢結果說明">查詢結果說明&lt;/h3>
&lt;p>SERP API 回傳的查詢結果我以 JSON 格式來說明，以下直接貼出範例結果給大家參考，大部分欄位應該很容易就看出來意思。&lt;/p>
&lt;p>其他說明可以直接參考官方說明：&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://help.brightdata.com/hc/en-us/articles/14597847891217" target="_blank" rel="noopener">
SERP API 輸出 JSON 欄位說明
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://help.brightdata.com/hc/en-us/articles/8699149516177" target="_blank" rel="noopener">
SERP API 的回應 JSON 中的排名欄位是什麼？
&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;general&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;search_engine&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;google&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;results_cnt&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">2030000000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;search_time&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">0.31&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;language&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;zh-TW&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;mobile&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;basic_view&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;search_type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;text&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;page_title&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Google Pixel - Google 搜尋&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;timestamp&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2023-12-03T14:27:44.026Z&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;input&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;original_url&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://www.google.com.tw/search?q=Google+Pixel&amp;amp;gl=tw&amp;amp;lang=zh-TW&amp;amp;location=Kaohsiung+City%2CTaiwan&amp;amp;brd_json=1&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;request_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;xxxxxxxx&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;organic&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;link&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://store.google.com/tw/category/phones?hl=zh-TW&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;display_link&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://store.google.com › category › phones&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;title&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Google Pixel 手機- Google 商店&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;description&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Google 5G smartphones feature the latest technology so you always have that new phone feeling. Find out which Pixel is right for you.&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;rank&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;global_rank&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;link&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://store.google.com/tw/?hl=zh-TW&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;display_link&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://store.google.com › ...&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;title&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Google 商店官網，專售Google 製造的裝置和配件&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;description&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;全新Pixel 手機內建Google AI 技術，搭載最令人驚艷的Pixel 相機。 ... 支援大多數搭載Android 9.0 以上版本的手機，須有Google 帳戶、Google Pixel Watch 應用程式和網路連 ...&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;rank&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;global_rank&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">2&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="err">......&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;link&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://guidebooks.google.com/pixel?hl=zh-Hant&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;display_link&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://guidebooks.google.com › pixel&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;title&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;瞭解「Google Pixel」&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;description&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;設定新的Pixel 手機. 瞭解如何從你的舊Android 手機或iPhone® 轉移資料。 接下來，你可以學習如何自訂各項設定、取得日常事務協助以及 因應緊急狀況等等。&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;rank&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;global_rank&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">10&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;pagination&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;current_page&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;next_page_link&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://www.google.com.tw/search?q=Google+Pixel&amp;amp;sca_esv=587474982&amp;amp;gl=tw&amp;amp;hl=zh-TW&amp;amp;ei=XZBsZxxxxxxxx4HIDg&amp;amp;start=10&amp;amp;sa=N&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;next_page_start&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;next_page&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">2&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;related&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;list_group&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;link&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://www.google.com.tw/search?sca_esv=587474982&amp;amp;gl=tw&amp;amp;hl=zh-TW&amp;amp;q=google+pixel%E8%A9%95%E5%83%B9&amp;amp;sa=X&amp;amp;ved=2ahUKEwiS9uLuvPOCAxXYBogKHdNVAOkQ1QJ6BAgjEAE&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;text&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;google pixel評價&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;rank&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;global_rank&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">11&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="err">......&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;list_group&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;link&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;https://www.google.com.tw/search?sca_esv=587474982&amp;amp;gl=tw&amp;amp;hl=zh-TW&amp;amp;q=google%E6%89%8B%E6%A9%9Fpixel+7&amp;amp;sa=X&amp;amp;ved=2ahUKEwiS9uLuvPOCAxXYBogKHdNVAOkQ1QJ6BAgeEAE&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;text&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;google手機pixel 7&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;rank&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">8&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;global_rank&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">18&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h3 id="完整-python-範例">完整 Python 範例&lt;/h3>
&lt;p>首先要確認有安裝 Requests 套件：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">pip install requests
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>完整 Python 程式碼：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt"> 10
&lt;/span>&lt;span class="lnt"> 11
&lt;/span>&lt;span class="lnt"> 12
&lt;/span>&lt;span class="lnt"> 13
&lt;/span>&lt;span class="lnt"> 14
&lt;/span>&lt;span class="lnt"> 15
&lt;/span>&lt;span class="lnt"> 16
&lt;/span>&lt;span class="lnt"> 17
&lt;/span>&lt;span class="lnt"> 18
&lt;/span>&lt;span class="lnt"> 19
&lt;/span>&lt;span class="lnt"> 20
&lt;/span>&lt;span class="lnt"> 21
&lt;/span>&lt;span class="lnt"> 22
&lt;/span>&lt;span class="lnt"> 23
&lt;/span>&lt;span class="lnt"> 24
&lt;/span>&lt;span class="lnt"> 25
&lt;/span>&lt;span class="lnt"> 26
&lt;/span>&lt;span class="lnt"> 27
&lt;/span>&lt;span class="lnt"> 28
&lt;/span>&lt;span class="lnt"> 29
&lt;/span>&lt;span class="lnt"> 30
&lt;/span>&lt;span class="lnt"> 31
&lt;/span>&lt;span class="lnt"> 32
&lt;/span>&lt;span class="lnt"> 33
&lt;/span>&lt;span class="lnt"> 34
&lt;/span>&lt;span class="lnt"> 35
&lt;/span>&lt;span class="lnt"> 36
&lt;/span>&lt;span class="lnt"> 37
&lt;/span>&lt;span class="lnt"> 38
&lt;/span>&lt;span class="lnt"> 39
&lt;/span>&lt;span class="lnt"> 40
&lt;/span>&lt;span class="lnt"> 41
&lt;/span>&lt;span class="lnt"> 42
&lt;/span>&lt;span class="lnt"> 43
&lt;/span>&lt;span class="lnt"> 44
&lt;/span>&lt;span class="lnt"> 45
&lt;/span>&lt;span class="lnt"> 46
&lt;/span>&lt;span class="lnt"> 47
&lt;/span>&lt;span class="lnt"> 48
&lt;/span>&lt;span class="lnt"> 49
&lt;/span>&lt;span class="lnt"> 50
&lt;/span>&lt;span class="lnt"> 51
&lt;/span>&lt;span class="lnt"> 52
&lt;/span>&lt;span class="lnt"> 53
&lt;/span>&lt;span class="lnt"> 54
&lt;/span>&lt;span class="lnt"> 55
&lt;/span>&lt;span class="lnt"> 56
&lt;/span>&lt;span class="lnt"> 57
&lt;/span>&lt;span class="lnt"> 58
&lt;/span>&lt;span class="lnt"> 59
&lt;/span>&lt;span class="lnt"> 60
&lt;/span>&lt;span class="lnt"> 61
&lt;/span>&lt;span class="lnt"> 62
&lt;/span>&lt;span class="lnt"> 63
&lt;/span>&lt;span class="lnt"> 64
&lt;/span>&lt;span class="lnt"> 65
&lt;/span>&lt;span class="lnt"> 66
&lt;/span>&lt;span class="lnt"> 67
&lt;/span>&lt;span class="lnt"> 68
&lt;/span>&lt;span class="lnt"> 69
&lt;/span>&lt;span class="lnt"> 70
&lt;/span>&lt;span class="lnt"> 71
&lt;/span>&lt;span class="lnt"> 72
&lt;/span>&lt;span class="lnt"> 73
&lt;/span>&lt;span class="lnt"> 74
&lt;/span>&lt;span class="lnt"> 75
&lt;/span>&lt;span class="lnt"> 76
&lt;/span>&lt;span class="lnt"> 77
&lt;/span>&lt;span class="lnt"> 78
&lt;/span>&lt;span class="lnt"> 79
&lt;/span>&lt;span class="lnt"> 80
&lt;/span>&lt;span class="lnt"> 81
&lt;/span>&lt;span class="lnt"> 82
&lt;/span>&lt;span class="lnt"> 83
&lt;/span>&lt;span class="lnt"> 84
&lt;/span>&lt;span class="lnt"> 85
&lt;/span>&lt;span class="lnt"> 86
&lt;/span>&lt;span class="lnt"> 87
&lt;/span>&lt;span class="lnt"> 88
&lt;/span>&lt;span class="lnt"> 89
&lt;/span>&lt;span class="lnt"> 90
&lt;/span>&lt;span class="lnt"> 91
&lt;/span>&lt;span class="lnt"> 92
&lt;/span>&lt;span class="lnt"> 93
&lt;/span>&lt;span class="lnt"> 94
&lt;/span>&lt;span class="lnt"> 95
&lt;/span>&lt;span class="lnt"> 96
&lt;/span>&lt;span class="lnt"> 97
&lt;/span>&lt;span class="lnt"> 98
&lt;/span>&lt;span class="lnt"> 99
&lt;/span>&lt;span class="lnt">100
&lt;/span>&lt;span class="lnt">101
&lt;/span>&lt;span class="lnt">102
&lt;/span>&lt;span class="lnt">103
&lt;/span>&lt;span class="lnt">104
&lt;/span>&lt;span class="lnt">105
&lt;/span>&lt;span class="lnt">106
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">time&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">json&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="n">ZONE&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;your_zone&amp;gt;&amp;#34;&lt;/span>
&lt;span class="n">ACCOUNT_ID&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;your_account_id&amp;gt;&amp;#34;&lt;/span>
&lt;span class="n">PASSWORD&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;your_password&amp;gt;&amp;#34;&lt;/span>
&lt;span class="n">HOST&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;your_host&amp;gt;&amp;#34;&lt;/span>
&lt;span class="n">API_TOKEN&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;your_api_token&amp;gt;&amp;#34;&lt;/span>
&lt;span class="k">class&lt;/span> &lt;span class="nc">Brightdata&lt;/span>&lt;span class="p">():&lt;/span>
&lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">zone&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">account_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">password&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">host&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">api_token&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">zone&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">zone&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">account_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">account_id&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">password&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">password&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">host&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">host&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">api_token&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">api_token&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">username&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;brd-customer-{self.account_id}-zone-{self.zone}&amp;#34;&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">proxy_url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;http://{self.username}:{self.password}@{self.host}&amp;#34;&lt;/span>
&lt;span class="k">def&lt;/span> &lt;span class="nf">sync_get_search_result&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">keyword&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34; SERP API 同步請求 - 取得搜尋結果&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">proxies&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;http&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">proxy_url&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;https&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">proxy_url&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://www.google.com.tw/search&amp;#39;&lt;/span>
&lt;span class="n">params&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;q&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">keyword&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 搜尋關鍵字&lt;/span>
&lt;span class="s2">&amp;#34;gl&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;tw&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;lang&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;zh-TW&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;location&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Kaohsiung City,Taiwan&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;num&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;100&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;brd_json&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;1&amp;#34;&lt;/span> &lt;span class="c1"># 回傳 JSON 格式，預設是 html&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="c1"># 使用 verify=False 忽略 SSL 憑證&lt;/span>
&lt;span class="c1"># 為了安全，建議還是安裝 SSL 憑證：https://help.brightdata.com/hc/en-us/articles/4413322250001&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">params&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">proxies&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">proxies&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">verify&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">False&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">200&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;Error: {response.status_code} - {response.reason}&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="k">def&lt;/span> &lt;span class="nf">async_set_search_job&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">keyword&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34; SERP API 非同步請求 - 設定搜尋任務
&lt;/span>&lt;span class="s2">
&lt;/span>&lt;span class="s2"> * 記得要先去後台開啟 Asynchronous requests
&lt;/span>&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://api.brightdata.com/serp/req?customer={self.account_id}&amp;amp;zone={self.zone}&amp;#39;&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;Content-Type&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;application/json&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;Authorization&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;Bearer {self.api_token}&amp;#39;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;country&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;tw&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;query&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;q&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">keyword&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 搜尋關鍵字&lt;/span>
&lt;span class="s2">&amp;#34;gl&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;tw&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;lang&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;zh-TW&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;location&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Kaohsiung City,Taiwan&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;num&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;100&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="s2">&amp;#34;brd_json&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;json&amp;#34;&lt;/span> &lt;span class="c1"># 回傳 JSON 格式，預設是 html&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">post&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">json&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">response_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">200&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">response_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;x-response-id&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;response id: {response_id}&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;Error: {response.status_code} - {response.reason}&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">response_id&lt;/span>
&lt;span class="k">def&lt;/span> &lt;span class="nf">async_get_search_result&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">response_id&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34; SERP API 非同步請求 - 取得搜尋結果
&lt;/span>&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://api.brightdata.com/serp/get_result?customer={self.account_id}&amp;amp;zone={self.zone}&amp;amp;response_id={response_id}&amp;#39;&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;Authorization&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;Bearer {self.api_token}&amp;#39;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">200&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;Error: {response.status_code} - {response.reason}&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;__main__&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">brightdata&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Brightdata&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ZONE&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ACCOUNT_ID&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">PASSWORD&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">HOST&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">API_TOKEN&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># SERP API 同步請求&lt;/span>
&lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">brightdata&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sync_get_search_result&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Google Pixel&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dumps&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">))&lt;/span>
&lt;span class="c1"># SERP API 非同步請求&lt;/span>
&lt;span class="c1"># response_id = brightdata.async_set_search_job(&amp;#34;Google Pixel&amp;#34;)&lt;/span>
&lt;span class="c1"># time.sleep(10) # 等待它完成查詢&lt;/span>
&lt;span class="c1"># result = brightdata.async_get_search_result(response_id)&lt;/span>
&lt;span class="c1"># print(json.dumps(result))&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;br/>
&lt;p>* 官方還有更多的說明文件，有需要都可以進去看看：&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://help.brightdata.com/hc/en-us/sections/16062473940113" target="_blank" rel="noopener">
PROXIES &amp;amp; SCRAPING INFRA &amp;gt; SERP API
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://help.brightdata.com/hc/en-us/sections/4413189032977" target="_blank" rel="noopener">
API DOCUMENTATION &amp;gt; SERP-API
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://help.brightdata.com/hc/en-us/articles/16593685131153" target="_blank" rel="noopener">
SERP-API 常見 Q&amp;amp;A
&lt;/a>&lt;/li>
&lt;/ul>
&lt;br/>
&lt;br/>
&lt;div class="notices info" data-title="註冊 bright data">
&lt;p>如果願意透過此連結註冊，我可以獲得一絲絲分潤，就當支持我寫作吧~🫡&lt;/p>
&lt;p>註冊 Bright Data 帳號：&lt;a href="https://get.brightdata.com/fabjye">https://get.brightdata.com/fabjye&lt;/a>&lt;/p>
&lt;p>官方還提供我的讀者優惠~&lt;br />
透過上述連結註冊的新用戶，首次儲值 25 美元再&lt;strong>送 25 美元&lt;/strong>，直接省一半!!&lt;/p>
&lt;/div>
&lt;br/>
&lt;br/>
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>如果你有爬取(抓取)搜尋結果資料的需求，我覺得花點小錢還是蠻值得的，總比自己在那邊 搞爬蟲、驗證碼(CAPTCHA)、換 IP、Proxy、被Ban帳號 好太多了&amp;hellip; (&amp;lt;- 過來人😭😭😭&lt;/p>
&lt;p>Bright Data 除了這次介紹的 SERP API 工具外，他還有其他很多的服務，像是 Proxy、Scraping Browser API、Web Scraper IDE、Web Unlocker 等等，如果有這方面的需求，也可以跟他們詢問 (反正問又不用錢XD)。&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://brightdata.com/" target="_blank" rel="noopener">
BrightData 官方網站
&lt;/a>&lt;br />
&lt;a href="https://help.brightdata.com/hc/en-us/sections/16062473940113" target="_blank" rel="noopener">
BrightData SERP-API 官方文檔1
&lt;/a>&lt;br />
&lt;a href="https://help.brightdata.com/hc/en-us/sections/4413189032977" target="_blank" rel="noopener">
BrightData SERP-API 官方文檔2
&lt;/a>&lt;br />
&lt;a href="https://help.brightdata.com/hc/en-us/articles/16593685131153" target="_blank" rel="noopener">
BrightData SERP-API 常見 Q&amp;amp;A
&lt;/a>&lt;br />
&lt;a href="https://brightdata.com/cp/zones" target="_blank" rel="noopener">
BrightData 使用者後台
&lt;/a>&lt;/p>
&lt;br/>
&lt;blockquote>
&lt;p>只做能力範圍的事，就永遠無法進步。&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/brightdata_serp_api.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/brightdata_serp_api_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Google搜尋</category><category>Yahoo搜尋</category><category>SEO</category><category>API</category><category>Python</category><category>分享</category></item><item><title>如何使用 Google 的 Gemini 模型 API？(基礎教學，附上 Python 範例程式)</title><link>https://blog.jiatool.com/posts/gemini_api/</link><pubDate>Sun, 17 Dec 2023 21:45:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Wed, 28 Feb 2024 15:35:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/gemini_api/</guid><description>前言 在上個禮拜(12/6)推出了 Google DeepMind 開發的 Gemini (雙子星) ，是第一個在 MMLU (大規模多任務語言理解) 方面超越人類專家的模型，要與 OpenAI 的 GPT-4 來抗衡。 我之前</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>在上個禮拜(12/6)推出了 Google DeepMind 開發的 &lt;a href="https://deepmind.google/technologies/gemini/" target="_blank" rel="noopener">
Gemini (雙子星)
&lt;/a>，是第一個在 MMLU (大規模多任務語言理解) 方面超越人類專家的模型，要與 OpenAI 的 GPT-4 來抗衡。&lt;/p>
&lt;p>我之前寫過一篇 &lt;a href="https://blog.jiatool.com/posts/chatgpt_api" target="_blank" rel="noopener">
如何使用 OpenAI ChatGPT API
&lt;/a>，而在前幾天(12/13) Google 也開放了 &lt;a href="https://developers.googleblog.com/2023/12/build-with-gemini-pro.html" target="_blank" rel="noopener">
Gemini Pro 版本的 API
&lt;/a>，可以透過「Google AI Studio 中的 Gemini API」或「Google Cloud 的 Vertex AI 平臺」來存取。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gemini_api/welcome_gemini.jpg" alt="Google DeepMind 開發的 Gemini 多模態模型" data-caption="Google DeepMind 開發的 Gemini 多模態模型" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
Google DeepMind 開發的 Gemini 多模態模型
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;div class="alert alert-info" role="alert" data-dir="ltr">右邊有目錄，可直接跳至你想看的章節 →&lt;/div>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="gemini-簡介">Gemini 簡介&lt;/h2>
&lt;p>Gemini 是一個原生多模態的 LLM (大型語言模型)，從訓練時就餵進去文字、影像、音訊等等多種形態的資料，使用 Google 自行開發的 TPU 晶片訓練而成，是第一個在 MMLU (大規模多任務語言理解) 方面超越人類專家的模型。&lt;/p>
&lt;p>* 官方 Gemini 簡介文章：&lt;a href="https://blog.google/technology/ai/google-gemini-ai">https://blog.google/technology/ai/google-gemini-ai&lt;/a>&lt;/p>
&lt;br/>
&lt;p>而官方有釋出一部試用 Gemini Ultra 的展示影片，我看完真的覺得很驚訝，在網路上也掀起了一陣熱烈討論。&lt;/p>
&lt;p>* 有 CC 中文字幕&lt;/p>
&lt;iframe width="672" height="378" src="https://www.youtube.com/embed/UIZAiXYceBI?si=6VOjykF9uKkO_mt6" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen>&lt;/iframe>
&lt;p>* 有文章版可以看：&lt;a href="https://developers.googleblog.com/2023/12/how-its-made-gemini-multimodal-prompting.html" target="_blank" rel="noopener">
How it's Made: Interacting with Gemini through multimodal prompting
&lt;/a>&lt;/p>
&lt;p>* Gemini 的訓練資料是到 2023 年初，在此之後的它可能就不知道了。&lt;/p>
&lt;br/>
&lt;h3 id="gemini-模型三種尺寸">Gemini 模型三種尺寸&lt;/h3>
&lt;p>Gemini 依照尺寸分成三種版本：&lt;/p>
&lt;ul>
&lt;li>Gemini Ultra：最強大，適用高度複雜的任務&lt;/li>
&lt;li>Gemini Pro：最通用&lt;/li>
&lt;li>Gemini Nano：可於行動裝置上運作&lt;/li>
&lt;/ul>
&lt;p>目前 Google 的 Bard 背後已經換成了 Gemini Pro (好像只有英文版)，Gemini Nano 也應用於 Google Pixel 8 上。&lt;br />
而 Gemini Ultra 應該明年初會推出。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gemini_api/gemini_sizes.jpg" alt="Gemini 分成三種尺寸" data-caption="Gemini 分成三種尺寸" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='650px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:650px;height:;"/>
&lt;figcaption style="text-align: center;">
Gemini 分成三種尺寸
&lt;/figcaption>
&lt;/figure>
&lt;p>* Gemini Ultra 對比 OpenAI GPT-4；Gemini Pro 對比 OpenAI GPT-3.5。&lt;br />
* 目前只開放 Gemini Pro 版本的 API。&lt;/p>
&lt;br/>
&lt;h3 id="api-價格">API 價格&lt;/h3>
&lt;p>以下價格都是 12/16 查詢的金額。&lt;/p>
&lt;br/>
&lt;p>在明年初全面上市之前，可以 &amp;quot;免費&amp;quot; 使用相同速率限制、相同模型來嘗試，不確定之後還會不會有免費方案(但降低使用速率)。&lt;br />
* 免費方案的輸入輸出資料會被拿去訓練，需要注意。&lt;/p>
&lt;p>Gemini Pro 的 API 限制每分鐘最多 60 個請求(以個人使用絕對夠用)，預計明年初之後收費如下：&lt;/p>
&lt;ul>
&lt;li>Price (input)&lt;br />
$0.00025 / 1K characters&lt;br />
$0.0025 / image&lt;/li>
&lt;li>Price (output)&lt;br />
$0.0005 / 1K characters&lt;/li>
&lt;/ul>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gemini_api/gemini_pro_price.jpg" alt="Gemini Pro 版本的 API 價格" data-caption="Gemini Pro 版本的 API 價格" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
Gemini Pro 版本的 API 價格
&lt;/figcaption>
&lt;/figure>
&lt;p>而 OpenAI GPT 的 API 收費如下 (以 GPT-3.5 Turbo 為例)：&lt;/p>
&lt;ul>
&lt;li>Price (input)&lt;br />
$0.001 / 1K tokens&lt;/li>
&lt;li>Price (output)&lt;br />
$0.002 / 1K tokens&lt;/li>
&lt;/ul>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gemini_api/openai_gpt_price.jpg" alt="OpenAI GPT 的 API 價格" data-caption="OpenAI GPT 的 API 價格" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='750px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:750px;height:;"/>
&lt;figcaption style="text-align: center;">
OpenAI GPT 的 API 價格
&lt;/figcaption>
&lt;/figure>
&lt;p>* 以上價格皆為美金，撰寫文章當下約 1 美金 = 31.3 新台幣。&lt;/p>
&lt;br/>
&lt;p>比較一下，可以看到 Google 的 Gemini 相較來說更划算，便宜了 4 倍，而且注意看他們的計算方式也不同，一個是用 character、一個是用 token，我們來看看不同的計算方式差多少。&lt;/p>
&lt;br/>
&lt;p>底下我自己實際用它們官網計算 token 的工具，來比較兩者的差距。&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://makersuite.google.com/" target="_blank" rel="noopener">
Google AI Studio
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://platform.openai.com/tokenizer" target="_blank" rel="noopener">
OpenAI Tokenizer
&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>先測試一段英文，兩者算出來的 token 是差不多的 (分別為 24 跟 25)：&lt;/p>
&lt;blockquote>
&lt;p>Gemini is built from the ground up for multimodality — reasoning seamlessly across image, video, audio, and code.&lt;/p>
&lt;/blockquote>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gemini_api/gemini_count_tokens_english.jpg" alt="Google Gemini token 計算 - 英文" data-caption="Google Gemini token 計算 - 英文" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='850px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:850px;height:;"/>
&lt;figcaption style="text-align: center;">
Google Gemini token 計算 - 英文
&lt;/figcaption>
&lt;/figure>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gemini_api/gpt_count_tokens_english.jpg" alt="OpenAI GPT-3.5 token 計算 - 英文" data-caption="OpenAI GPT-3.5 token 計算 - 英文" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='650px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:650px;height:;"/>
&lt;figcaption style="text-align: center;">
OpenAI GPT-3.5 token 計算 - 英文
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>但是，如果是中文，因為計算方式的差異，整整差了兩倍！！ (分別為 25 跟 50)&lt;/p>
&lt;blockquote>
&lt;p>Gemini 是一個原生多模態的大型語言模型，在大規模多任務語言理解方面甚至超越人類專家。&lt;/p>
&lt;/blockquote>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gemini_api/gemini_count_tokens_chinese.jpg" alt="Google Gemini token 計算 - 中文" data-caption="Google Gemini token 計算 - 中文" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='850px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:850px;height:;"/>
&lt;figcaption style="text-align: center;">
Google Gemini token 計算 - 中文
&lt;/figcaption>
&lt;/figure>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gemini_api/gpt_count_tokens_chinese.jpg" alt="OpenAI GPT-3.5 token 計算 - 中文" data-caption="OpenAI GPT-3.5 token 計算 - 中文" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='650px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:650px;height:;"/>
&lt;figcaption style="text-align: center;">
OpenAI GPT-3.5 token 計算 - 中文
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h2 id="gemini-pro-api">Gemini Pro API&lt;/h2>
&lt;h3 id="創建-api-key">創建 API key&lt;/h3>
&lt;p>進到 &lt;a href="https://ai.google.dev/?hl=zh-tw" target="_blank" rel="noopener">
Google AI for Developers
&lt;/a> 的網站，可以查看 Google AI 模型的介紹、價格、說明文件與範例。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gemini_api/build_with_gemini1.jpg" alt="建置 Gemini" data-caption="建置 Gemini" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='650px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:650px;height:;"/>
&lt;figcaption style="text-align: center;">
建置 Gemini
&lt;/figcaption>
&lt;/figure>
&lt;p>點擊 &amp;quot;Get API key in Google AI Studio&amp;quot; 前往 &lt;a href="https://makersuite.google.com/" target="_blank" rel="noopener">
Google AI Studio
&lt;/a> 來在網頁上測試 LLM AI 模型(類似 Playground 頁面的用途) 與取得 API key，&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gemini_api/build_with_gemini2.jpg" alt="建置 Gemini" data-caption="建置 Gemini" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
建置 Gemini
&lt;/figcaption>
&lt;/figure>
&lt;blockquote>
&lt;p>Google AI Studio 是以瀏覽器為基礎的 IDE，可使用生成式模型進行原型設計。Google AI Studio 可讓您快速試用模型並嘗試各種提示建構符合需求的項目後，您可以從 Gemini API 提供支援的程式語言，並將其匯出為程式碼。&lt;/p>
&lt;/blockquote>
&lt;p>關於 Google AI Studio 的使用我就不多介紹了。提醒如果想輸入圖片，右邊的 Model 記得要切換成 Gemini Pro Vision，才有支援圖像。&lt;/p>
&lt;p>* &lt;a href="https://ai.google.dev/tutorials/ai-studio_quickstart?hl=zh-tw" target="_blank" rel="noopener">
Google AI Studio 官方教學文章
&lt;/a>&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gemini_api/google_ai_studio.jpg" alt="Google AI Studio" data-caption="Google AI Studio" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
Google AI Studio
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>點擊左邊的 &amp;quot;Get API key&amp;quot; &amp;gt; &amp;quot;Create API key in new project&amp;quot; 來自動產生一個 Google Cloud 專案並創建一個 API key。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gemini_api/google_cloud_keys.jpg" alt="創建 Google Cloud API key" data-caption="創建 Google Cloud API key" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
創建 Google Cloud API key
&lt;/figcaption>
&lt;/figure>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gemini_api/google_cloud_key_generated.jpg" alt="創建 Google Cloud API key" data-caption="創建 Google Cloud API key" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
創建 Google Cloud API key
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h3 id="gemini-模型種類說明">Gemini 模型種類說明&lt;/h3>
&lt;p>&lt;a href="https://ai.google.dev/models/gemini?hl=zh-tw" target="_blank" rel="noopener">
Gemini models 種類說明
&lt;/a> 列出目前可使用的 Gemini 模型資訊，包含 &amp;quot;模型說明&amp;quot;、&amp;quot;模型更新時間&amp;quot;、&amp;quot;輸入輸出類型&amp;quot;、&amp;quot;Token限制&amp;quot;、&amp;quot;頻率限制&amp;quot;&lt;/p>
&lt;p>Gemini Pro 用在文字輸入，而 Gemini Pro Vision 可以文字加影像輸入。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gemini_api/api_models.png" alt="Gemini 可使用的模型種類" data-caption="Gemini 可使用的模型種類" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
Gemini 可使用的模型種類
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="api-版本說明">API 版本說明&lt;/h3>
&lt;p>目前 Gemini API 有 &lt;a href="https://ai.google.dev/docs/api_versions?hl=zh-tw" target="_blank" rel="noopener">
v1 和 v1beta 版本
&lt;/a>：&lt;/p>
&lt;ul>
&lt;li>v1：API 的穩定版。在主要版本的生命週期內，穩定版本的功能都能完整支援。如有任何破壞性變更，系統會建立 API 的下一個主要版本，並在合理的時間內淘汰現有版本。&lt;/li>
&lt;li>v1beta：包含可能處於開發階段的搶先體驗功能，且需要快速更新及破壞性變更。請勿使用此版本於正式版應用程式。&lt;/li>
&lt;/ul>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gemini_api/api_versions_explained.png" alt="API 版本比較 (v1 與 v1beta)" data-caption="API 版本比較 (v1 與 v1beta)" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='750px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:750px;height:;"/>
&lt;figcaption style="text-align: center;">
API 版本比較 (v1 與 v1beta)
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="傳入參數">傳入參數&lt;/h3>
&lt;p>我們使用的 &lt;a href="https://ai.google.dev/api/rest/v1/models/generateContent?hl=zh-tw" target="_blank" rel="noopener">
generateContent 方法
&lt;/a> 其 Request 相關資訊如下：&lt;/p>
&lt;pre>&lt;code>POST https://generativelanguage.googleapis.com/v1/models/{gemini-pro or gemini-pro-vision}:generateContent?key={API_KEY}
&lt;/code>&lt;/pre>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;contents&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;parts&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;text&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;prompt...&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;user or model&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;safetySettings&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;category&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;enum (HarmCategory)&amp;gt;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;threshold&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;enum (HarmBlockThreshold)&amp;gt;&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;generationConfig&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;temperature&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;number&amp;gt;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;topP&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;number&amp;gt;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;topK&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;number&amp;gt;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;candidateCount&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;integer&amp;gt;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;maxOutputTokens&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;integer&amp;gt;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;stopSequences&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;&amp;lt;string&amp;gt;&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;code>contents&lt;/code> 放 prompt 提示 (&lt;code>text&lt;/code>) 與角色 (&lt;code>role&lt;/code>，可以是 &lt;code>user&lt;/code> 或 &lt;code>model&lt;/code>，不填則預設 &lt;code>user&lt;/code>)。&lt;/p>
&lt;br/>
&lt;p>&lt;code>safetySettings&lt;/code> 是 OpenAI GPT 沒有的參數，用於封鎖不安全的回覆內容。&lt;/p>
&lt;p>&lt;code>safetySettings&lt;/code> &amp;gt; &lt;code>category&lt;/code> 類別，可以使用以下數值：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>數值&lt;/th>
&lt;th>代表意思&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>HARM_CATEGORY_HARASSMENT&lt;/td>
&lt;td>騷擾內容。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>HARM_CATEGORY_HATE_SPEECH&lt;/td>
&lt;td>仇恨言論和內容。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>HARM_CATEGORY_SEXUALLY_EXPLICIT&lt;/td>
&lt;td>情色露骨內容。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>HARM_CATEGORY_DANGEROUS_CONTENT&lt;/td>
&lt;td>危險內容。&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>* 其他還有 HARM_CATEGORY_UNSPECIFIED、HARM_CATEGORY_DEROGATORY、HARM_CATEGORY_TOXICITY、HARM_CATEGORY_VIOLENCE、HARM_CATEGORY_SEXUAL、HARM_CATEGORY_MEDICAL、HARM_CATEGORY_DANGEROUS，不過那是給 PaLM 2（舊版）模型使用的，Gemini 模型不支援。&lt;/p>
&lt;p>&lt;code>safetySettings&lt;/code> &amp;gt; &lt;code>threshold&lt;/code> 封鎖門檻，可以使用以下數值：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>數值&lt;/th>
&lt;th>代表意思&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>HARM_BLOCK_THRESHOLD_UNSPECIFIED&lt;/td>
&lt;td>未指定門檻。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>BLOCK_LOW_AND_ABOVE&lt;/td>
&lt;td>允許含有「NEGLIGIBLE」的內容&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>BLOCK_MEDIUM_AND_ABOVE&lt;/td>
&lt;td>允許含有「NEGLIGIBLE」、「LOW」的內容。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>BLOCK_ONLY_HIGH&lt;/td>
&lt;td>允許含有「NEGLIGIBLE」、「LOW」、「MEDIUM」的內容。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>BLOCK_NONE&lt;/td>
&lt;td>允許所有內容。&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;br/>
&lt;p>&lt;code>generationConfig&lt;/code> 用於設定模型生成和輸出的設定參數，其中幾個比較會用到的是：&lt;/p>
&lt;ul>
&lt;li>&lt;code>temperature&lt;/code>：輸出內容的隨機性。越接近 1.0，產生的回應會豐富、多元、更有創意；反之越接近 0.0，則會產生較有確定性、可能性較高的回覆。&lt;/li>
&lt;li>&lt;code>maxOutputTokens&lt;/code>：最大輸出回應 Token 數量。Gemini Pro 模型預設 2048；Gemini Pro Vision 模型預設 4096。&lt;/li>
&lt;li>&lt;code>candidateCount&lt;/code>：要傳回的回應數量。預設 1，可設定 1~8，但目前好像限制只能用 1。&lt;/li>
&lt;/ul>
&lt;br/>
&lt;br/>
&lt;p>用法可以直接看下一章節的 Python 範例程式碼。其他更詳細的說明，請參考以下官方文件：&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://cloud.google.com/vertex-ai/docs/generative-ai/model-reference/gemini" target="_blank" rel="noopener">
Gemini API 說明文件
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://ai.google.dev/api/rest/v1/models/generateContent?hl=zh-tw" target="_blank" rel="noopener">
Gemini API generateContent 參考資料
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://ai.google.dev/docs/concepts?hl=zh-tw#model_parameters" target="_blank" rel="noopener">
LLM 概念指南 &amp;gt; 模型參數
&lt;/a>&lt;/li>
&lt;/ul>
&lt;br/>
&lt;h3 id="回覆內容">回覆內容&lt;/h3>
&lt;p>API 範例回覆內容如下：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;candidates&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;parts&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;text&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;我知道王建民。王建民，1980年3月31日出生於台灣台中市，是一位前台灣棒球選手，司職投手。他曾效力於中華職棒的興農牛隊，美國職棒的紐約洋基隊、華盛頓國民隊和芝加哥白襪隊，以及中國棒球聯賽的北京猛虎隊。\n\n王建民是台灣史上第一位大聯盟先發勝投破百的投手，也是第一位入選大聯盟全明星賽的台灣選手。他在2006年締造19勝6敗、 防禦率3.63的優異成績，並在季後賽拿下3勝0敗的戰績，幫助洋基隊奪得世界大賽冠軍。王建民也因此成為台灣的棒球英雄，並獲得「台灣之光」的稱號。\n\n然而，王建民在2008年季初因傷缺陣，並在2009年進行了韌帶移植手術。此後，他的成績大幅下滑，並在2012年離開了大聯盟。王建民於2013年回歸中華職棒，效力於義大犀牛隊。2016年，他宣布正式退休。\n\n王建民的職業生涯戰績為127勝72敗， 防禦率3.92，三振數1718次。他是台灣棒球史上最成功的投手之一，也是台灣人民的驕傲。&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;model&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;finishReason&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;STOP&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;index&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;safetyRatings&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;category&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;HARM_CATEGORY_SEXUALLY_EXPLICIT&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;probability&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;NEGLIGIBLE&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;category&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;HARM_CATEGORY_HATE_SPEECH&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;probability&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;NEGLIGIBLE&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;category&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;HARM_CATEGORY_HARASSMENT&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;probability&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;NEGLIGIBLE&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;category&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;HARM_CATEGORY_DANGEROUS_CONTENT&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;probability&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;NEGLIGIBLE&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;promptFeedback&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;safetyRatings&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;category&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;HARM_CATEGORY_SEXUALLY_EXPLICIT&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;probability&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;NEGLIGIBLE&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;category&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;HARM_CATEGORY_HATE_SPEECH&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;probability&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;NEGLIGIBLE&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;category&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;HARM_CATEGORY_HARASSMENT&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;probability&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;NEGLIGIBLE&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;category&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;HARM_CATEGORY_DANGEROUS_CONTENT&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;probability&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;NEGLIGIBLE&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;code>candidates&lt;/code> 就是回應候選內容，目前好像只會有一個，因為輸入的 &lt;code>generationConfig&lt;/code> &amp;gt; &lt;code>candidateCount&lt;/code> 它也只讓我設定 1。&lt;/p>
&lt;ul>
&lt;li>&lt;code>content&lt;/code>：生成回應內容，格式跟輸入的 &lt;code>contents&lt;/code> 一樣。&lt;/li>
&lt;li>&lt;code>finishReason&lt;/code>：模型停止產生 token 的原因。&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>數值&lt;/th>
&lt;th>代表意思&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>FINISH_REASON_UNSPECIFIED&lt;/td>
&lt;td>預設值。這個值未使用。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>STOP&lt;/td>
&lt;td>模型的自然停止或提供的停止序列。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>MAX_TOKENS&lt;/td>
&lt;td>已達到請求中指定的 token 數量上限。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>SAFETY&lt;/td>
&lt;td>內容因安全原因而被標記。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>RECITATION&lt;/td>
&lt;td>內容因遭檢舉為引用原因而被標記。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>OTHER&lt;/td>
&lt;td>未知原因。&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;ul>
&lt;li>&lt;code>index&lt;/code>：此候選內容在候選清單中的索引 (目前只有一則)。&lt;/li>
&lt;li>&lt;code>safetyRatings&lt;/code>：安全性評級清單。顯示此回覆內容在各項安全性類別的等級(可能性)。&lt;/li>
&lt;/ul>
&lt;br/>
&lt;p>我自己在測試時，有時會如下回應，不知道是不是剛推出，所以還不太穩。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;candidates&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[{&lt;/span>&lt;span class="nt">&amp;#34;finishReason&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;OTHER&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nt">&amp;#34;index&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">}],&lt;/span>
&lt;span class="nt">&amp;#34;promptFeedback&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;safetyRatings&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>&lt;span class="nt">&amp;#34;category&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;HARM_CATEGORY_SEXUALLY_EXPLICIT&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nt">&amp;#34;probability&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;NEGLIGIBLE&amp;#34;&lt;/span>&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>&lt;span class="nt">&amp;#34;category&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;HARM_CATEGORY_HATE_SPEECH&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nt">&amp;#34;probability&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;NEGLIGIBLE&amp;#34;&lt;/span>&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>&lt;span class="nt">&amp;#34;category&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;HARM_CATEGORY_HARASSMENT&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nt">&amp;#34;probability&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;NEGLIGIBLE&amp;#34;&lt;/span>&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>&lt;span class="nt">&amp;#34;category&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;HARM_CATEGORY_DANGEROUS_CONTENT&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nt">&amp;#34;probability&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;NEGLIGIBLE&amp;#34;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;p>其他更詳細的說明，請參考以下官方文件：&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://ai.google.dev/api/rest/v1/GenerateContentResponse?hl=zh-tw" target="_blank" rel="noopener">
Gemini API GenerateContentResponse 參考資料
&lt;/a>&lt;/li>
&lt;/ul>
&lt;br/>
&lt;h3 id="python-範例程式碼">Python 範例程式碼&lt;/h3>
&lt;p>在 &lt;a href="https://ai.google.dev/tutorials/python_quickstart" target="_blank" rel="noopener">
官網的範例
&lt;/a> 是使用他們創建的 &lt;a href="https://pypi.org/project/google-generativeai/" target="_blank" rel="noopener">
google-generativeai
&lt;/a> 套件。&lt;br />
不過這邊我想改用我們熟悉的 Requests 套件來嘗試、示範。&lt;/p>
&lt;br/>
&lt;p>首先要確認有安裝 Requests 套件：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">pip install requests
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>那我們開始吧~🏃&lt;/p>
&lt;br/>
&lt;h4 id="單個純文字">單個純文字&lt;/h4>
&lt;p>純粹問它一段話：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="c1"># 單個純文字&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">json&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://generativelanguage.googleapis.com/v1/models/gemini-pro:generateContent?key={API_KEY}&amp;#39;&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;Content-Type&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;application/json&amp;#39;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;contents&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;parts&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[{&lt;/span>&lt;span class="s2">&amp;#34;text&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;你知道王建民嗎？&amp;#34;&lt;/span>&lt;span class="p">}]&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">post&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">json&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;response status_code: {response.status_code}&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dumps&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">indent&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ensure_ascii&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">False&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h4 id="單個純文字--參數">單個純文字 + 參數&lt;/h4>
&lt;p>問它一段話，並且加上一些參數設定：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="c1"># 單個純文字 + 參數&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">json&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://generativelanguage.googleapis.com/v1/models/gemini-pro:generateContent?key={API_KEY}&amp;#39;&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;Content-Type&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;application/json&amp;#39;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;contents&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;parts&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[{&lt;/span>&lt;span class="s2">&amp;#34;text&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;你知道王建民嗎？&amp;#34;&lt;/span>&lt;span class="p">}]&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="s2">&amp;#34;safetySettings&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;category&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;HARM_CATEGORY_DANGEROUS_CONTENT&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;threshold&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;BLOCK_NONE&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="s2">&amp;#34;generationConfig&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;temperature&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">1.0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;maxOutputTokens&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">30&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;topP&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">0.8&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;topK&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">10&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">post&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">json&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;response status_code: {response.status_code}&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dumps&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">indent&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ensure_ascii&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">False&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h4 id="多輪純文字對話聊天">多輪純文字對話（聊天）&lt;/h4>
&lt;p>像在 Bard 或 ChatGPT 上一樣，可以多輪對話，它會記得之前的內容：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="c1"># 多輪對話（聊天）&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">json&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://generativelanguage.googleapis.com/v1/models/gemini-pro:generateContent?key={API_KEY}&amp;#39;&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;Content-Type&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;application/json&amp;#39;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;contents&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;user&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;parts&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[{&lt;/span>&lt;span class="s2">&amp;#34;text&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;你知道王建民嗎？&amp;#34;&lt;/span>&lt;span class="p">}]&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;model&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;parts&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[{&lt;/span>&lt;span class="s2">&amp;#34;text&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;我知道王建民。王建民，1980年3月31日出生於台灣台中市，是一位前台灣棒球選手，司職投手。他曾效力於中華職棒的興農牛隊，美國職棒的紐約洋基隊、華盛頓國民隊和芝加哥白襪隊，以及中國棒球聯賽的北京猛虎隊。&lt;/span>&lt;span class="se">\n\n&lt;/span>&lt;span class="s2">王建民是台灣史上第一位大聯盟先發勝投破百的投手，也是第一位入選大聯盟全明星賽的台灣選手。他在2006年締造19勝6敗、 防禦率3.63的優異成績，並在季後賽拿下3勝0敗的戰績，幫助洋基隊奪得世界大賽冠軍。王建民也因此成為台灣的棒球英雄，並獲得「台灣之光」的稱號。&lt;/span>&lt;span class="se">\n\n&lt;/span>&lt;span class="s2">然而，王建民在2008年季初因傷缺陣，並在2009年進行了韌帶移植手術。此後，他的成績大幅下滑，並在2012年離開了大聯盟。王建民於2013年回歸中華職棒，效力於義大犀牛隊。2016年，他宣布正式退休。&lt;/span>&lt;span class="se">\n\n&lt;/span>&lt;span class="s2">王建民的職業生涯戰績為127勝72敗， 防禦率3.92，三振數1718次。他是台灣棒球史上最成功的投手之一，也是台灣人民的驕傲。&amp;#34;&lt;/span>&lt;span class="p">}]&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;user&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;parts&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[{&lt;/span>&lt;span class="s2">&amp;#34;text&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;他現在在哪裡？&amp;#34;&lt;/span>&lt;span class="p">}]&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">post&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">json&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;response status_code: {response.status_code}&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dumps&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">indent&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ensure_ascii&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">False&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h4 id="單個文字和圖片">單個文字和圖片&lt;/h4>
&lt;p>如果需要 AI 可以看圖片，需要改用 Gemini Pro Vision 模型 (支援文字和圖片輸入)，並且圖片要轉換為 Base64 編碼的字串，&lt;/p>
&lt;p>圖片的 &lt;code>mime_type&lt;/code> 參數目前支援「&lt;code>image/png&lt;/code>」、「&lt;code>image/jpeg&lt;/code>」、「&lt;code>image/heic&lt;/code>」、「&lt;code>image/heif&lt;/code>」、「&lt;code>image/webp&lt;/code>」幾種格式。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="c1"># 單個文字和圖片&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">json&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">base64&lt;/span>
&lt;span class="c1"># 讀取圖片檔案，並轉換成 Base64 編碼的字串&lt;/span>
&lt;span class="k">with&lt;/span> &lt;span class="nb">open&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;gemini_test_image.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;rb&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">image_file&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">image_base64_string&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">base64&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">b64encode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">image_file&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">read&lt;/span>&lt;span class="p">())&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;utf-8&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># print(image_base64_string)&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://generativelanguage.googleapis.com/v1/models/gemini-pro-vision:generateContent?key={API_KEY}&amp;#39;&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;Content-Type&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;application/json&amp;#39;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;contents&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;parts&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;text&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;詳細說明你在這張圖片中看到什麼？&amp;#34;&lt;/span>&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;inline_data&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;mime_type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;image/jpeg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;data&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">image_base64_string&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">post&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">json&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;response status_code: {response.status_code}&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dumps&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">indent&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ensure_ascii&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">False&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;!--adsense-->
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>v1 Beta 版本還有更多功能，像是 &lt;a href="https://ai.google.dev/docs/function_calling" target="_blank" rel="noopener">
函數呼叫(Function calling)
&lt;/a>、&lt;a href="https://ai.google.dev/docs/semantic_retriever" target="_blank" rel="noopener">
語意檢索器(Semantic Retriever、RAG)
&lt;/a>，雖然還在測試中，不建議用於正式版應用，但有興趣的還是可以去玩玩看🤖。&lt;/p>
&lt;p>至少在今年底前使用 Google Gemini API 都是「免費」使用，你想要拿來練習、做專案、做 Side Project 都可以使盡玩(?)，但要注意不要上傳任何敏感資料，因為目前方案所有的輸入輸出都可能會被拿去當訓練資料。&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://deepmind.google/technologies/gemini/" target="_blank" rel="noopener">
Google Gemini 官方網站
&lt;/a>&lt;br />
&lt;a href="https://ai.google.dev/docs?hl=zh-tw" target="_blank" rel="noopener">
Google Gemini API 說明文件
&lt;/a>&lt;br />
&lt;a href="https://makersuite.google.com/" target="_blank" rel="noopener">
Google AI Studio
&lt;/a>&lt;br />
&lt;a href="https://developers.googleblog.com/" target="_blank" rel="noopener">
Google for Developers Blog
&lt;/a>&lt;/p>
&lt;br/>
&lt;blockquote>
&lt;p>The sky&amp;rsquo;s the limit&lt;br />
一切皆有可能&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/gemini_api.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/gemini_api_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Gemini</category><category>LLM</category><category>AI</category><category>人工智慧</category><category>API</category><category>Python</category><category>Google</category><category>分享</category></item><item><title>DataForSEO 教學 — Google、Yahoo 搜尋結果 SERP API</title><link>https://blog.jiatool.com/posts/dataforseo/</link><pubDate>Sat, 18 Nov 2023 21:50:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sat, 18 Nov 2023 21:50:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/dataforseo/</guid><description>(先澄清，以下非業配，純粹依個人使用過程描述。) 前言 在很久之前，我有寫一篇關於第三方 Google 搜尋結果的 API (Aves API) 。而最近又在因緣際會下，被迫(?)接觸</description><content:encoded>&lt;p>(先澄清，以下非業配，純粹依個人使用過程描述。)&lt;/p>
&lt;h2 id="前言">前言&lt;/h2>
&lt;p>在很久之前，我有寫一篇關於第三方 &lt;a href="https://blog.jiatool.com/posts/aves_api" target="_blank" rel="noopener">
Google 搜尋結果的 API (Aves API)
&lt;/a>。而最近又在因緣際會下，被迫(?)接觸了另一個類似的服務平台 — DataForSEO。&lt;/p>
&lt;p>&lt;a href="https://dataforseo.com/" target="_blank" rel="noopener">
DataForSEO
&lt;/a> 提供了更多的服務，包括 Google Search、Google Maps、Google News、Google Images、YouTube、Yahoo Search、Bing Search、百度 Search、Google Play 和 Apple App，還有一些其他商業應用的服務。可以看的出來還蠻多樣的，如果有這方面的需求或許可以參考。&lt;/p>
&lt;p>這次就改以「Yahoo 搜尋 API」當範例，來跟著我一起嘗試這個 API 服務吧，這篇也算把我自己的使用經驗記錄下來。&lt;/p>
&lt;br/>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/dataforseo/dataforseo_home.jpg" alt="DataForSEO 官網" data-caption="DataForSEO 官網" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
DataForSEO 官網
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="serp-api">SERP API&lt;/h2>
&lt;p>官方的 &lt;a href="https://dataforseo.com/apis/serp-api" target="_blank" rel="noopener">
SERP API 頁面
&lt;/a> 有一些簡單的介紹，SERP API 目前支援以下幾種搜尋：&lt;/p>
&lt;ul>
&lt;li>Google SERP&lt;/li>
&lt;li>Google 圖片&lt;/li>
&lt;li>Google 新聞&lt;/li>
&lt;li>Google 地圖&lt;/li>
&lt;li>Yahoo SERP&lt;/li>
&lt;li>Bing SERP&lt;/li>
&lt;li>百度 SERP&lt;/li>
&lt;li>YouTube SERP&lt;/li>
&lt;/ul>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/dataforseo/serp_api.jpg" alt="SERP API 支援的搜尋引擎" data-caption="SERP API 支援的搜尋引擎" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
SERP API 支援的搜尋引擎
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h3 id="搜尋測試頁面">搜尋測試頁面&lt;/h3>
&lt;p>在 DataForSEO 官網上有提供一個 &lt;a href="https://dataforseo.com/apis/serp-api#playground" target="_blank" rel="noopener">
Google SERP 搜尋測試頁面
&lt;/a>，可以實際輸入關鍵字，並查看它回傳的資料，只可惜好像沒有提供台灣的選項。&lt;/p>
&lt;p>但它在使用者後台(需註冊)也有提供一個 API Explorer (就是 Playground) 的 GUI 介面，會完整許多，各種支援的搜尋引擎都可以選，地區也有台灣(並細分到縣市)，也有許多參數可以設定，但這邊就會直接花到錢的 (新帳戶有送 1 美元的額度可供試用)。&lt;/p>
&lt;p>關於使用者後台頁面，我文章後續章節會再介紹。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/dataforseo/playground.jpg" alt="Google SERP 搜尋測試頁面" data-caption="Google SERP 搜尋測試頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
Google SERP 搜尋測試頁面
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h3 id="serp-api-價格">SERP API 價格&lt;/h3>
&lt;p>搜尋 API 價格官方有詳細說明在&lt;a href="https://dataforseo.com/pricing/serp/serp-api" target="_blank" rel="noopener">
這個網頁
&lt;/a>，依照你使用的模式它分為三種價格：STANDARD QUEUE、PRIORITY QUEUE、LIVE MODE。&lt;/p>
&lt;ul>
&lt;li>STANDARD QUEUE：每一次查詢 $0.0006，平均等 5 分鐘。&lt;/li>
&lt;li>PRIORITY QUEUE：每一次查詢 $0.0012，平均等 1 分鐘。&lt;/li>
&lt;li>LIVE MODE：每一次查詢 $0.002，平均等 6 秒。&lt;/li>
&lt;/ul>
&lt;p>* 以上價格為美金&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/dataforseo/serp_pricing.jpg" alt="SERP API 價格" data-caption="SERP API 價格" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
SERP API 價格
&lt;/figcaption>
&lt;/figure>
&lt;p>LIVE MODE 使用上最簡單，只要單一請求就會回傳結果，速度也最快，但價格當然也最貴。&lt;br />
STANDARD QUEUE 和 PRIORITY QUEUE 則是要先發送查詢任務請求，再來定時去問問它查好了沒，最後再取得查詢結果，要分成三段，在程式上寫起來比較麻煩，但它比較便宜(窮人的悲哀QQ)，而 STANDARD QUEUE 和 PRIORITY QUEUE 兩者看起來只差在等待時間及價格。&lt;/p>
&lt;br/>
&lt;p>以下文章我會以 STANDARD QUEUE 和 PRIORITY QUEUE 模式來示範。&lt;/p>
&lt;br/>
&lt;h3 id="api-使用">API 使用&lt;/h3>
&lt;p>SERP API 使用上分為三個請求：&lt;/p>
&lt;ol>
&lt;li>&lt;a href="https://docs.dataforseo.com/v3/serp/yahoo/organic/task_post/" target="_blank" rel="noopener">
Task POST
&lt;/a> (&lt;code>task_post&lt;/code>)：設定任務&lt;/li>
&lt;li>&lt;a href="https://docs.dataforseo.com/v3/serp/yahoo/organic/tasks_ready/" target="_blank" rel="noopener">
Tasks Ready
&lt;/a> (&lt;code>tasks_ready&lt;/code>)：取得已完成任務&lt;/li>
&lt;li>&lt;a href="https://docs.dataforseo.com/v3/serp/yahoo/organic/task_get/regular/" target="_blank" rel="noopener">
Task GET
&lt;/a> (&lt;code>task_get&lt;/code>)：取得任務的結果&lt;/li>
&lt;/ol>
&lt;p>* STANDARD QUEUE、PRIORITY QUEUE 模式的區分是在送出 task_post 請求時，帶上 &lt;code>priority&lt;/code> 參數來指定，&lt;code>1&lt;/code> (預設)代表 STANDARD、&lt;code>2&lt;/code> 代表 PRIORITY。&lt;/p>
&lt;br/>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/dataforseo/serp_api_flow.jpg" alt="SERP API 流程" data-caption="SERP API 流程" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='650px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:650px;height:;"/>
&lt;figcaption style="text-align: center;">
SERP API 流程
&lt;/figcaption>
&lt;/figure>
&lt;ol>
&lt;li>
&lt;p>首先使用 &amp;quot;Task POST&amp;quot; 設定查詢任務，指定關鍵字以及其餘參數，讓它開始去抓我們想要的搜尋結果，這邊最多可以一次給 100 組關鍵字，不過稍微注意有限制每分鐘最多只能發送 2000 個 API 請求。&lt;/p>
&lt;p>* 你也可以指定 &lt;code>pingback_url&lt;/code>，當任務完成時它會主動通知你；&lt;br />
* 或指定 &lt;code>postback_url&lt;/code>，當任務完成時它會主動將結果傳送給你。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>再來使用 &amp;quot;Tasks Ready&amp;quot; 查詢它執行完哪些任務，可以每 10 秒檢查一次，或一分鐘檢查一次，它只有限制每分鐘最多進行 20 次 API 請求。另外，已經被收集的任務(我猜是指已使用 &lt;code>task_get&lt;/code> 取得的任務)和放超過三天未收集的任務會被移除不會在裡面。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>最後，使用 &amp;quot;Task GET&amp;quot; 帶上任務 ID 取得任務的查詢結果，它有分三種 Regular、Advanced、HTML，Regular 就是以 JSON 格式整理好的結果；Advanced 跟 Regular 一樣，只是好像還有多一些特定資訊，我也不是很清楚；HTML 就是回傳搜尋結果的 HTML 格式。&lt;/p>
&lt;p>* 而且任務結果在 30 天內都會保留，用 ID 都可以取得結果。&lt;br />
* 關於搜尋結果不同類別(type)各自代表甚麼，在這邊有官方的圖文說明：&lt;a href="https://dataforseo.com/serp-features">https://dataforseo.com/serp-features&lt;/a>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>* 以上三種請求，只有 &amp;quot;Task POST&amp;quot; 會收費，其餘兩個並不會產生費用。&lt;/p>
&lt;br/>
&lt;br/>
&lt;p>送出的請求 Header 皆需要帶上憑證，確認是哪個帳號發出的，其格式如下：&lt;/p>
&lt;pre>&lt;code>Authorization: Basic ${credentials}
&lt;/code>&lt;/pre>&lt;p>其中 &lt;code>credentials&lt;/code> 是將你的 &amp;quot;API login&amp;quot; 與 &amp;quot;API password&amp;quot; 組的字串 &lt;code>{login}:{password}&lt;/code> 經過 Base64 編碼的結果。&lt;/p>
&lt;p>例如帳號是 &lt;code>jia@gmail.com&lt;/code>、密碼是 &lt;code>abc123&lt;/code>，組成 &lt;code>jia@gmail.com:abc123&lt;/code>，再經過 Base64 變成 &lt;code>amlhQGdtYWlsLmNvbTphYmMxMjM=&lt;/code>。&lt;/p>
&lt;p>* &amp;quot;API login&amp;quot; 與 &amp;quot;API password&amp;quot; 可以在 &lt;a href="https://app.dataforseo.com/api-dashboard" target="_blank" rel="noopener">
使用者後台 API Dashboard
&lt;/a> 網頁找到。&lt;/p>
&lt;br/>
&lt;br/>
&lt;p>對了，&lt;br />
它們 API 還有提供 📦 沙盒模式(Sandbox)，讓我們可以在撰寫程式時做測試，不會花費到費用，但當然回傳的資料就是它們的範例資料，但可以讓我們確認 API 回傳的資料格式、測試程式有沒有問題。&lt;/p>
&lt;p>官方文件：&lt;a href="https://docs.dataforseo.com/v3/appendix/sandbox/">https://docs.dataforseo.com/v3/appendix/sandbox/&lt;/a>&lt;/p>
&lt;br/>
&lt;br/>
&lt;p>* 官方文件有更完整的說明：&lt;a href="https://docs.dataforseo.com/v3/serp/yahoo/overview/">https://docs.dataforseo.com/v3/serp/yahoo/overview/&lt;/a>&lt;/p>
&lt;p>* 其他常見的 Q&amp;amp;A：&lt;a href="https://dataforseo.com/help-center/category/serp-api">https://dataforseo.com/help-center/category/serp-api&lt;/a>&lt;/p>
&lt;br/>
&lt;h3 id="python-範例">Python 範例&lt;/h3>
&lt;p>首先要確認有安裝 Requests 套件：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">pip install requests
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>完整 Python 程式碼：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;span class="lnt">70
&lt;/span>&lt;span class="lnt">71
&lt;/span>&lt;span class="lnt">72
&lt;/span>&lt;span class="lnt">73
&lt;/span>&lt;span class="lnt">74
&lt;/span>&lt;span class="lnt">75
&lt;/span>&lt;span class="lnt">76
&lt;/span>&lt;span class="lnt">77
&lt;/span>&lt;span class="lnt">78
&lt;/span>&lt;span class="lnt">79
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">json&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="k">class&lt;/span> &lt;span class="nc">DataforseoSerp&lt;/span>&lt;span class="p">():&lt;/span>
&lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">credentials&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">open_sandbox&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">False&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">base_url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://api.dataforseo.com/v3/serp&amp;#39;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">open_sandbox&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">base_url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://sandbox.dataforseo.com/v3/serp&amp;#39;&lt;/span> &lt;span class="c1"># 沙盒模式&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">search_engine&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;yahoo&amp;#39;&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;Authorization&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;Basic ${credentials}&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;Content-Type&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;application/json&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">location_code&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1012825&lt;/span> &lt;span class="c1"># New Taipei City,Taiwan&lt;/span>
&lt;span class="c1"># https://docs.dataforseo.com/v3/serp/yahoo/locations/&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">language_code&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;zh-TW&amp;#39;&lt;/span>
&lt;span class="c1"># https://docs.dataforseo.com/v3/serp/yahoo/languages/&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">device&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;desktop&amp;#34;&lt;/span> &lt;span class="c1"># mobile&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">os&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;windows&amp;#34;&lt;/span> &lt;span class="c1"># macos android ios&lt;/span>
&lt;span class="k">def&lt;/span> &lt;span class="nf">task_post&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">keywords&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">depth&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">100&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;span class="s2"> 設定查詢任務，keywords 最多一次可以 100 個，每分鐘最多可以發送 2000 個 API 呼叫
&lt;/span>&lt;span class="s2"> https://docs.dataforseo.com/v3/serp/yahoo/organic/task_post/
&lt;/span>&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">keywords&lt;/span> &lt;span class="ow">is&lt;/span> &lt;span class="bp">None&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="ow">or&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">keywords&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="bp">None&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;{self.base_url}/{self.search_engine}/organic/task_post&amp;#39;&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">keyword&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">keywords&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">data&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">({&lt;/span>
&lt;span class="s2">&amp;#34;keyword&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">keyword&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;location_code&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">location_code&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;language_code&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">language_code&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;device&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">device&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;os&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;depth&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">depth&lt;/span>
&lt;span class="p">})&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">post&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">json&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="k">def&lt;/span> &lt;span class="nf">tasks_ready&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;span class="s2"> 取得已完成的查詢任務
&lt;/span>&lt;span class="s2"> https://docs.dataforseo.com/v3/serp/yahoo/organic/tasks_ready/
&lt;/span>&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;{self.base_url}/{self.search_engine}/organic/tasks_ready&amp;#39;&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="k">def&lt;/span> &lt;span class="nf">task_get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">task_id&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;span class="s2"> 取得查詢任務的結果
&lt;/span>&lt;span class="s2"> https://docs.dataforseo.com/v3/serp/yahoo/organic/task_get/regular/
&lt;/span>&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">task_id&lt;/span> &lt;span class="ow">is&lt;/span> &lt;span class="bp">None&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="bp">None&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;{self.base_url}/{self.search_engine}/organic/task_get/regular/{task_id}&amp;#39;&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">dataforseo_serp&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">DataforseoSerp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;xxxxxxxxxxxxxxxxxxxxxxxxxxx&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">open_sandbox&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dataforseo_serp&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">task_post&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="s2">&amp;#34;飲料&amp;#34;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dumps&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">))&lt;/span>
&lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dataforseo_serp&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tasks_ready&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dumps&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">))&lt;/span>
&lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dataforseo_serp&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">task_get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;11171539-6790-0066-2000-fa82270464a2&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dumps&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">))&lt;/span>
&lt;span class="k">with&lt;/span> &lt;span class="nb">open&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;dataforseo_serp_result.json&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;w&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dump&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>當然比較好的做法，是還要判斷它回傳結果的 &lt;code>status_code&lt;/code> 欄位和 &lt;code>tasks&lt;/code> 底下的 &lt;code>status_code&lt;/code> 欄位，確保任務執行 OK 才去取資料，如果有錯誤，程式內要做相對應處理。&lt;/p>
&lt;p>這邊只是為了示範，我就沒有寫出來了。&lt;/p>
&lt;p>* 各個狀態代碼意思如&lt;a href="https://docs.dataforseo.com/v3/appendix/errors/" target="_blank" rel="noopener">
這個官方清單
&lt;/a>。&lt;/p>
&lt;br/>
&lt;h2 id="使用者後台">使用者後台&lt;/h2>
&lt;p>當註冊後登入，即可進入 &lt;a href="https://app.dataforseo.com/api-dashboard" target="_blank" rel="noopener">
使用者後台頁面
&lt;/a> 去查看更多相關資訊。&lt;/p>
&lt;p>其中有幾個重要的頁面：&lt;/p>
&lt;ul>
&lt;li>API Dashboard (儀錶板)&lt;/li>
&lt;li>API Usage (使用紀錄)&lt;/li>
&lt;li>API Errors (錯誤紀錄)&lt;/li>
&lt;li>API Explorer (API Playground)&lt;/li>
&lt;li>API Settings (設定 API 限制)&lt;/li>
&lt;/ul>
&lt;h3 id="api-dashboard-儀錶板">API Dashboard (儀錶板)&lt;/h3>
&lt;p>有顯示你的 &amp;quot;API login&amp;quot; 與 &amp;quot;API password&amp;quot;，以及圖表化顯示每天的花費。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/dataforseo/api_dashboard.jpg" alt="API Dashboard (儀錶板) 頁面" data-caption="API Dashboard (儀錶板) 頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='850px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:850px;height:;"/>
&lt;figcaption style="text-align: center;">
API Dashboard (儀錶板) 頁面
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="api-usage-使用紀錄">API Usage (使用紀錄)&lt;/h3>
&lt;p>就是你 API 的呼叫紀錄，它有將不同種類的 API 區分開來，方便我們查找。&lt;br />
有紀錄任務 ID、執行時間、執行狀態、花費、送出的參數，甚至可以從這邊看到查詢結果(等同於 &amp;quot;Task GET&amp;quot; 請求)。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/dataforseo/api_usage.jpg" alt="API Usage (使用紀錄) 頁面" data-caption="API Usage (使用紀錄) 頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='850px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:850px;height:;"/>
&lt;figcaption style="text-align: center;">
API Usage (使用紀錄) 頁面
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="api-errors-錯誤紀錄">API Errors (錯誤紀錄)&lt;/h3>
&lt;p>發生錯誤的 API 請求會在這頁列出來。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/dataforseo/api_errors.jpg" alt="API Errors (錯誤紀錄) 頁面" data-caption="API Errors (錯誤紀錄) 頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='850px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:850px;height:;"/>
&lt;figcaption style="text-align: center;">
API Errors (錯誤紀錄) 頁面
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="api-explorer-api-playground">API Explorer (API Playground)&lt;/h3>
&lt;p>以圖形化的操作頁面，讓你實際測試 API 的結果是否符合你的預期，有輸入框讓你設定 API 不同參數，像是用哪個搜尋引擎、地區(有細分到縣市)、語言、電腦版或手機版、作業系統、關鍵字。&lt;/p>
&lt;p>但要稍微注意，這邊是會直接花到錢的 (新帳戶有送 1 美元的額度可供試用)。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/dataforseo/api_explorer.jpg" alt="API Explorer (API Playground) 頁面" data-caption="API Explorer (API Playground) 頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='850px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:850px;height:;"/>
&lt;figcaption style="text-align: center;">
API Explorer (API Playground) 頁面
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="api-settings-設定-api-限制">API Settings (設定 API 限制)&lt;/h3>
&lt;p>能設定可以呼叫 API 的 IP 白名單、限制每日最大花費額度(總共額度，或也可以細到 by 不同 API 去限制)。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/dataforseo/api_settings.jpg" alt="API Settings (設定 API 限制) 頁面" data-caption="API Settings (設定 API 限制) 頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='850px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:850px;height:;"/>
&lt;figcaption style="text-align: center;">
API Settings (設定 API 限制) 頁面
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h2 id="注意事項">注意事項&lt;/h2>
&lt;p>我在使用 Yahoo 搜尋 API 時發現，我明明設定要 100 筆結果(&lt;code>depth=100&lt;/code>)，結果回傳只有 70 筆、甚至 40 幾筆而已的，我也有透過 API 回傳的 &lt;code>check_url&lt;/code> 網址去確認，經過詢問與確認，官方是這樣答覆我：&lt;/p>
&lt;blockquote>
&lt;p>Today, you contacted our Support Team and provided us with ID of your task sent to the Yahoo Serp API that returned fewer results than expected.&lt;br />
Our developers have carefully checked the situation and explained that such a search engine has some limitations. To avoid timeouts, we have a restriction that allows us to crawl up to 6 pages of the ordinary SERP (the one you can see in a browser). Taking into account that each page contains 7-8 results. In total, the API does not return more than 50 results.&lt;br />
If we remove such a restriction globally, this API will return 500 errors, and since we will have to send numerous requests to this search engine, it may harm it due to high traffic coming from us. I hope it makes sense.&lt;br />
Hope for your understanding!&lt;/p>
&lt;/blockquote>
&lt;p>也就是可能他們的 Yahoo 搜尋 API 很可能沒辦法抓到我們指定的筆數，除非你只需要第一頁，或前三頁之類的，不然這也是很困擾，要特別注意。&lt;/p>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>相比上次使用的 Aves API 來說，DataForSEO 真的多了非常多的服務，而且價格貌似也比較便宜。官方同樣有線上客服，有相關需求都可以直接詢問，回應速度還蠻快的。&lt;/p>
&lt;p>當然我目前只是短暫的嘗試，還不確定它長久、大量地使用下來穩定性如何，這部分有需求的人可以自行比較看看。&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://dataforseo.com/" target="_blank" rel="noopener">
DataForSEO 官方網站
&lt;/a>&lt;br />
&lt;a href="https://docs.dataforseo.com/v3/" target="_blank" rel="noopener">
DataForSEO 官方文檔
&lt;/a>&lt;br />
&lt;a href="https://app.dataforseo.com/api-dashboard" target="_blank" rel="noopener">
DataForSEO Dashboard 後台
&lt;/a>&lt;/p>
&lt;br/>
&lt;blockquote>
&lt;p>「失敗很正常，如果沒有經歷失敗，表示你還不夠創新。」&lt;br />
Failure is an option here. If things are not failing, you are not innovating enough.&lt;/p>
&lt;p align="right">—— Elon Musk 伊隆·馬斯克 (著名企業家)&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/dataforseo.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/dataforseo_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Google搜尋</category><category>Yahoo搜尋</category><category>SEO</category><category>API</category><category>Python</category><category>分享</category></item><item><title>(2023年新版) 使用 Streamlit 簡單又快速建立 Dashboard 網頁</title><link>https://blog.jiatool.com/posts/streamlit_2023/</link><pubDate>Sun, 17 Sep 2023 21:35:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sun, 17 Sep 2023 21:35:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/streamlit_2023/</guid><description>前言 之前寫這篇 Streamlit 的教學文章 已經過去兩年多了，陸續官方還增加了許多功能與優化，而且從我部落格後台的數據來看，發現那篇文章還蠻多人觀看。因此決定</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>之前寫&lt;a href="https://blog.jiatool.com/posts/streamlit" target="_blank" rel="noopener">
這篇 Streamlit 的教學文章
&lt;/a>已經過去兩年多了，陸續官方還增加了許多功能與優化，而且從我部落格後台的數據來看，發現那篇文章還蠻多人觀看。因此決定再寫篇更新的內容，並多補充一些細節。&lt;/p>
&lt;p>此篇文章使用的 Streamlit 是 v1.26.0 版本。&lt;/p>
&lt;br/>
&lt;p>Streamlit 幫助我們快速製作 Web 應用程式，而且不需要任何前端技能，全部都採用 Python 語法完成。讓你輕鬆分享網路爬蟲、數據科學和機器學習的資料，是一個非常方便的套件。&lt;/p>
&lt;p>* 文章最後會附上完整的範例程式碼，請一定看到最後~&lt;/p>
&lt;br/>
&lt;h2 id="demo">Demo&lt;/h2>
&lt;p>這是最後將程式碼放到 GitHub，並使用 Streamlit Cloud 部署的成果。&lt;/p>
&lt;div class="alert alert-info" role="alert" data-dir="ltr">Streamlit 成果範例：&lt;a href="https://jiatool-demo.streamlit.app/">streamlit_2023_demo&lt;/a>&lt;/div>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/demo.jpg" alt="Streamlit Demo 範例" data-caption="Streamlit Demo 範例" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
Streamlit Demo 範例
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="安裝與執行">安裝與執行&lt;/h2>
&lt;ul>
&lt;li>Streamlit [&lt;a href="https://streamlit.io/" target="_blank" rel="noopener">
官方網站
&lt;/a>] [&lt;a href="https://docs.streamlit.io/" target="_blank" rel="noopener">
官方文檔
&lt;/a>]&lt;/li>
&lt;/ul>
&lt;p>安裝&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">pip install streamlit
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>撰寫本篇文章時最新版為：v1.26.0&lt;/p>
&lt;p>執行&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">streamlit run &amp;lt;py程式檔案路徑&amp;gt;
&lt;span class="c1"># 以我下方文章範例的話，就是：&lt;/span>
streamlit run streamlit_app.py
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>如果想指定 Streamlit 的 port 埠號，只要在後方加上&lt;code>--server.port&lt;/code> 參數：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">streamlit run &amp;lt;py程式檔案路徑&amp;gt; --server.port &lt;span class="m">8888&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>需要終止該應用程式只需在終端中按 &lt;strong>Ctrl + c&lt;/strong>。&lt;/p>
&lt;br/>
&lt;h2 id="創建-streamlit-應用程式">創建 Streamlit 應用程式&lt;/h2>
&lt;p>除了跟著我以下的文章流程學習，也可以參考 &lt;a href="https://docs.streamlit.io/library/get-started" target="_blank" rel="noopener">
官方文檔 Get started
&lt;/a> 的流程操作。&lt;/p>
&lt;h3 id="新增-py-程式碼">新增 py 程式碼&lt;/h3>
&lt;p>新創建一個 Python 檔案 &lt;code>streamlit_app.py&lt;/code>，以下教學都只會編輯這個檔案。&lt;/p>
&lt;p>打開它，在一開始導入 Streamlit 與範例需要的其他套件：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">time&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">streamlit&lt;/span> &lt;span class="kn">as&lt;/span> &lt;span class="nn">st&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">numpy&lt;/span> &lt;span class="kn">as&lt;/span> &lt;span class="nn">np&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">pandas&lt;/span> &lt;span class="kn">as&lt;/span> &lt;span class="nn">pd&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;p>打開 &amp;quot;命令提示字元&amp;quot; 或 &amp;quot;終端機&amp;quot;，開始執行程式：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">streamlit run streamlit_app.py
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>* 第一次執行時，它可能會問你 Email，這可以不用理它，直接按 Enter 即可。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/streamlit_run_email.png" alt="執行 Streamlit 程式，第一次會遇到 Email" data-caption="執行 Streamlit 程式，第一次會遇到 Email" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
執行 Streamlit 程式，第一次會遇到 Email
&lt;/figcaption>
&lt;/figure>
&lt;p>它應該會顯示如下資訊，並自動開啟一個瀏覽器網頁。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/run_streamlit.png" alt="執行 Streamlit 程式" data-caption="執行 Streamlit 程式" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
執行 Streamlit 程式
&lt;/figcaption>
&lt;/figure>
&lt;p>然後網頁裡面顯示&amp;hellip; 一片空白？！&lt;br />
沒錯！我們又還沒有添加元件進去，怎麼會有東西呢~ 😆&lt;/p>
&lt;br/>
&lt;h3 id="添加文字和數據">添加文字和數據&lt;/h3>
&lt;p>先幫我們的應用程式上個標題，加入以下程式碼：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">title&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;我的第一個應用程式&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>存檔，回到瀏覽器的網頁上。&lt;/p>
&lt;p>可以重整網頁，或點擊右上角菜單內 &amp;quot;Rerun&amp;quot; 的按鈕，&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/rerun.jpg" alt="Rerun 重整網頁" data-caption="Rerun 重整網頁" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='350px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:350px;height:;"/>
&lt;figcaption style="text-align: center;">
Rerun 重整網頁
&lt;/figcaption>
&lt;/figure>
&lt;p>網頁上就會顯示一個標題文字了：&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/first_title.jpg" alt="試著加入標題吧" data-caption="試著加入標題吧" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
試著加入標題吧
&lt;/figcaption>
&lt;/figure>
&lt;p>如何？簡單吧，那我們再繼續接著下去~&lt;/p>
&lt;br/>
&lt;h3 id="使用-stwrite-和-magic-commands">使用 &lt;code>st.write&lt;/code> 和 Magic Commands&lt;/h3>
&lt;p>在 Streamlit 內有個神奇的指令，他們把它叫 &lt;a href="https://docs.streamlit.io/library/api-reference/write-magic" target="_blank" rel="noopener">
&lt;code>st.write&lt;/code> 和 Magic Commands
&lt;/a>，不管給它 &amp;quot;字串&amp;quot;、&amp;quot;Markdown&amp;quot;、&amp;quot;數據資料&amp;quot; 還是 &amp;quot;圖表&amp;quot;，Streamlit 都會自動辨別並以合適的方式顯示出來。&lt;/p>
&lt;p>在程式碼中只要把想顯示的東西放進 &lt;code>st.write&lt;/code>，甚至單一行只有變數或字串，根本不需要使用 &lt;code>st.write&lt;/code>，它都會自動套用並顯示。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;嘗試創建**表格**：&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">df&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">({&lt;/span>
&lt;span class="s1">&amp;#39;first column&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">4&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="s1">&amp;#39;second column&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">20&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">30&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">40&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="p">})&lt;/span>
&lt;span class="n">df&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/magic_commands.jpg" alt="呈現 Markdown 與 表格" data-caption="呈現 Markdown 與 表格" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
呈現 Markdown 與 表格
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>但是官方有提到有以下三個原因，如果可以的話還是使用更具體的方法比較好：&lt;/p>
&lt;ol>
&lt;li>&lt;code>Magic&lt;/code> 和 &lt;code>st.write()&lt;/code> 會檢查您傳入的數據類型，然後決定如何最好地呈現，但有時你可能想以另一種方式呈現它。&lt;/li>
&lt;li>其他方法返回一個可以使用和修改的對象，可以通過向其添加數據或替換它。&lt;/li>
&lt;li>如果使用更具體的 Streamlit 方法，您可以傳遞其他參數來自定義其行為。&lt;/li>
&lt;/ol>
&lt;br/>
&lt;h3 id="繪製圖表和地圖-chart">繪製圖表和地圖 Chart&lt;/h3>
&lt;h5 id="折線圖-stline_chart">折線圖 &lt;code>st.line_chart()&lt;/code>&lt;/h5>
&lt;p>使用 Numpy 生成一個隨機樣本，然後將其繪製成折線圖。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">chart_data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">20&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">),&lt;/span>
&lt;span class="n">columns&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;a&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;b&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;c&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">line_chart&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">chart_data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>而且它本身有下載、全螢幕觀看等功能。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/line_chart.jpg" alt="繪製折線圖" data-caption="繪製折線圖" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='650px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:650px;height:;"/>
&lt;figcaption style="text-align: center;">
繪製折線圖
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h5 id="地圖-stmap">地圖 &lt;code>st.map()&lt;/code>&lt;/h5>
&lt;p>使用 Numpy 生成一個隨機樣本，繪製到地圖上。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">map_data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">100&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mi">50&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">50&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mf">22.6&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">120.4&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="n">columns&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;lat&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;lon&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">map&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">map_data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/map.jpg" alt="繪製地圖" data-caption="繪製地圖" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='650px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:650px;height:;"/>
&lt;figcaption style="text-align: center;">
繪製地圖
&lt;/figcaption>
&lt;/figure>
&lt;p>更多圖表元件請參考：&lt;a href="https://docs.streamlit.io/library/api-reference/charts" target="_blank" rel="noopener">
官方文件 Chart elements
&lt;/a>&lt;/p>
&lt;br/>
&lt;h3 id="輸入類元件">輸入類元件&lt;/h3>
&lt;p>除了上述標題、圖表，還有其他小工具，像是按鈕、選擇框、複選框、滑塊等等。&lt;/p>
&lt;br/>
&lt;h5 id="按鈕-stbutton">按鈕 &lt;code>st.button()&lt;/code>&lt;/h5>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">if&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">button&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;不要按!&amp;#39;&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;不是叫你不要按了嗎！&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/button.png" alt="按鈕元件" data-caption="按鈕元件" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='400px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:400px;height:;"/>
&lt;figcaption style="text-align: center;">
按鈕元件
&lt;/figcaption>
&lt;/figure>
&lt;p>但你可能會注意到，每次點擊按鈕時，上方的折線圖也會產生變化。&lt;br />
這是因為 Streamlit 只要元件有輸入值的改變，整個程式(網頁)就會重新運行，因此折線圖裡的 random 才會出來不同資料。&lt;/p>
&lt;br/>
&lt;h5 id="複選框-stcheckbox">複選框 &lt;code>st.checkbox()&lt;/code>&lt;/h5>
&lt;p>使用複選框來顯示/隱藏數據，例如將剛剛繪製地圖的程式改成：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">if&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">checkbox&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;顯示地圖圖表&amp;#39;&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="n">map_data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">100&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mi">50&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">50&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mf">22.6&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">120.4&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="n">columns&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;lat&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;lon&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">map&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">map_data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h5 id="選擇框-stselectbox">選擇框 &lt;code>st.selectbox()&lt;/code>&lt;/h5>
&lt;p>使用選擇框提供使用者選擇：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">option&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">selectbox&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="s1">&amp;#39;你喜歡哪種動物？&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;狗&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;貓&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;鸚鵡&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;天竺鼠&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;你的答案：{option}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/checkbox_selectbox.jpg" alt="複選框 與 選擇框" data-caption="複選框 與 選擇框" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='650px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:650px;height:;"/>
&lt;figcaption style="text-align: center;">
複選框 與 選擇框
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h3 id="調整佈局-layout">調整佈局 Layout&lt;/h3>
&lt;p>除了剛剛示範的一行一個元件，Streamlit 有提供幾種佈局容器元件供使用、排版。&lt;/p>
&lt;br/>
&lt;h5 id="側邊欄-stsidebar">側邊欄 &lt;code>st.sidebar&lt;/code>&lt;/h5>
&lt;p>例如我們能將元件移到側邊欄中，這邊範例將剛剛的選擇框移入側邊欄：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">option&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sidebar&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">selectbox&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="s1">&amp;#39;你喜歡哪種動物？&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;狗&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;貓&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;鸚鵡&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;天竺鼠&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sidebar&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;你的答案：{option}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/sidebar.jpg" alt="將元件移到側邊欄" data-caption="將元件移到側邊欄" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='750px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:750px;height:;"/>
&lt;figcaption style="text-align: center;">
將元件移到側邊欄
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h5 id="列容器-stcolumns">列容器 &lt;code>st.columns()&lt;/code>&lt;/h5>
&lt;p>也有左右兩邊的方式來排列的容器：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">left_column&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">right_column&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">columns&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">left_column&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;這是左邊欄位。&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">right_column&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;這是右邊欄位。&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h5 id="展開容器-stexpander">展開容器 &lt;code>st.expander()&lt;/code>&lt;/h5>
&lt;p>也可以通過能展開的容器，來隱藏大量內容來節省空間：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">expander&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">expander&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;點擊來展開...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">expander&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;如果你要顯示很多文字，但又不想佔大半空間，可以使用這種方式。&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/expander.png" alt="將內容摺疊起來，節省空間" data-caption="將內容摺疊起來，節省空間" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
將內容摺疊起來，節省空間
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h5 id="分頁容器-sttabs">分頁容器 &lt;code>st.tabs()&lt;/code>&lt;/h5>
&lt;p>或者切出不同分頁，來放置不同種類的資料：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">tab1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">tab2&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tabs&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="s2">&amp;#34;Cat 介紹&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;Dog 介紹&amp;#34;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="k">with&lt;/span> &lt;span class="n">tab1&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">header&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;A cat&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">image&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;https://static.streamlit.io/examples/cat.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">width&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">200&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">with&lt;/span> &lt;span class="n">tab2&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">header&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;A dog&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">image&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;https://static.streamlit.io/examples/dog.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">width&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">200&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/tabs.jpg" alt="不同分頁，放置不同種類的資料" data-caption="不同分頁，放置不同種類的資料" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
不同分頁，放置不同種類的資料
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>其他更多佈局和容器請參考：&lt;a href="https://docs.streamlit.io/library/api-reference/layout" target="_blank" rel="noopener">
官方文件 Layouts and Containers
&lt;/a>&lt;/p>
&lt;br/>
&lt;h3 id="狀態元件-status">狀態元件 Status&lt;/h3>
&lt;h5 id="進度條-stprogress">進度條 &lt;code>st.progress()&lt;/code>&lt;/h5>
&lt;p>使用 &lt;code>time.sleep()&lt;/code> 來模擬進度條的等待：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">bar&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">progress&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">100&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="n">bar&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">progress&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">i&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;目前進度 {i+1} %&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">0.05&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">bar&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">progress&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">100&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;載入完成！&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>而且網頁右上角還會顯示&amp;quot;RUNNING&amp;hellip;&amp;quot;，並有多個運動圖示跳動，讓使用者知道目前網頁中還有東西正在運行。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/progress.jpg" alt="進度條載入時，網頁右上角 RUNNING... 字樣" data-caption="進度條載入時，網頁右上角 RUNNING... 字樣" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
進度條載入時，網頁右上角 RUNNING... 字樣
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h5 id="消息通知-sttoast">消息通知 &lt;code>st.toast()&lt;/code>&lt;/h5>
&lt;p>當有時候我們會需要跳出一個消息通知使用者，但並不想太干擾使用者，這時候就可以使用 &lt;code>st.toast()&lt;/code>：&lt;/p>
&lt;p>* 也可以為文字加上顏色，和加上 icon。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">if&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">button&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;儲存&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;primary&amp;#34;&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">toast&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;:rainbow[你編輯的內容已經保存]&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">icon&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;💾&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 或是簡單點，只顯示文字&lt;/span>
&lt;span class="c1"># st.toast(&amp;#39;你編輯的內容已經保存&amp;#39;)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h5 id="box-訊息-stsuccessstinfostwarningsterror">box 訊息 &lt;code>st.success()&lt;/code>、&lt;code>st.info()&lt;/code>、&lt;code>st.warning()&lt;/code>、&lt;code>st.error()&lt;/code>&lt;/h5>
&lt;p>或者想要在頁面上顯示較醒目的錯誤訊息：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">success&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;Success!&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">info&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;Info!&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">warning&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;Warning!&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">error&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;Error!&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">icon&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;🚨&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/toast_and_box.jpg" alt="box 訊息 和右下角的 toast 消息" data-caption="box 訊息 和右下角的 toast 消息" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
box 訊息 和右下角的 toast 消息
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h5 id="特效-stballoons-與-stsnow">特效 &lt;code>st.balloons()&lt;/code> 與 &lt;code>st.snow()&lt;/code>&lt;/h5>
&lt;p>還有看似無用，但真的好像無用(?)的特效，慶祝氣球 &lt;code>st.balloons()&lt;/code> 與慶祝降雪 &lt;code>st.snow()&lt;/code>：&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/balloons.jpg" alt="慶祝氣球特效" data-caption="慶祝氣球特效" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='650px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:650px;height:;"/>
&lt;figcaption style="text-align: center;">
慶祝氣球特效
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h3 id="聊天元件-chat">聊天元件 Chat&lt;/h3>
&lt;h5 id="聊天元件-stchat_message-與-stchat_input">聊天元件 &lt;code>st.chat_message()&lt;/code> 與 &lt;code>st.chat_input()&lt;/code>&lt;/h5>
&lt;p>最近因為 ChatGPT 之類的 LLM 熱門而新增的 &amp;quot;聊天元件&amp;quot; &lt;code>st.chat_message()&lt;/code>、&lt;code>st.chat_input()&lt;/code>：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">with&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">chat_message&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;user&amp;#34;&lt;/span>&lt;span class="p">):&lt;/span> &lt;span class="c1"># 或者寫 &amp;#34;human&amp;#34;&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Hi 👋，請問你是誰？&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 另一種寫法&lt;/span>
&lt;span class="n">message&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">chat_message&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;assistant&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 或者寫 &amp;#34;ai&amp;#34;&lt;/span>
&lt;span class="c1"># message = st.chat_message(&amp;#34;assistant&amp;#34;, avatar=&amp;#34;🦖&amp;#34;) # 自訂頭像&lt;/span>
&lt;span class="n">message&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;你好！我是 ChatBot 🤖，可以回答各種問題，提供資訊。&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">message&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;有什麼我可以幫助你的嗎？&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">chat_input&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Say something...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/chat_message.jpg" alt="因應最近 LLM 熱門而新增的聊天元件" data-caption="因應最近 LLM 熱門而新增的聊天元件" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
因應最近 LLM 熱門而新增的聊天元件
&lt;/figcaption>
&lt;/figure>
&lt;p>官方還特別寫兩篇教你如何搭建一個對話式的應用程式，甚至示範如何串接 OpenAI 的 GPT 模型，或透過 LangChain 串接：&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://docs.streamlit.io/knowledge-base/tutorials/build-conversational-apps" target="_blank" rel="noopener">
Build conversational apps
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://docs.streamlit.io/knowledge-base/tutorials/llm-quickstart" target="_blank" rel="noopener">
LLM quickstart
&lt;/a>&lt;/li>
&lt;/ul>
&lt;br/>
&lt;h3 id="表單元件">表單元件&lt;/h3>
&lt;h5 id="表單-stform">表單 &lt;code>st.form()&lt;/code>&lt;/h5>
&lt;p>經過上面的嘗試，我們都發現在 Streamlit 中，操作每個元件都會導致整個應用程式重新運行。&lt;/p>
&lt;p>但是，有時我們可能希望像表單那樣，全部填寫好後再一次觸發(提交)，這時候就可以使用 &lt;code>st.form()&lt;/code> 表單元件：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">with&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">form&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;my_form&amp;#39;&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="n">form_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text_input&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">label&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;姓名&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">placeholder&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;請輸入姓名&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">form_gender&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">selectbox&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;性別&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;男&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;女&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;其他&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="n">form_birthday&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">date_input&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;生日&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">submit_button&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">form_submit_button&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">label&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;Submit&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">submit_button&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;hello {form_name}, 性別:{form_gender}, 生日:{form_birthday}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/form.png" alt="使用表單元件，一次一起提交" data-caption="使用表單元件，一次一起提交" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
使用表單元件，一次一起提交
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h3 id="使用快取-caching">使用快取 Caching&lt;/h3>
&lt;p>如同前面所述，只要元件輸入值有改變，整個程式(網頁)就會重新運行，但假如有較耗費時間、資源的運算，會造成使用者每調一個參數，就浪費時間在等待，或者產生的物件被重置。&lt;/p>
&lt;p>因此 Streamlit 內提供兩種快取(Caching)機制，將之前運算過的結果快取起來，如果下次遇到一樣的輸入值，就能直接使用之前的結果，節省時間，也有助於在重新運行時持久保存物件。&lt;/p>
&lt;p>這兩種快取機制以裝飾器(Decorator)寫法使用，用途區分如下：&lt;/p>
&lt;ol>
&lt;li>&lt;code>@st.cache_data&lt;/code>：計算後的結果、從 CSV 加載 DataFrame、查詢 API&amp;hellip;，大多情況都可以使用 &lt;code>@st.cache_data&lt;/code>。&lt;/li>
&lt;li>&lt;code>@st.cache_resource&lt;/code>：全域資源，例如 ML 模型或資料庫連接。&lt;/li>
&lt;/ol>
&lt;figure >
&lt;img data-src="https://docs.streamlit.io/images/caching-high-level-diagram.png" alt="Streamlit 提供兩種緩存(Caching)機制" data-caption="Streamlit 提供兩種緩存(Caching)機制" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='550px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:550px;height:;"/>
&lt;figcaption style="text-align: center;">
Streamlit 提供兩種緩存(Caching)機制
&lt;/figcaption>
&lt;/figure>
&lt;p>對於會變動的資料來源，建議可以設定 ttl (time to live)，例如設定 &lt;code>ttl=300&lt;/code>，則快取會在 3600 秒 (1小時) 後失效，並在重新運行函數時，再次執行、緩存快取。&lt;/p>
&lt;p>對於資料量太大造成記憶體可能不足問題，則可以設定 &lt;code>max_entries=1000&lt;/code> 來限制最大資料筆數。&lt;/p>
&lt;p>* 更多說明請參考官方文件：&lt;a href="https://docs.streamlit.io/library/advanced-features/caching" target="_blank" rel="noopener">
Caching
&lt;/a>&lt;/p>
&lt;br/>
&lt;p>要使用 &lt;code>@st.cache_data&lt;/code> 裝飾器，就需要將運算部分的程式碼包成函式(def)。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="nd">@st.cache_data&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ttl&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">3600&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">show_spinner&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;正在加載資料...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 👈 Add the caching decorator&lt;/span>
&lt;span class="k">def&lt;/span> &lt;span class="nf">load_data&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="n">df&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">read_csv&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">df&lt;/span>
&lt;span class="n">df&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">load_data&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;https://raw.githubusercontent.com/plotly/datasets/master/26k-consumer-complaints.csv&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dataframe&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">df&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>第一次載入時會跑比較久(上面範例是讓它到網路上下載 csv 資料後顯示)，之後再重整網頁時，因為有快取的關係，它應該一瞬間就顯示出來了。&lt;/p>
&lt;br/>
&lt;p>如果想要清除快取再測試，可以從右上角的選單選擇 &amp;quot;Clear caches&amp;quot;：&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/clear_caches.jpg" alt="右上角選單 &amp;#34;Clear caches&amp;#34; 可以清除快取" data-caption="右上角選單 &amp;#34;Clear caches&amp;#34; 可以清除快取" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
右上角選單 &amp;#34;Clear caches&amp;#34; 可以清除快取
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h3 id="網頁配置設定">網頁配置設定&lt;/h3>
&lt;div class="alert alert-warning" role="alert" data-dir="ltr">網頁配置程式碼要寫在所有 Streamlit 命令之前，而且只能設定一次。&lt;/div>
&lt;p>此函式有五個參數：&lt;/p>
&lt;ul>
&lt;li>page_title：網頁標題，顯示在瀏覽器分頁的標籤上，預設是程式碼的檔名。&lt;/li>
&lt;li>page_icon：網頁圖標，顯示在網頁標題前，可以使用 &lt;code>st.image&lt;/code> 或 Emoji，或者使用&amp;quot;random&amp;quot;讓它隨機產生XD。&lt;/li>
&lt;li>layout：網頁中佈局寬度，預設是&amp;quot;centered&amp;quot;，還可以使用&amp;quot;wide&amp;quot;。&lt;/li>
&lt;li>initial_sidebar_state：側邊欄顯示狀態，&amp;quot;expanded&amp;quot;打開或&amp;quot;collapsed&amp;quot;隱藏，預設是&amp;quot;auto&amp;quot;，代表在手機尺寸的設備上是隱藏，否則是打開顯示。&lt;/li>
&lt;li>menu_items：右上角的菜單設定，共有以下三項可以設定：
&lt;ul>
&lt;li>&amp;ldquo;Get help&amp;rdquo;：設定 URL，如果沒有，則會隱藏此菜單選項。&lt;/li>
&lt;li>&amp;ldquo;Report a Bug&amp;rdquo;：設定 URL，如果沒有，則會隱藏此菜單選項。&lt;/li>
&lt;li>&amp;ldquo;About&amp;rdquo;：顯示在 &amp;quot;關於&amp;quot; 彈跳視窗中的 Markdown 字串，如果沒有，則僅顯示 Streamlit 預設的內容。&lt;/li>
&lt;li>URL 也可以設定為電子郵件地址，像是 &lt;code>mailto:john@example.com&lt;/code>。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>官方文件：&lt;a href="https://docs.streamlit.io/library/api-reference/utilities/st.set_page_config" target="_blank" rel="noopener">
st.set_page_config
&lt;/a>&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/web_page.png" alt="自訂網頁標題與 icon" data-caption="自訂網頁標題與 icon" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
自訂網頁標題與 icon
&lt;/figcaption>
&lt;/figure>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">set_page_config&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">page_title&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;自定義網頁標題&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">page_icon&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;random&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">layout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;centered&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">initial_sidebar_state&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;expanded&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">menu_items&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;Get Help&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;https://blog.jiatool.com/about/&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;About&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;# 這是什麼網頁？ &lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">**[IT空間](https://blog.jiatool.com/)** 示範 streamlit 之用網頁&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;p>在網頁右上方選單，除了之前提過的 Rerun 和清除快取，還有網頁設定與螢幕錄影功能，將你的操作流程直接錄影起來，展示給其他人。&lt;/p>
&lt;p>而選單內的&amp;quot;設定&amp;quot;有幾個選項：&lt;/p>
&lt;ul>
&lt;li>Run on save：程式存檔後網頁自動重跑，不需要再手動點 Rerun&lt;/li>
&lt;li>Wide mode：佈局寬度調寬&lt;/li>
&lt;li>Theme：選擇或自訂佈景主題&lt;/li>
&lt;/ul>
&lt;p>* 自定義主題可參考&lt;a href="https://docs.streamlit.io/library/advanced-features/theming" target="_blank" rel="noopener">
官方介紹說明
&lt;/a>。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/settings.jpg" alt="右上角選單 &amp;#34;Settings&amp;#34; 網頁設定" data-caption="右上角選單 &amp;#34;Settings&amp;#34; 網頁設定" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
右上角選單 &amp;#34;Settings&amp;#34; 網頁設定
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h3 id="更多的元件工具">更多的元件、工具&lt;/h3>
&lt;p>Streamlit 還有提供更多的元件，和或者其他用途的工具：&lt;/p>
&lt;ul>
&lt;li>連接 &amp;quot;Database 資料庫&amp;quot; 或 &amp;quot;Web API&amp;quot; 取得資料：&lt;a href="https://docs.streamlit.io/library/advanced-features/connecting-to-data" target="_blank" rel="noopener">
Connecting to data
&lt;/a>&lt;/li>
&lt;li>設定主題顏色的配置：&lt;a href="https://docs.streamlit.io/library/advanced-features/theming" target="_blank" rel="noopener">
Theming
&lt;/a>&lt;/li>
&lt;li>做成多頁的應用：&lt;a href="https://docs.streamlit.io/library/get-started/multipage-apps" target="_blank" rel="noopener">
Multipage apps
&lt;/a>&lt;/li>
&lt;li>設定和取得瀏覽器網址列的查詢參數：&lt;a href="https://docs.streamlit.io/library/api-reference/utilities/st.experimental_set_query_params" target="_blank" rel="noopener">
st.experimental_set_query_params()
&lt;/a>、&lt;a href="https://docs.streamlit.io/library/api-reference/utilities/st.experimental_get_query_params" target="_blank" rel="noopener">
st.experimental_get_query_params()
&lt;/a>&lt;/li>
&lt;li>託管靜態文件服務：&lt;a href="https://docs.streamlit.io/library/advanced-features/static-file-serving" target="_blank" rel="noopener">
Static file serving
&lt;/a>&lt;/li>
&lt;li>更多更多元件：&lt;a href="https://docs.streamlit.io/library/api-reference" target="_blank" rel="noopener">
API reference
&lt;/a>&lt;/li>
&lt;/ul>
&lt;br/>
&lt;p>官方有將 streamlit 可以下的指令、各式元件的寫法濃縮整理成一頁，方便快速查閱：&lt;a href="https://cheat-sheet.streamlit.app/">https://cheat-sheet.streamlit.app/&lt;/a>&lt;/p>
&lt;br/>
&lt;h2 id="部署應用程式">部署應用程式&lt;/h2>
&lt;p>除了將程式在自己的電腦執行，或架在伺服器之外，官方有提供「&lt;a href="https://streamlit.io/cloud" target="_blank" rel="noopener">
Streamlit Community Cloud
&lt;/a>」，可以在上面部署、管理、共享你的 Streamlit 應用程式。你只要將專案上傳自己的 GitHub 存儲庫(公開或私有都可以)，再到 Streamlit Community Cloud 設定連接即可，算是蠻方便的。&lt;/p>
&lt;p>* 關於 Streamlit Community Cloud 官方說明可在這邊查看：&lt;a href="https://docs.streamlit.io/streamlit-community-cloud" target="_blank" rel="noopener">
Welcome to Streamlit Community Cloud
&lt;/a>&lt;/p>
&lt;br/>
&lt;p>完整部署介紹請參考&lt;a href="https://docs.streamlit.io/streamlit-community-cloud/deploy-your-app" target="_blank" rel="noopener">
官方說明
&lt;/a>，只需要四個步驟：&lt;/p>
&lt;ol>
&lt;li>先確認你的資料夾內有程式執行需要的&lt;a href="https://docs.streamlit.io/streamlit-community-cloud/deploy-your-app/app-dependencies" target="_blank" rel="noopener">
依賴套件文件
&lt;/a>：
&lt;ul>
&lt;li>Python 依賴文件 [必要]：&lt;code>requirements.txt&lt;/code>、&lt;code>Pipfile&lt;/code>、&lt;code>environment.yml&lt;/code>、&lt;code>pyproject.toml&lt;/code> 這幾種擇一，指定程式需要哪些 Python 套件。&lt;/li>
&lt;li>apt-get 依賴 [非必要]：需要哪些 apt-get 的依賴套件。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>將專案推到自己的 GitHub (公開或私有都可以)。&lt;/li>
&lt;li>前往 &lt;a href="https://share.streamlit.io/" target="_blank" rel="noopener">
share.streamlit.io
&lt;/a> 工作區，連接你剛剛上傳的 GitHub 存儲庫。&lt;/li>
&lt;li>部署完成！！&lt;/li>
&lt;/ol>
&lt;br/>
&lt;p>推上 GitHub 的專案資料夾內大致會長這樣：&lt;/p>
&lt;pre>&lt;code>your-repository/
├── streamlit_app.py
└── requirements.txt
&lt;/code>&lt;/pre>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/github_repository.jpg" alt="推上 GitHub Repository" data-caption="推上 GitHub Repository" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='850px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:850px;height:;"/>
&lt;figcaption style="text-align: center;">
推上 GitHub Repository
&lt;/figcaption>
&lt;/figure>
&lt;p>前往 &lt;a href="https://share.streamlit.io/" target="_blank" rel="noopener">
share.streamlit.io
&lt;/a> 工作區，連接你剛剛上傳的 GitHub 存儲庫。&lt;/p>
&lt;p>點擊右上角 &amp;quot;New app&amp;quot;&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/new_app.jpg" alt="右上角 &amp;#34;New app&amp;#34;" data-caption="右上角 &amp;#34;New app&amp;#34;" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
右上角 &amp;#34;New app&amp;#34;
&lt;/figcaption>
&lt;/figure>
&lt;p>第一次需要給 Streamlit 擁有讀取 GitHub Repository 的權限：&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/github_permission.jpg" alt="第一次需要給 Streamlit 讀取 GitHub 權限" data-caption="第一次需要給 Streamlit 讀取 GitHub 權限" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
第一次需要給 Streamlit 讀取 GitHub 權限
&lt;/figcaption>
&lt;/figure>
&lt;p>下一步，指定 GitHub Repository、分支、程式檔案名稱，以及是否要自訂網址名稱(你可以為你的應用程式自訂一個獨一無二的名稱)：&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/deploy_setting.jpg" alt="部署設定" data-caption="部署設定" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
部署設定
&lt;/figcaption>
&lt;/figure>
&lt;p>下方還可以打開 &amp;quot;Advanced settings&amp;hellip;&amp;quot;，這邊可以更改 Python 版本、設定環境變數。&lt;br />
我們這個範例不需要編輯這邊。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/advanced_settings.jpg" alt="部署進階設定" data-caption="部署進階設定" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
部署進階設定
&lt;/figcaption>
&lt;/figure>
&lt;p>點擊 &amp;quot;Deploy!&amp;quot;，等個一、兩分鐘安裝。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/deploying.jpg" alt="部署中..." data-caption="部署中..." src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
部署中...
&lt;/figcaption>
&lt;/figure>
&lt;p>部署完成，網址列上顯示的就是你這個應用程式的專屬網址，把它分享給其他人炫耀你努力的成果吧~🎉&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/deploy_completed.jpg" alt="部署完成" data-caption="部署完成" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
部署完成
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;br/>
&lt;p>前往 &lt;a href="https://share.streamlit.io/" target="_blank" rel="noopener">
share.streamlit.io
&lt;/a> 工作區，可以查看你全部的 Streamlit 應用程式，它還提供統計來訪人數的功能。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/your_apps.jpg" alt="share.streamlit.io 工作區" data-caption="share.streamlit.io 工作區" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='850px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:850px;height:;"/>
&lt;figcaption style="text-align: center;">
share.streamlit.io 工作區
&lt;/figcaption>
&lt;/figure>
&lt;p>來看看我 2021 年發布的 &lt;a href="https://it-jia-streamlit-demo-streamlit-app-t4el3t.streamlit.app/" target="_blank" rel="noopener">
Demo
&lt;/a> 範例，共有 1,522 名讀者來訪~ (而且是計算不重複的)&lt;br />
* 這個統計功能是從 2022 年 4 月才開始，所以實際上會再更多。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit_2023/analytics.jpg" alt="統計來訪人數" data-caption="統計來訪人數" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='650px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:650px;height:;"/>
&lt;figcaption style="text-align: center;">
統計來訪人數
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h2 id="完整範例程式碼">完整範例程式碼&lt;/h2>
&lt;p>附上完整範例程式碼：&lt;a href="https://github.com/it-jia/streamlit_2023_demo/blob/main/streamlit_app.py" target="_blank" rel="noopener">
streamlit_app.py
&lt;/a>&lt;/p>
&lt;p>此範例程式碼部署在 Streamlit Cloud (share.streamlit.io) 的 Demo：&lt;/p>
&lt;div class="alert alert-info" role="alert" data-dir="ltr">Streamlit 成果範例：&lt;a href="https://jiatool-demo.streamlit.app/">streamlit_2023_demo&lt;/a>&lt;/div>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>從之前第一次嘗試 Streamlit 到現在過了兩年多，它又陸續新增了不少功能，看起來還有積極再發展。&lt;/p>
&lt;p>經過上方教學實際操作後，會發覺這個套件真的可以很簡單、快速的建立一個顯示資料用的儀表板(Dashboard)，因此特別寫這篇文章來分享給大家~&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://streamlit.io/" target="_blank" rel="noopener">
Streamlit 官方網站
&lt;/a>&lt;br />
&lt;a href="https://docs.streamlit.io/" target="_blank" rel="noopener">
Streamlit 官方文檔
&lt;/a>&lt;/p>
&lt;br/>
&lt;blockquote>
&lt;p>每一個你討厭的現在，&lt;br />
都有一個不夠努力的曾經。&lt;/p>
&lt;p align="right">—— 幾米 (台灣繪本作家)&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/streamlit_2023.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/streamlit_2023_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Python</category><category>Streamlit</category><category>Dashboard</category><category>套件</category><category>分享</category><category>Python套件</category></item><item><title>[Python爬蟲實例] 爬取"Agoda"訂房網站的搜尋住宿結果</title><link>https://blog.jiatool.com/posts/agoda_spider/</link><pubDate>Sat, 08 Jul 2023 21:35:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Wed, 11 Dec 2024 21:35:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/agoda_spider/</guid><description>前言 今天的 Python網路爬蟲實例 系列將來介紹 Agoda 訂房網站該如何搜尋住宿結果，看看它是如何發出請求、解析回傳資料，它 WebAPI 的查詢語言有別於我們之前</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>今天的 &lt;a href="https://blog.jiatool.com/series/Python%e7%b6%b2%e8%b7%af%e7%88%ac%e8%9f%b2%e5%af%a6%e4%be%8b/" target="_blank" rel="noopener">
Python網路爬蟲實例
&lt;/a> 系列將來介紹 Agoda 訂房網站該如何搜尋住宿結果，看看它是如何發出請求、解析回傳資料，它 WebAPI 的查詢語言有別於我們之前遇過的 REST 風格，它是採用比較新的 GraphQL。&lt;/p>
&lt;p>會寫這篇文章，是之前有網友詢問，我稍微試了一下，並將結果記錄下來，因此本篇不會有太詳細的介紹。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/agoda_spider/hostel.jpg" alt="旅館 (來源：Unsplash)" data-caption="旅館 (來源：Unsplash)" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
旅館 (來源：Unsplash)
&lt;/figcaption>
&lt;/figure>
&lt;p>備註：此文僅教育學習，切勿用作商業用途，個人實作皆屬個人行為，本作者不負任何法律責任。&lt;/p>
&lt;h2 id="套件">套件&lt;/h2>
&lt;p>此次 Python 爬蟲主要使用到的套件：&lt;/p>
&lt;ul>
&lt;li>Requests [&lt;a href="https://requests.readthedocs.io/en/master/" target="_blank" rel="noopener">
Doc
&lt;/a>] [&lt;a href="https://github.com/psf/requests" target="_blank" rel="noopener">
GitHub
&lt;/a>]&lt;/li>
&lt;/ul>
&lt;p>安裝&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">pip install requests
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;!--adsense-->
&lt;h2 id="搜尋住宿">搜尋住宿&lt;/h2>
&lt;h3 id="請求路徑與參數">請求路徑與參數&lt;/h3>
&lt;p>我直接在 Agoda 首頁搜尋 &amp;quot;台北市&amp;quot; 的住宿，接下來打開瀏覽器的 &lt;strong>開發人員工具&lt;/strong> (F12 或 Ctrl + Shift + i)並重整網頁。&lt;/p>
&lt;p>切換到 &lt;strong>Network&lt;/strong>(網路) &amp;gt; &lt;strong>Fetch/XHR&lt;/strong> 分頁，會看見一個 /search 的請求，裡面包含我們這次搜尋住宿的結果。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/agoda_spider/search.jpg" alt="開發人員工具 &amp;gt; Network &amp;gt; Fetch/XHR" data-caption="開發人員工具 &amp;gt; Network &amp;gt; Fetch/XHR" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
開發人員工具 &amp;gt; Network &amp;gt; Fetch/XHR
&lt;/figcaption>
&lt;/figure>
&lt;p>切到 &lt;strong>Headers&lt;/strong> 查看請求的方式與參數。&lt;/p>
&lt;p>網址是 &lt;code>https://www.agoda.com/graphql/search&lt;/code>、使用 &lt;code>POST&lt;/code> 方法、需要帶 &lt;code>payload&lt;/code>。&lt;/p>
&lt;p>其實從網址就可以猜的出來，它可能是採用 GraphQL 查詢語言。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/agoda_spider/search_headers.png" alt="&amp;#34;搜尋住宿&amp;#34;請求的方式與參數" data-caption="&amp;#34;搜尋住宿&amp;#34;請求的方式與參數" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;搜尋住宿&amp;#34;請求的方式與參數
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>我將其整理出來，相關參數如下：&lt;/p>
&lt;p>GraphQL 查詢語言會把需要的欄位全部列在 Request Body 的 json 格式字串內，所以它請求的 Request Body 會很~長~一串，我文章中就不全部列出來了，可以直接參考這個檔案(&lt;a href="https://gist.github.com/it-jia/9c10105a4cb6fdbccbf29fa92c183cb2" target="_blank" rel="noopener">
agoda_query.json
&lt;/a>)或自行用瀏覽器的開發人員工具查看。&lt;/p>
&lt;div class="box">&lt;p>Request URL：&lt;code>https://www.agoda.com/graphql/search&lt;/code>&lt;br />
Request Methon：&lt;code>POST&lt;/code>&lt;br />
Request Headers：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;User-Agent&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Content-Type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;application/json&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Ag-Language-Locale&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;zh-tw&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Request Payload：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;operationName&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;citySearch&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;variables&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;CitySearchRequest&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="err">...&lt;/span>&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;ContentSummaryRequest&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="err">...&lt;/span>&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;PricingSummaryRequest&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="err">...&lt;/span>&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;PriceStreamMetaLabRequest&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="err">...&lt;/span>&lt;span class="p">}&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;query&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;query citySearch($CitySearchRequest: CitySearchRequest!, $ContentSummaryRequest: ContentSummaryRequest!, ......&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/div>
&lt;br/>
&lt;p>城市代表 ID (&lt;code>cityId&lt;/code>) 可以從我們查詢時的網址列 (&lt;code>city&lt;/code>) 找到：&lt;br />
&lt;code>https://www.agoda.com/zh-hk/search?city=4951&amp;amp;checkIn=2023-06-19&amp;amp;los=1&amp;amp;rooms=1&amp;amp;...&lt;/code> 裡面的 &lt;code>city=4951&lt;/code>。&lt;/p>
&lt;br/>
&lt;h3 id="回傳資料">回傳資料&lt;/h3>
&lt;p>GraphQL 查詢語言的特點就是，其回傳資料的格式等同於你發出請求時所指定的欄位(也就是我們 agoda_query.json 檔案的內容)。&lt;/p>
&lt;p>住宿搜尋結果會列在 &lt;code>[&amp;quot;data&amp;quot;][&amp;quot;citySearch&amp;quot;][&amp;quot;properties&amp;quot;]&lt;/code> 裡面。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;data&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;citySearch&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;aggregation&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{},&lt;/span>
&lt;span class="nt">&amp;#34;featuredPulseProperties&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[],&lt;/span>
&lt;span class="nt">&amp;#34;properties&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;住宿搜尋結果會列在這裡&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;searchEnrichment&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{},&lt;/span>
&lt;span class="nt">&amp;#34;searchResult&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h3 id="範例程式">範例程式&lt;/h3>
&lt;p>使用 Python 搭配 requests 套件的寫法如下：&lt;/p>
&lt;p>* 因為請求需要夾帶的 JSON 太長，我存在另外一個檔案(&lt;a href="https://gist.github.com/it-jia/9c10105a4cb6fdbccbf29fa92c183cb2" target="_blank" rel="noopener">
agoda_query.json
&lt;/a>)內再讀取進來。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">json&lt;/span>
&lt;span class="c1"># 因為請求需要夾帶的 JSON 太長，我存在另外一個檔案內再讀取進來&lt;/span>
&lt;span class="n">f&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">open&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;agoda_query.json&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">load&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">post&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="s1">&amp;#39;https://www.agoda.com/graphql/search&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;User-Agent&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;Content-Type&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;application/json&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;Ag-Language-Locale&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;zh-tw&amp;#39;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="n">json&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">data&lt;/span>
&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 將回傳結果儲存在 JSON 檔案&lt;/span>
&lt;span class="k">with&lt;/span> &lt;span class="nb">open&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;agoda_result.json&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;w&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">fp&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dump&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">fp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h2 id="延伸練習">延伸練習&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>我們在搜尋住宿時，會給他許多不同的篩選欄位，例如價格、地點、星級、床型、評價得分&amp;hellip;，你知道如何將這些篩選條件加入請求嗎？&lt;br />
(提示：可以觀察 &lt;code>agoda_query.json&lt;/code> 這個檔案內容)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Agoda 網站除了找住宿以外，它還可以搜尋機票，試著自己實際找找看吧。&lt;br />
(提示：它好像有一個 POST 請求 &lt;code>https://www.agoda.com/api/gw/flight/searchunbundled&lt;/code>，不知道是不是)&lt;/p>
&lt;/li>
&lt;/ol>
&lt;br/>
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>Agoda 訂房網站的 WebAPI 是採用比較新的 GraphQL，它可以精確地選擇所需的資料、避免請求過多或過少的資料，有別於我們之前遇過、常見的 REST。&lt;/p>
&lt;p>關於 GraphQL 的介紹與 REST 的差異比較，如果有人想看的話(按讚或留言讓我知道)，之後考慮整理一篇出來。&lt;/p>
&lt;p>之後會繼續陸續寫一些網站的&lt;a href="https://blog.jiatool.com/series/Python%e7%b6%b2%e8%b7%af%e7%88%ac%e8%9f%b2%e5%af%a6%e4%be%8b/" target="_blank" rel="noopener">
Python網路爬蟲實例
&lt;/a>，如果你正好是剛開始想學爬蟲的新手、想知道某網站如何爬取資料、遇到其他問題，也歡迎在底下留言，或追蹤 FB 粉專『&lt;a href="https://www.facebook.com/jiatool" target="_blank" rel="noopener">
IT空間
&lt;/a>』~ 🔔&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;blockquote>
&lt;p>所謂失敗，並非被打倒，而是倒地不起。&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/agoda_spider.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/agoda_spider_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Python</category><category>網路爬蟲</category><category>Python網路爬蟲實例</category></item><item><title>OpenAI ChatGPT API 如何使用？(附上 Python 範例程式)</title><link>https://blog.jiatool.com/posts/chatgpt_api/</link><pubDate>Sat, 18 Mar 2023 21:10:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sun, 19 Mar 2023 14:45:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/chatgpt_api/</guid><description>前言 ChatGPT 是由 OpenAI 所開發的一個基於 GPT-3.5 架構的大型語言模型，自從去年底發表到現在依然話題不斷、人氣超高。而在三月初，OpenAI 公開了 ChatGPT 的 API，也就</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>ChatGPT 是由 OpenAI 所開發的一個基於 GPT-3.5 架構的大型語言模型，自從去年底發表到現在依然話題不斷、人氣超高。而在三月初，OpenAI 公開了 ChatGPT 的 API，也就是 gpt-3.5-turbo 模型的 API，讓我們不再被限制只能透過官方網頁使用，並且提供更多可調整的參數選項。&lt;/p>
&lt;p>這篇文章就是要一起來了解 ChatGPT API，並實際使用 Python 串接 API (當然有 Python 範例程式碼)，帶著大家快速上手。&lt;/p>
&lt;br/>
&lt;p>這兩份官方文件建議可以看看：&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://platform.openai.com/docs/guides/chat" target="_blank" rel="noopener">
OpenAI 官方說明文件
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://platform.openai.com/docs/api-reference/chat" target="_blank" rel="noopener">
OpenAI 官方 API 參考
&lt;/a>&lt;/li>
&lt;/ul>
&lt;br/>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/chatgpt_api/gtpapi.jpg" alt="OpenAI 公開 ChatGPT API" data-caption="OpenAI 公開 ChatGPT API" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
OpenAI 公開 ChatGPT API
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;!--adsense-->
&lt;br/>
&lt;h2 id="api-key-申請">API key 申請&lt;/h2>
&lt;p>進到帳號的 &lt;a href="https://platform.openai.com/account/api-keys" target="_blank" rel="noopener">
API key
&lt;/a> 頁面，登入帳號後，點擊 &amp;ldquo;Create new secret key&amp;rdquo; 來產生 API key，這時候就要把 key 複製並保存下來了，如果忘記的話，再產生一次即可。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/chatgpt_api/apikey.jpg" alt="API key 申請" data-caption="API key 申請" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
API key 申請
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h2 id="使用量與計費方式">使用量與計費方式&lt;/h2>
&lt;p>而帳號實際的總使用量可以到 &lt;a href="https://platform.openai.com/account/usage" target="_blank" rel="noopener">
帳號 Usage
&lt;/a> 頁面查看。&lt;/p>
&lt;p>目前每個帳號會贈送 18 美元的額度讓你試用 (如果你是用同一組手機去開多個帳號，那就不一定了)，並且有使用期限要留意，不要白白浪費了~&lt;br />
如果免費額度用完過到期，就應該要綁信用卡才能使用了。&lt;/p>
&lt;p>每種模型的計費方式可參考 &lt;a href="https://openai.com/pricing" target="_blank" rel="noopener">
官網 Pricing
&lt;/a> 頁面說明。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/chatgpt_api/usage.jpg" alt="帳號實際的總使用量" data-caption="帳號實際的總使用量" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
帳號實際的總使用量
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h2 id="範例程式碼">範例程式碼&lt;/h2>
&lt;p>馬上給各位看看範例程式碼。&lt;/p>
&lt;p>這邊分別使用使用兩種套件來示範，我們之前常用的 requests，與官方提供的 openai 套件。&lt;/p>
&lt;p>Model 使用 ChatGPT 的 &lt;code>gpt-3.5-turbo&lt;/code>，如果之後 GPT-4 的也開放後可以使用 &lt;code>gpt-4&lt;/code>。&lt;br />
目前 OpenAI API 有提供&lt;a href="https://platform.openai.com/docs/models" target="_blank" rel="noopener">
這些 Model
&lt;/a>，裡面有對每一種 Model 做詳細說明。&lt;/p>
&lt;br/>
&lt;h3 id="使用-requests-套件">使用 requests 套件&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="n">API_KEY&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;&amp;lt;YOUR_API_KEY&amp;gt;&amp;#39;&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">post&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="s1">&amp;#39;https://api.openai.com/v1/chat/completions&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;Content-Type&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;application/json&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;Authorization&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;Bearer {API_KEY}&amp;#39;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="n">json&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;model&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;gpt-3.5-turbo&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;messages&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[{&lt;/span>&lt;span class="s2">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;user&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;說句話吧&amp;#34;&lt;/span>&lt;span class="p">}],&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h3 id="使用官方-openai-套件">使用官方 openai 套件&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">openai&lt;/span>
&lt;span class="n">openai&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">api_key&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;&amp;lt;YOUR_API_KEY&amp;gt;&amp;#39;&lt;/span>
&lt;span class="n">completion&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">openai&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ChatCompletion&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">model&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;gpt-3.5-turbo&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">messages&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;user&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;說句話吧&amp;#34;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">completion&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h2 id="參數">參數&lt;/h2>
&lt;p>輸入參數除了上方範例中的 &lt;code>model&lt;/code> 和 &lt;code>messages&lt;/code>，還有以下這些。&lt;/p>
&lt;p>此表格是依照官方 &lt;a href="https://platform.openai.com/docs/api-reference/chat/create" target="_blank" rel="noopener">
API Reference
&lt;/a> 所整理出來的。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>參數名稱&lt;/th>
&lt;th>資料型態&lt;/th>
&lt;th>必填/選填&lt;/th>
&lt;th>預設值&lt;/th>
&lt;th>說明&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>model&lt;/code>&lt;/td>
&lt;td>string&lt;/td>
&lt;td>必填&lt;/td>
&lt;td>-&lt;/td>
&lt;td>要使用的 Model ID。 (&lt;a href="https://platform.openai.com/docs/models/model-endpoint-compatibility" target="_blank" rel="noopener">
可使用的model
&lt;/a>)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>messages&lt;/code>&lt;/td>
&lt;td>array&lt;/td>
&lt;td>必填&lt;/td>
&lt;td>-&lt;/td>
&lt;td>以對話格式生成對話的訊息。 (&lt;a href="https://platform.openai.com/docs/guides/chat/introduction" target="_blank" rel="noopener">
格式參考
&lt;/a>，或以下說明)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>temperature&lt;/code>&lt;/td>
&lt;td>number&lt;/td>
&lt;td>選填&lt;/td>
&lt;td>1&lt;/td>
&lt;td>介於 0 和 2 之間。較高的值(如 0.8)將使輸出更加隨機，而較低的值(如 0.2)將使輸出更加集中和確定。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>top_p&lt;/code>&lt;/td>
&lt;td>number&lt;/td>
&lt;td>選填&lt;/td>
&lt;td>1&lt;/td>
&lt;td>一種替代&lt;code>temperature&lt;/code>的方法(nucleus sampling)。Model 考慮具有 top_p 概率質量的標記的結果。所以 0.1 意味著只考慮構成前 10% 概率質量的標記。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>n&lt;/code>&lt;/td>
&lt;td>integer&lt;/td>
&lt;td>選填&lt;/td>
&lt;td>1&lt;/td>
&lt;td>輸出幾種回覆結果。 (參考以下說明)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>stream&lt;/code>&lt;/td>
&lt;td>boolean&lt;/td>
&lt;td>選填&lt;/td>
&lt;td>false&lt;/td>
&lt;td>開啟 stream 方式傳送，就像 ChatGPT 網頁版那樣會一個一個字跑出來。(&lt;a href="https://github.com/openai/openai-cookbook/blob/main/examples/How_to_stream_completions.ipynb" target="_blank" rel="noopener">
官方範例
&lt;/a>)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>stop&lt;/code>&lt;/td>
&lt;td>string or array&lt;/td>
&lt;td>選填&lt;/td>
&lt;td>null&lt;/td>
&lt;td>指定字串，如果回覆有出現這些字串將會停止輸出。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>max_tokens&lt;/code>&lt;/td>
&lt;td>integer&lt;/td>
&lt;td>選填&lt;/td>
&lt;td>inf&lt;/td>
&lt;td>聊天完成時生成的最大令牌數。如果太小它可能回覆到一半就會斷掉，但每種 Model 都有各自的最大值。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>presence_penalty&lt;/code>&lt;/td>
&lt;td>number&lt;/td>
&lt;td>選填&lt;/td>
&lt;td>0&lt;/td>
&lt;td>-2.0 和 2.0 之間的數字。正值會根據到目前為止是否出現在文本中來懲罰新標記，從而增加 Model 談論新主題的可能性。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>frequency_penalty&lt;/code>&lt;/td>
&lt;td>number&lt;/td>
&lt;td>選填&lt;/td>
&lt;td>0&lt;/td>
&lt;td>-2.0 和 2.0 之間的數字。正值會根據新標記在文本中的現有頻率對其進行懲罰，從而降低 Model 逐字重複同一行的可能性。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>logit_bias&lt;/code>&lt;/td>
&lt;td>map&lt;/td>
&lt;td>選填&lt;/td>
&lt;td>null&lt;/td>
&lt;td>修改指定標記出現在完成中的可能性。&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>user&lt;/code>&lt;/td>
&lt;td>string&lt;/td>
&lt;td>選填&lt;/td>
&lt;td>-&lt;/td>
&lt;td>代表你的用戶的ID，幫助 OpenAI 監控和檢測濫用行為。 (&lt;a href="https://platform.openai.com/docs/guides/safety-best-practices/end-user-ids" target="_blank" rel="noopener">
更多說明
&lt;/a>)&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>* 官方建議不要同時更改 temperature 和 top_p，可以參考&lt;a href="https://platform.openai.com/docs/api-reference/parameter-details" target="_blank" rel="noopener">
這邊的說明
&lt;/a>。&lt;/p>
&lt;p>* 表格內有幾個說明你可能看不懂，因為我也不太懂 XP&lt;/p>
&lt;br/>
&lt;p>&lt;code>messages&lt;/code> 是個陣列的格式，放著你們之間的對話。&lt;br />
裡面的 &lt;code>role&lt;/code> 欄位可以放三種身分：&amp;ldquo;system&amp;rdquo;、&amp;ldquo;user&amp;rdquo;、&amp;ldquo;assistant&amp;rdquo;。&lt;/p>
&lt;p>對話可以先有一則 &amp;ldquo;system&amp;rdquo;，對 Model 先做出指示，例如 &amp;ldquo;你是一隻貓&amp;rdquo; (？，不過官方說 gpt-3.5-turbo 對 &amp;ldquo;system&amp;rdquo; 消息的關注度不高，因此重要的說明建議還是放在 &amp;ldquo;user&amp;rdquo; 的消息比較好。&lt;br />
&amp;ldquo;user&amp;rdquo; 是我們使用者的發問；&amp;ldquo;assistant&amp;rdquo; 則是 Model 的回話。&lt;/p>
&lt;p>如果你想要讓對話有上下文關係(要讓 Model 記得之前講過的話)，要把全部對話紀錄都在傳給它，然後這些都算進 token(使用量) 裡&amp;hellip;，像是底下這樣。&lt;/p>
&lt;p>第一次問它：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Json" data-lang="Json">&lt;span class="s2">&amp;#34;messages&amp;#34;&lt;/span>&lt;span class="err">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>&lt;span class="nt">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;user&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nt">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;王建民是誰&amp;#34;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>它回覆：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Json" data-lang="Json">&lt;span class="s2">&amp;#34;usage&amp;#34;&lt;/span>&lt;span class="err">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;prompt_tokens&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">14&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;completion_tokens&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">217&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;total_tokens&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">231&lt;/span>
&lt;span class="p">}&lt;/span>&lt;span class="err">,&lt;/span>
&lt;span class="s2">&amp;#34;choices&amp;#34;&lt;/span>&lt;span class="err">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;message&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;assistant&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;\n\n王建民是一位台灣籍棒球運動員，曾效力於美國職棒大聯盟紐約洋基隊、匹茲堡海盜隊、倫敦青年隊、堪薩斯城皇家隊等隊伍，擅長投球，被譽為是台灣最優秀的投手之一。他在職業生涯期間獲得多項獎項，包括台灣大賽MVP、亞洲聯盟MVP、美國聯盟先發投手等。他在2015年正式宣布退役，現在是一位棒球分析師和教練。&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>想再繼續深入詢問，第二次問它，就要把剛剛我問的跟他回的都放進去：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Json" data-lang="Json">&lt;span class="err">&amp;#39;messages&amp;#39;:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>&lt;span class="nt">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;user&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nt">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;王建民是誰&amp;#34;&lt;/span>&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>&lt;span class="nt">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;assistant&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nt">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;\n\n王建民是一位台灣籍棒球運動員，曾效力於美國職棒大聯盟紐約洋基隊、匹茲堡海盜隊、倫敦青年隊、堪薩斯城皇家隊等隊伍，擅長投球，被譽為是台灣最優秀的投手之一。他在職業生涯期間獲得多項獎項，包括台灣大賽MVP、亞洲聯盟MVP、美國聯盟先發投手等。他在2015年正式宣布退役，現在是一位棒球分析師和教練。&amp;#34;&lt;/span>&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>&lt;span class="nt">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;user&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nt">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;他在美國大聯盟最多一年曾經拿過幾勝&amp;#34;&lt;/span>&lt;span class="p">},&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>它回覆：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Json" data-lang="Json">&lt;span class="s2">&amp;#34;usage&amp;#34;&lt;/span>&lt;span class="err">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;prompt_tokens&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">268&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;completion_tokens&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">63&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;total_tokens&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">331&lt;/span>
&lt;span class="p">}&lt;/span>&lt;span class="err">,&lt;/span>
&lt;span class="s2">&amp;#34;choices&amp;#34;&lt;/span>&lt;span class="err">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;message&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;assistant&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;王建民在美國大聯盟生涯中最多一年的勝場數為19勝，是在2008年效力於倫敦青年隊時所取得的成績。&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>可以感受到 total_tokens 的使用量了嗎？&lt;br />
如果想讓它記得以前講過的話，每次請求所消耗的 token 是要繼續往上疊的，也是蠻恐怖的 XD&lt;/p>
&lt;p>以上內容可以參考&lt;a href="https://platform.openai.com/docs/guides/chat/introduction" target="_blank" rel="noopener">
官方說明
&lt;/a>。&lt;/p>
&lt;br/>
&lt;p>參數 &lt;code>n&lt;/code> 是代表你想要它給出幾種回覆，例如 &lt;code>n=3&lt;/code> 會產生如下三則訊息回覆：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Json" data-lang="Json">&lt;span class="s2">&amp;#34;choices&amp;#34;&lt;/span>&lt;span class="err">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;message&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;assistant&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;\n\n你好，有什麼我可以幫助您的？&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;finish_reason&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;stop&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;index&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;message&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;assistant&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;\n\n您好，有什麼我能幫助您的嗎？&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;finish_reason&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;stop&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;index&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;message&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;assistant&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;\n\n您好，有什麼我可以為您做的嗎？&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;finish_reason&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;stop&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;index&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">2&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h2 id="回覆內容">回覆內容&lt;/h2>
&lt;p>依照上方的範例程式，他回傳的格式與內容會類似這樣：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Json" data-lang="Json">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;chatcmpl-6v4faabcd9gXfUerJvBf123Co&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;object&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;chat.completion&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;created&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1679060660&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;model&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;gpt-3.5-turbo-0301&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;usage&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;prompt_tokens&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">14&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;completion_tokens&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">24&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;total_tokens&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">38&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;choices&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;message&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;role&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;assistant&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;content&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;\n\n你好，有什麼我可以為你效勞的嗎？&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;finish_reason&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;stop&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;index&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;code>usage&lt;/code> 欄位顯示你本次消耗的 token 數量。&lt;/p>
&lt;ul>
&lt;li>&lt;code>prompt_tokens&lt;/code>：你問他(輸入)所消耗的 token。&lt;/li>
&lt;li>&lt;code>completion_tokens&lt;/code>：它回覆(輸出)所消耗的 token。&lt;/li>
&lt;li>&lt;code>total_tokens&lt;/code>：本次請求總共消耗多少 token，也就是 &lt;code>prompt_tokens&lt;/code> 加 &lt;code>completion_tokens&lt;/code>。&lt;/li>
&lt;/ul>
&lt;p>如果想知道一句話代表幾個 token，可以使用官方提供的 Python 套件 — tiktoken：&lt;a href="https://github.com/openai/tiktoken">https://github.com/openai/tiktoken&lt;/a>&lt;br />
也有計算 token 相關的&lt;a href="https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb" target="_blank" rel="noopener">
使用說明
&lt;/a>。&lt;/p>
&lt;p>本來想說可以使用官方的 &lt;a href="https://platform.openai.com/tokenizer" target="_blank" rel="noopener">
Tokenizer 網頁
&lt;/a>來計算，但它是 GPT-3 Model 的，官方有說轉換 token 的計算方式可能因不同 Model 而異，因此我實際使用其實跟 gpt-3.5-turbo 出來的結果有落差。&lt;/p>
&lt;p>帳號實際的總使用量可以到 &lt;a href="https://platform.openai.com/account/usage" target="_blank" rel="noopener">
帳號 Usage
&lt;/a> 頁面查看。&lt;/p>
&lt;p>&lt;em>* 你會發現中文消耗的 token 比英文還多很多😭&lt;/em>&lt;/p>
&lt;br/>
&lt;p>&lt;code>choices&lt;/code> 內就是主要我們想知道的部分 — ChatGPT 的回覆。&lt;/p>
&lt;ul>
&lt;li>&lt;code>message&lt;/code> &amp;gt; &lt;code>content&lt;/code>：回覆的內容。&lt;/li>
&lt;li>&lt;code>index&lt;/code>：代表第幾種回覆。(如果輸入參數有設定 &lt;code>n&lt;/code> 的話)&lt;/li>
&lt;li>&lt;code>finish_reason&lt;/code>：代表此次回覆結束的原因(狀態)，可能會有以下四種值：
&lt;ul>
&lt;li>&lt;code>stop&lt;/code>：完整的輸出。&lt;/li>
&lt;li>&lt;code>length&lt;/code>：由於 max_tokens 參數或 token 限制，導致輸出不完整。&lt;/li>
&lt;li>&lt;code>content_filter&lt;/code>：由於內容過濾器中的標誌而省略了內容。&lt;/li>
&lt;li>&lt;code>null&lt;/code>：API 響應仍在進行中或未完成。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;br/>
&lt;h2 id="playground-遊樂場">Playground 遊樂場&lt;/h2>
&lt;p>OpenAI 還有提供 Playground 遊樂場，可以在上面測試不同的模型、調整不同的參數，觀察其結果，方便我們去快速了解。&lt;/p>
&lt;p>Playground 遊樂場：&lt;a href="https://platform.openai.com/playground">https://platform.openai.com/playground&lt;/a>&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/chatgpt_api/playground.jpg" alt="Playground 遊樂場" data-caption="Playground 遊樂場" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='850px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:850px;height:;"/>
&lt;figcaption style="text-align: center;">
Playground 遊樂場
&lt;/figcaption>
&lt;/figure>
&lt;p>對了，使用 Playground 也是會消耗你自己的 token，這點要稍微注意一下，不要以為是 ChatGPT 網頁而玩過頭了🤣&lt;/p>
&lt;br/>
&lt;h2 id="其他說明">其他說明&lt;/h2>
&lt;p>串接 OpenAI API 發出請求可能會收到錯誤，而完整詳細的錯誤代碼說明與進一步的解決辦法，可以參考這邊官方的文章：&lt;a href="https://platform.openai.com/docs/guides/error-codes">https://platform.openai.com/docs/guides/error-codes&lt;/a>&lt;/p>
&lt;p>OpenAI API 在使用上還有一些速率限制，如果使用會比較大量的朋友可以過去了解一下：&lt;a href="https://platform.openai.com/docs/guides/rate-limits/overview">https://platform.openai.com/docs/guides/rate-limits/overview&lt;/a>&lt;/p>
&lt;br/>
&lt;!--adsense-->
&lt;br/>
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>使用 OpenAI API 上非常簡單，只是有些小地方要注意一下。&lt;br />
在看完以上介紹，趕快實際動手做，看看有沒有什麼 idea 可以進一步放大 ChatGPT 的用途~&lt;/p>
&lt;br/>
&lt;p>歡迎追蹤『&lt;a href="https://www.facebook.com/jiatool" target="_blank" rel="noopener">
IT空間
&lt;/a>』FB 粉專，取得最新發文通知🔔&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://platform.openai.com/docs/guides/chat" target="_blank" rel="noopener">
OpenAI 官方說明文件
&lt;/a>&lt;br />
&lt;a href="https://platform.openai.com/docs/api-reference/chat" target="_blank" rel="noopener">
OpenAI 官方 API 參考
&lt;/a>&lt;br />
&lt;a href="https://platform.openai.com/account/usage" target="_blank" rel="noopener">
OpenAI 帳號後台
&lt;/a>&lt;br />
&lt;a href="https://platform.openai.com/docs/models" target="_blank" rel="noopener">
OpenAI 各種 Model 說明
&lt;/a>&lt;br />
&lt;a href="https://openai.com/pricing" target="_blank" rel="noopener">
OpenAI 各種 Model 價格
&lt;/a>&lt;br />
&lt;a href="https://platform.openai.com/playground" target="_blank" rel="noopener">
OpenAI Playground 遊樂場
&lt;/a>&lt;br />
&lt;a href="https://platform.openai.com/docs/guides/error-codes" target="_blank" rel="noopener">
OpenAI API 錯誤代碼
&lt;/a>&lt;br />
&lt;a href="https://platform.openai.com/docs/guides/rate-limits/overview" target="_blank" rel="noopener">
OpenAI API 速率限制
&lt;/a>&lt;/p>
&lt;br/>
&lt;blockquote>
&lt;p>別讓沒有夢想的人摧毀你的夢想。&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/chatgpt_api.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/chatgpt_api_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>OpenAI</category><category>LLM</category><category>AI</category><category>人工智慧</category><category>API</category><category>Python</category><category>分享</category></item><item><title>Heroku 的替代方案？ Fly.io 平台 — Python Flask 實際範例</title><link>https://blog.jiatool.com/posts/flyio_python/</link><pubDate>Sat, 03 Sep 2022 20:50:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sat, 03 Sep 2022 20:50:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/flyio_python/</guid><description>前言 上禮拜著名的佈署平台神器 Heroku 公告說將在 11 月 28 日停止免費方案，之後不付錢不給用了 QAQ，包括旗下的 Heroku Dynos、Heroku Postgres</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>上禮拜著名的佈署平台神器 Heroku 公告說將在 11 月 28 日停止免費方案，之後不付錢不給用了 QAQ，包括旗下的 Heroku Dynos、Heroku Postgres、Heroku Data for Redis 等服務的免費版本。&lt;br />
(&lt;a href="https://www.ithome.com.tw/news/152729" target="_blank" rel="noopener">
平臺即服務Heroku將在今年終止免費服務 | iThome
&lt;/a>)&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/flyio_python/heroku_announcement.png" alt="Heroku 公告" data-caption="Heroku 公告" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='950px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:950px;height:;"/>
&lt;figcaption style="text-align: center;">
Heroku 公告
&lt;/figcaption>
&lt;/figure>
&lt;p>所以看到有網友推薦 &lt;a href="https://fly.io/" target="_blank" rel="noopener">
Fly.io
&lt;/a>，那我就來試用看看並記錄過程吧，也順便給需要的網友參考~&lt;/p>
&lt;p>* 以下流程及範例程式參考&lt;a href="https://fly.io/docs/getting-started/python/" target="_blank" rel="noopener">
官方文檔
&lt;/a>。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/flyio_python/flyio.jpg" alt="Fly.io 官網" data-caption="Fly.io 官網" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='750px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:750px;height:;"/>
&lt;figcaption style="text-align: center;">
Fly.io 官網
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="費用">費用&lt;/h2>
&lt;p>既然要使用，那當然要先了解一下此平台的&lt;a href="https://fly.io/docs/about/pricing/" target="_blank" rel="noopener">
收費機制
&lt;/a>，免費版提供：&lt;/p>
&lt;ul>
&lt;li>最多 3 個 shared-cpu-1x 256MB VM (虛擬機)&lt;/li>
&lt;li>3GB 持久卷(volume)存儲&lt;/li>
&lt;li>160GB 出站數據傳輸量&lt;/li>
&lt;/ul>
&lt;p>* 迷之音：奇怪？我記得上禮拜看的時候，他應該還有限制每月的小時數，不知道是我記錯了，還是他們想透過更多免費額度來吸引 Heroku 那邊來的使用者。&lt;/p>
&lt;br/>
&lt;h2 id="部署步驟">部署步驟&lt;/h2>
&lt;h3 id="準備專案">準備專案&lt;/h3>
&lt;p>我們直接下載官方在GitHub提供的範例&lt;a href="https://github.com/fly-apps/python-hellofly-flask" target="_blank" rel="noopener">
範例專案
&lt;/a>下來，我將資料夾改名(fly_flask)方便我自己區分。&lt;/p>
&lt;p>主要會需要以下四個檔案(剩下的非必要)：&lt;/p>
&lt;pre>&lt;code>fly_flask
├─ templates
│ └─ hello.html
├─ hellofly.py
├─ Procfile
└─ requirements.txt
&lt;/code>&lt;/pre>&lt;br/>
&lt;p>首先 hellofly.py 是我們 flask 主要的入口 (這個簡單的範例也只有這支XD)。&lt;/p>
&lt;p>而當你網址輸入根目錄(&lt;code>/&lt;/code>)或後面隨便帶字串(&lt;code>/&amp;lt;name&amp;gt;&lt;/code>)，它會進到 &lt;code>hello&lt;/code> 這個函式，並渲染 hello.html 這個網頁(檔案位於 templates &amp;gt; hello.html)。&lt;/p>
&lt;br/>
&lt;p>我們先在本機實際運行這個應用程式看看。&lt;br />
(非必要的步驟，但可以先確保整個專案是可以運作的)&lt;/p>
&lt;p>首先要安裝相關套件，在此資料夾打開命令提示字元 CMD，&lt;br />
我還有搭配 pipenv 虛擬環境&amp;amp;套件管理工具，所以指令有些不同：&lt;/p>
&lt;p>創建一個虛擬環境&lt;br />
&lt;code>pipenv --python 3&lt;/code>&lt;/p>
&lt;p>安裝 requirements.txt 裡面列出來的套件&lt;br />
&lt;code>pipenv install&lt;/code>&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/flyio_python/cmd_install_package.jpg" alt="Python虛擬環境建置&amp;amp;安裝套件" data-caption="Python虛擬環境建置&amp;amp;安裝套件" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
Python虛擬環境建置&amp;amp;安裝套件
&lt;/figcaption>
&lt;/figure>
&lt;p>其實主要就是 Flask 與 gunicorn 兩個套件。&lt;br />
gunicorn 是用來在正式環境運行 Flask 之用，它是個 WSGI(Web Server Gateway Interface) HTTP Server，因為 Flask 內建的只適合開發測試用，看看再下一張執行它跳出的紅字就在提醒你了。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/flyio_python/cmd_package.png" alt="查看已安裝套件" data-caption="查看已安裝套件" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='650px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:650px;height:;"/>
&lt;figcaption style="text-align: center;">
查看已安裝套件
&lt;/figcaption>
&lt;/figure>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/flyio_python/cmd_run_flask.png" alt="執行 Flask" data-caption="執行 Flask" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
執行 Flask
&lt;/figcaption>
&lt;/figure>
&lt;p>試著在瀏覽器的網址列輸入&lt;br />
&lt;code>http://127.0.0.1:5000&lt;/code>&lt;br />
和&lt;br />
&lt;code>http://127.0.0.1:5000/&amp;lt;隨便你打&amp;gt;&lt;/code>&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/flyio_python/confirm_run_result.png" alt="在瀏覽器確認執行結果" data-caption="在瀏覽器確認執行結果" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
在瀏覽器確認執行結果
&lt;/figcaption>
&lt;/figure>
&lt;p>OK，看來很正常，沒問題。&lt;/p>
&lt;figure >
&lt;img data-src="https://memeprod.ap-south-1.linodeobjects.com/user-template/276a87d67dc92c2663cb337a160fd60d.png" alt="來源：Meme 梗圖倉庫" data-caption="來源：Meme 梗圖倉庫" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='450px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:450px;height:;"/>
&lt;figcaption style="text-align: center;">
來源：Meme 梗圖倉庫
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h3 id="專案設定">專案設定&lt;/h3>
&lt;p>來到重要的一步，要先設置一些文件，告訴 Fly 我們的應用程式開如何運行及相關設定。&lt;/p>
&lt;br/>
&lt;p>當然，第一步還要要到 &lt;a href="https://fly.io/app/sign-in" target="_blank" rel="noopener">
Fly.io
&lt;/a> 網站註冊一組帳號，完成後會看到這個畫面。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/flyio_python/fly_background.jpg" alt="Fly.io 登入後頁面" data-caption="Fly.io 登入後頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
Fly.io 登入後頁面
&lt;/figcaption>
&lt;/figure>
&lt;p>接下來，依照你的作業系統&lt;a href="https://fly.io/docs/getting-started/installing-flyctl/" target="_blank" rel="noopener">
安裝 flyctl
&lt;/a>，這個工具就跟 Heroku 裡的 Heroku CLI 是同樣的概念。&lt;/p>
&lt;p>以 Windows 為例，在 Powershell 內輸入 &lt;code>iwr https://fly.io/install.ps1 -useb | iex&lt;/code> 來安裝 flyctl。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/flyio_python/powershell_install_flyctl.png" alt="Windows 安裝 flyctl" data-caption="Windows 安裝 flyctl" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
Windows 安裝 flyctl
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>每個應用程式(APP)都需要一個 fly.toml 檔案來告訴 Fly 系統如何部署它。&lt;/p>
&lt;p>可以使用 &lt;code>flyctl launch&lt;/code> 指令來自動生成。&lt;br />
(如果你剛剛才安裝 flyctl，那命令提示字元 CMD 可能要重開它才會生效)&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/flyio_python/cmd_flyctl_login.png" alt="flyctl 登入" data-caption="flyctl 登入" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
flyctl 登入
&lt;/figcaption>
&lt;/figure>
&lt;p>啊，第一次要先登入，輸入 &lt;code>flyctl auth login&lt;/code> 來自動打開網頁登入。&lt;br />
登入完成後再次輸入 &lt;code>flyctl launch&lt;/code>。&lt;/p>
&lt;br/>
&lt;p>喔喔喔~它會自動辨識我們使用 Python 創建應用程式，但我們已經有範例的 Procfile 檔案，這邊輸入 &lt;code>N&lt;/code> 跳過即可。&lt;/p>
&lt;p>輸入名稱後(名稱只能包含數字、小寫字母和破折號)，接下來它會讓你選擇看要架在哪個地區的伺服器上。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/flyio_python/cmd_flyctl_launch1.png" alt="flyctl launch" data-caption="flyctl launch" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='550px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:550px;height:;"/>
&lt;figcaption style="text-align: center;">
flyctl launch
&lt;/figcaption>
&lt;/figure>
&lt;p>這是官網展示的伺服器分布，看來離我們最近的就是東京或香港了。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/flyio_python/server_city.png" alt="Fly 伺服器分布城市" data-caption="Fly 伺服器分布城市" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
Fly 伺服器分布城市
&lt;/figcaption>
&lt;/figure>
&lt;p>然後我們這個專案不需要資料庫。&lt;br />
完成~&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/flyio_python/cmd_flyctl_launch2.png" alt="flyctl launch" data-caption="flyctl launch" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
flyctl launch
&lt;/figcaption>
&lt;/figure>
&lt;p>它就會自動產生 &lt;code>fly.toml&lt;/code> 檔案，內容我們沒有特別需求就不用去改它。&lt;/p>
&lt;br/>
&lt;p>另外，說明一下 &lt;code>Procfile&lt;/code> 檔案用途，它是說明如何啟動我們的應用程式：&lt;/p>
&lt;pre>&lt;code>web: gunicorn hellofly:app
&lt;/code>&lt;/pre>&lt;p>前面說過，我們使用 gunicorn 這個 WSGI HTTP Server 來運行，後面的 hellofly 就是我們 Flask 的進入點 hellofly.py 的檔名。&lt;/p>
&lt;br/>
&lt;h3 id="專案佈署">專案佈署&lt;/h3>
&lt;p>接下來就是重頭戲 — 要將我們的應用程式佈署到 Fly.io 平台了。&lt;/p>
&lt;br/>
&lt;p>在命令提示字元 CMD 輸入指令：&lt;br />
&lt;code>flyctl deploy&lt;/code>&lt;/p>
&lt;p>等它跑一連串的東西&amp;hellip;&amp;hellip;&lt;br />
有興趣也可以觀察它做了哪些步驟。&lt;/p>
&lt;p>結束後，輸入指令來看看應用程式部屬的狀態：&lt;br />
&lt;code>flyctl status&lt;/code>&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/flyio_python/cmd_flyctl_status.png" alt="flyctl deploy 完成後執行 flyctl status" data-caption="flyctl deploy 完成後執行 flyctl status" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
flyctl deploy 完成後執行 flyctl status
&lt;/figcaption>
&lt;/figure>
&lt;p>在 Hostname 那行顯示了我這個應用程式的網址(&lt;code>fly-flask.fly.dev&lt;/code>)，或者輸入 &lt;code>flyctl open&lt;/code> 也可自動從瀏覽器中打開。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/flyio_python/flyctl_open.png" alt="來看看部屬是否有成功吧" data-caption="來看看部屬是否有成功吧" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='450px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:450px;height:;"/>
&lt;figcaption style="text-align: center;">
來看看部屬是否有成功吧
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>如果要查看 IP 可以使用：&lt;code>flyctl ips list&lt;/code>&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/flyio_python/cmd_flyctl_ips_list.png" alt="查看 IP (flyctl ips list)" data-caption="查看 IP (flyctl ips list)" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
查看 IP (flyctl ips list)
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h2 id="dashboard-頁面">Dashboard 頁面&lt;/h2>
&lt;p>在 Fly.io 平台後台有 Dashboard 頁面，可以依據每個 App 去看更詳細的資訊、統計、設定等等。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/flyio_python/fly_dashboard.jpg" alt="Dashboard 頁面" data-caption="Dashboard 頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
Dashboard 頁面
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h2 id="其他程式語言">其他程式語言&lt;/h2>
&lt;p>除了上述 Python 範例外，&lt;a href="https://fly.io/docs/getting-started/" target="_blank" rel="noopener">
官方文件
&lt;/a> 還提供更多不同程式語言的文章，目前看到的有 Crystal、Deno、Elixir、Go、Node、Laravel、Rails、Redwood、Remix、NuxtJS、NextJS、Ruby、靜態網站。&lt;/p>
&lt;p>甚至也可以使用 Dockerfile 部署在 Docker，所以照理來講它應該可以運行大部分的程式。&lt;/p>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>實際操作過一遍後，也會發現其實也蠻容易的。&lt;/p>
&lt;p>如果你想像 Heroku 一樣，程式碼推送到 GitHub 後自動佈署到 Fly.io，則可以參考這篇官方文章：&lt;a href="https://fly.io/docs/app-guides/continuous-deployment-with-github-actions/" target="_blank" rel="noopener">
Continuous Deployment with Fly and GitHub Actions
&lt;/a>&lt;/p>
&lt;p>之後如果有資料要儲存，可以起個 &lt;a href="https://fly.io/docs/reference/postgres/" target="_blank" rel="noopener">
Postgres
&lt;/a>、&lt;a href="https://fly.io/docs/app-guides/mysql-on-fly/" target="_blank" rel="noopener">
MySQL
&lt;/a>、&lt;a href="https://fly.io/docs/getting-started/edgedb/" target="_blank" rel="noopener">
EdgeDB
&lt;/a> 資料庫(DB)，這幾個官方都有寫詳細的文件說明。&lt;/p>
&lt;br/>
&lt;p>題外話&lt;br />
Fly.io 並不是使用 Docker 去運行 container 容器，而是使用 Firecracker micro-VMs 開源的虛擬化技術，說是 Docker 的隔離性還不太夠，這方面我就不太了解，有興趣的網友可以閱讀官方說明：&lt;a href="https://fly.io/blog/docker-without-docker/" target="_blank" rel="noopener">
Docker Without Docker
&lt;/a>&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://fly.io/" target="_blank" rel="noopener">
Fly.io 官方網站
&lt;/a>&lt;br />
&lt;a href="https://fly.io/docs/" target="_blank" rel="noopener">
Fly.io 官方文件
&lt;/a>&lt;br />
&lt;a href="https://www.youtube.com/watch?v=CedAzHw1k5I" target="_blank" rel="noopener">
Fly.io 官方教學影片—Tutorial: Deploy a non-web Python application to Fly.io
&lt;/a>&lt;/p>
&lt;br/>
&lt;blockquote>
&lt;p>珍惜今天，珍惜現在，誰知道明天和意外，哪一個先來。&lt;/p>
&lt;p align="right">—— 《螢火蟲之墓》&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/flyio_python.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/flyio_python_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Python</category><category>Flask</category><category>分享</category></item><item><title>「TDX 運輸資料流通服務平台」含 Python 範例程式，PTX 平台的升級版~</title><link>https://blog.jiatool.com/posts/tdx_python/</link><pubDate>Sun, 19 Jun 2022 21:25:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sat, 31 Dec 2022 21:00:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/tdx_python/</guid><description>前言 在之前文章介紹 PTX 公共運輸整合資訊流通服務平台 ，它整合多項公共運輸的資料服務 API，供我們串接取得相關數據。 「PTX 公共運輸資訊平台」AP</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>在之前文章介紹 &lt;a href="https://ptx.transportdata.tw/PTX/" target="_blank" rel="noopener">
PTX 公共運輸整合資訊流通服務平台
&lt;/a>，它整合多項公共運輸的資料服務 API，供我們串接取得相關數據。&lt;/p>
&lt;ol>
&lt;li>&lt;a href="https://blog.jiatool.com/posts/ptx_intro" target="_blank" rel="noopener">
「PTX 公共運輸資訊平台」API 介紹 (含 Odata 說明)
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://blog.jiatool.com/posts/ptx_python" target="_blank" rel="noopener">
「PTX 公共運輸資訊平台」Python 範例
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://blog.jiatool.com/posts/ptx_google_apps_script" target="_blank" rel="noopener">
「PTX 公共運輸資訊平台」Google Apps Script 範例
&lt;/a>&lt;/li>
&lt;/ol>
&lt;br/>
&lt;p>但經網友提醒，才發現 PTX 竟然只服務到今年(2022年)底，之後會改以「TDX 運輸資訊整合流通服務平台」代替，因此本篇文章將帶大家快速了解一下 TDX 平台，以及實際使用 Python 來串接，取得相關數據資料。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/tdx_python/ptx_close.jpg" alt="PTX 平台關閉" data-caption="PTX 平台關閉" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
PTX 平台關閉
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>後來我有寫一篇 &lt;a href="%28/posts/tdx_google_apps_script%29" target="_blank" rel="noopener">
Google Apps Script 範例程式
&lt;/a> 可以參考哦~&lt;/p>
&lt;br/>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/tdx_python/tdx_home.jpg" alt="TDX 運輸資訊整合流通服務平台" data-caption="TDX 運輸資訊整合流通服務平台" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
TDX 運輸資訊整合流通服務平台
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="tdx-平台說明">TDX 平台說明&lt;/h2>
&lt;p>按照官網的說法，TDX 整合交通部運輸數據五大平台(PTX、Traffic、GIS-T、TICP、LINK)，並使用全新的認證授權方式管控資源存取權限，提供單一服務查詢與介接入口。短時間內五大平台與 TDX 平台將持續並行運作，但未來會以 TDX 為主要的數據流通平台。&lt;br />
(參考：&lt;a href="https://tdx.transportdata.tw/about/faq" target="_blank" rel="noopener">
TDX 平台常見問題
&lt;/a>)&lt;/p>
&lt;figure >
&lt;img data-src="https://tdx.transportdata.tw/backend/images/Uploads/4c57b4tdxapi2.PNG" alt="TDX 整合五大平台 (圖片來源：TDX官網)" data-caption="TDX 整合五大平台 (圖片來源：TDX官網)" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='750px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:750px;height:;"/>
&lt;figcaption style="text-align: center;">
TDX 整合五大平台 (圖片來源：TDX官網)
&lt;/figcaption>
&lt;/figure>
&lt;p>實際使用其實「TDX 運輸資訊整合流通服務平台」服務及概念是跟「PTX 公共運輸整合資訊流通服務平台」差不多的，只是相較於 PTX 平台，TDX 平台又多了許多種類的資料，像是 &amp;quot;即時路況&amp;quot;、&amp;quot;停車資訊&amp;quot;、&amp;quot;GIS圖資&amp;quot;、&amp;quot;道路編碼&amp;quot; 等等也把它整合進來。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/tdx_python/tdx_service_scope.png" alt="TDX 平台服務範疇" data-caption="TDX 平台服務範疇" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
TDX 平台服務範疇
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>TDX 平台也有個&lt;a href="https://tdx.transportdata.tw/data-service/basic" target="_blank" rel="noopener">
詳細各項服務查詢頁面
&lt;/a>，可依照 &amp;quot;服務類型&amp;quot;、&amp;quot;資料主題&amp;quot;、&amp;quot;領域類型&amp;quot;、&amp;quot;資料類型&amp;quot; 來做篩選。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/tdx_python/tdx_service.jpg" alt="TDX 各項服務查詢" data-caption="TDX 各項服務查詢" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
TDX 各項服務查詢
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h2 id="註冊會員--取得api金鑰">註冊會員 &amp;amp; 取得API金鑰&lt;/h2>
&lt;p>同樣為了系統資源使用之公平性與資通訊安全考量，要先註冊會員來取得 API 金鑰(&lt;a href="https://tdx.transportdata.tw/register" target="_blank" rel="noopener">
TDX 註冊頁面
&lt;/a>)，但不知道是不是因為平台還在試營運階段的關係，審核完成並沒有寄 Email 通知，是我主動登入平台才發覺已審核通過&amp;hellip;&amp;hellip;&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/tdx_python/signup_account.png" alt="註冊 TDX 平台會員" data-caption="註冊 TDX 平台會員" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='850px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:850px;height:;"/>
&lt;figcaption style="text-align: center;">
註冊 TDX 平台會員
&lt;/figcaption>
&lt;/figure>
&lt;p>登入 TDX 平台後，前往 會員中心 &amp;gt; (左邊) &amp;gt; 資料服務 &amp;gt; API金鑰 頁面，對 預設的API Key (或建立新的金鑰) 點擊 &amp;quot;編輯&amp;quot;，即可查看 &amp;quot;Client Id&amp;quot; 和 &amp;quot;Client Secret&amp;quot;，這兩組字串先記錄下來，之後 call API 時需要帶上。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/tdx_python/tdx_api_key.png" alt="API金鑰 頁面" data-caption="API金鑰 頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
API金鑰 頁面
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>API 呼叫次數限制：&lt;/p>
&lt;ul>
&lt;li>使用 API 金鑰呼叫，每個呼叫來源端 IP 呼叫次數限制為 50 次/秒 (無每日上限)。&lt;/li>
&lt;li>不使用 API 金鑰呼叫，則僅能透過瀏覽器呼叫 API，且每個呼叫來源端 IP 的上限為每日 50 次。&lt;/li>
&lt;/ul>
&lt;br/>
&lt;p>有關 API 金鑰服務使用流程說明，請參考&lt;a href="https://tdx.transportdata.tw/about/service" target="_blank" rel="noopener">
官方說明
&lt;/a>。&lt;/p>
&lt;br/>
&lt;h2 id="swagger-工具">Swagger 工具&lt;/h2>
&lt;p>從上方導航欄 開發指引 &amp;gt; API說明，前往 TDX 平台的 &lt;a href="https://tdx.transportdata.tw/api-service/swagger" target="_blank" rel="noopener">
Swagger 工具
&lt;/a>，能查看有提供哪些 API，與各自的請求參數與回傳欄位說明。&lt;br />
詳細使用說明可以查看之前我寫的 &lt;a href="https://blog.jiatool.com/posts/ptx_intro" target="_blank" rel="noopener">
PTX 介紹 (含 Odata 說明)
&lt;/a> 文章。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/tdx_python/tdx_api_swagger.jpg" alt="TDX 平台 Swagger 工具" data-caption="TDX 平台 Swagger 工具" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
TDX 平台 Swagger 工具
&lt;/figcaption>
&lt;/figure>
&lt;p>右方有 Authorize 按鈕，填入 &amp;quot;Client Id&amp;quot; 與 &amp;quot;Client Secret&amp;quot; 驗證，即可使用你的 API 金鑰來呼叫。不使用 API 金鑰呼叫，有每日 50 次的上限。&lt;/p>
&lt;br/>
&lt;h2 id="api-認證授權機制">API 認證授權機制&lt;/h2>
&lt;p>API 認證授權機制與 PTX 平台有蠻大的差異，簡單來說每次請求前要先身份認證取得 Access Token，才能使用 Access Token 來取得 TDX API 服務的數據資料。&lt;br />
(或使用尚未過期的 Access Token，有效期限預設為 1 天)&lt;/p>
&lt;br/>
&lt;p>詳細步驟說明如下:&lt;/p>
&lt;ol>
&lt;li>取得 Access Token&lt;/li>
&lt;/ol>
&lt;p>依照以下格式發出請求：&lt;/p>
&lt;pre>&lt;code>Request URL: https://tdx.transportdata.tw/auth/realms/TDXConnect/protocol/openid-connect/token
Request Method: POST
Request Headers:
content-type: application/x-www-form-urlencoded
data:
grant_type: client_credentials
client_id: &amp;lt;your_client_id&amp;gt;
client_secret: &amp;lt;your_client_secret&amp;gt;
&lt;/code>&lt;/pre>&lt;p>data 參數說明如下:&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Key&lt;/th>
&lt;th>Value&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>grant_type&lt;/code>&lt;/td>
&lt;td>固定使用 &lt;code>client_credentials&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>client_id&lt;/code>&lt;/td>
&lt;td>您的 Client Id，從 TDX 會員中心取得&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>client_secret&lt;/code>&lt;/td>
&lt;td>您的 Client Secret，從 TDX 會員中心取得&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>回傳資料是 JSON 格式，其中包含 &lt;code>access_token&lt;/code> 參數，就是我們要的 Access Token。&lt;/p>
&lt;br/>
&lt;ol start="2">
&lt;li>呼叫 TDX API 服務，取得數據資料&lt;/li>
&lt;/ol>
&lt;pre>&lt;code>Request URL: TDX_API_URI
Request Method: GET
Request Headers:
authorization: Bearer &amp;lt;Access_Token&amp;gt;
&lt;/code>&lt;/pre>&lt;p>* 若 Access Token 時間超過有效期限(第一步驟收到回應中的 expires_in 參數)，則再重新透過第一步驟取得即可。&lt;/p>
&lt;br/>
&lt;p>* 官方的說明文件： &lt;a href="https://github.com/tdxmotc/SampleCode">https://github.com/tdxmotc/SampleCode&lt;/a>&lt;/p>
&lt;br/>
&lt;h2 id="完整-python-程式範例">完整 Python 程式範例&lt;/h2>
&lt;p>因為 TDX 平台的 API 一樣使用 OData (Open Data Protocol) 標準介面，所以這邊我就不再寫一次了，還不太懂的可前往 &lt;a href="https://blog.jiatool.com/posts/ptx_intro" target="_blank" rel="noopener">
「PTX 平台」API 介紹 (含 Odata 說明)
&lt;/a> 了解。&lt;/p>
&lt;p>同樣以下方條件當範例查詢：&lt;/p>
&lt;p>台鐵&amp;quot;台北&amp;quot;車站即時的列車到離站看板資訊，並且只要&amp;quot;逆行&amp;quot;的列車&lt;/p>
&lt;br/>
&lt;p>查詢的 URL 會長得像這樣：&lt;br />
&lt;code>https://tdx.transportdata.tw/api/basic/v2/Rail/TRA/LiveBoard/Station/1000?$filter=Direction eq 1&amp;amp;$format=JSON&lt;/code>&lt;/p>
&lt;p>會發現與 PTX 平台根本一樣，只差在網址前方的部分。&lt;/p>
&lt;br/>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="n">client_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;&amp;lt;your_client_id&amp;gt;&amp;#39;&lt;/span>
&lt;span class="n">client_secret&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;&amp;lt;your_client_secret&amp;gt;&amp;#39;&lt;/span>
&lt;span class="k">class&lt;/span> &lt;span class="nc">TDX&lt;/span>&lt;span class="p">():&lt;/span>
&lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">client_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">client_secret&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">client_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">client_id&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">client_secret&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">client_secret&lt;/span>
&lt;span class="k">def&lt;/span> &lt;span class="nf">get_token&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="n">token_url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://tdx.transportdata.tw/auth/realms/TDXConnect/protocol/openid-connect/token&amp;#39;&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;content-type&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;application/x-www-form-urlencoded&amp;#39;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;grant_type&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;client_credentials&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;client_id&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">client_id&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;client_secret&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">client_secret&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">post&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">token_url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># print(response.status_code)&lt;/span>
&lt;span class="c1"># print(response.json())&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()[&lt;/span>&lt;span class="s1">&amp;#39;access_token&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="k">def&lt;/span> &lt;span class="nf">get_response&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">url&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;authorization&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;Bearer {self.get_token()}&amp;#39;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;__main__&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">tdx&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">TDX&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">client_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">client_secret&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># url = &amp;#39;https://tdx.transportdata.tw/api/basic/v2/Rail/TRA/LiveBoard/Station/1000?$filter=Direction eq 1&amp;amp;$format=JSON&amp;#39;&lt;/span>
&lt;span class="n">base_url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;https://tdx.transportdata.tw/api&amp;#34;&lt;/span>
&lt;span class="c1"># 取得指定[車站]列車即時到離站電子看板(動態前後30分鐘的車次)&lt;/span>
&lt;span class="n">endpoint&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;/basic/v2/Rail/TRA/LiveBoard/Station/1000&amp;#34;&lt;/span>
&lt;span class="nb">filter&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;Direction eq 1&amp;#34;&lt;/span> &lt;span class="c1"># 順逆行: [0:&amp;#39;順行&amp;#39;, 1:&amp;#39;逆行&amp;#39;]&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;{base_url}{endpoint}?$filter={filter}&amp;amp;$format=JSON&amp;#34;&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">tdx&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_response&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>如此應該就能順利取得資料 🎉🎉🎉&lt;/p>
&lt;br/>
&lt;h2 id="其他程式範例">其他程式範例&lt;/h2>
&lt;p>除了參考我上面的 Python 範例，TDX 官方有提供 JavaScript 與 C# 程式語言的範例程式碼，需要的可前往參考 (&lt;a href="https://github.com/tdxmotc/SampleCode" target="_blank" rel="noopener">
GitHub
&lt;/a>)。&lt;/p>
&lt;br/>
&lt;p>我有寫一篇 &lt;a href="%28/posts/tdx_google_apps_script%29" target="_blank" rel="noopener">
Google Apps Script 範例程式
&lt;/a> 可以參考。&lt;/p>
&lt;p>也感謝熱心網友 meebox，提供 &amp;quot;適用在嵌入式系統的 MicroPython 環境、token 有效期判斷&amp;quot; 的版本：&lt;br />
&lt;a href="https://github.com/codemee/tdx">https://github.com/codemee/tdx&lt;/a>&lt;/p>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>這次快速(?)帶大家了解「TDX 運輸資料流通服務平台」，看起來就是 PTX 平台的升級版，加入更多不同服務的資料。&lt;br />
如果你之前已經用 PTX 做些作品出來，不妨試著將其改串接至 TDX，畢竟可能明年 PTX 平台就無法使用了。&lt;/p>
&lt;br/>
&lt;p>歡迎追蹤『&lt;a href="https://www.facebook.com/jiatool" target="_blank" rel="noopener">
IT空間
&lt;/a>』FB 粉專，取得最新發文通知🔔&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://tdx.transportdata.tw/" target="_blank" rel="noopener">
TDX 運輸資料流通服務平台 | 官網
&lt;/a>&lt;br />
&lt;a href="https://tdx.transportdata.tw/api-service/swagger" target="_blank" rel="noopener">
TDX API 說明 | Swagger 文件工具
&lt;/a>&lt;br />
&lt;a href="https://github.com/tdxmotc/SampleCode" target="_blank" rel="noopener">
TDX 官方介接說明與範例程式碼 | GitHub
&lt;/a>&lt;br />
&lt;a href="https://tdx.transportdata.tw/about/faq" target="_blank" rel="noopener">
TDX 平台常見問題 | 官網
&lt;/a>&lt;/p>
&lt;br/>
&lt;blockquote>
&lt;p>你不可能有先見之明，只能有後見之明，&lt;br />
因此，你必須相信，這些小事一定會和你的未來產生關聯。&lt;/p>
&lt;p align="right">—— 史蒂夫·賈伯斯&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/tdx_python.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/tdx_python_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>TDX</category><category>API</category><category>交通</category><category>公共運輸</category><category>Python</category><category>分享</category></item><item><title>[Python爬蟲實例] 591 租屋網 - 搜尋房屋與房屋詳情</title><link>https://blog.jiatool.com/posts/house591_spider/</link><pubDate>Sat, 04 Jun 2022 20:55:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Mon, 29 Sep 2025 10:30:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/house591_spider/</guid><description>前言 之前某天在社團看到網友詢問 591 租屋網的網路爬蟲，因此才有這篇文章的誕生，距離 Python網路爬蟲實例 系列 上一篇文章已經隔了半年了呢 (好久~</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>之前某天在社團看到網友詢問 591 租屋網的網路爬蟲，因此才有這篇文章的誕生，距離 &lt;a href="https://blog.jiatool.com/series/Python%e7%b6%b2%e8%b7%af%e7%88%ac%e8%9f%b2%e5%af%a6%e4%be%8b/" target="_blank" rel="noopener">
Python網路爬蟲實例
&lt;/a>系列 上一篇文章已經隔了半年了呢 (好久~&lt;/p>
&lt;p>這次要來分別說明 591 租屋網的 &amp;quot;搜尋房屋&amp;quot; 與 &amp;quot;取得房屋詳情&amp;quot; 兩個請求，以及如何發出請求、取得回傳數據資料。&lt;/p>
&lt;div class="notices warning" data-title="2024年11月30日 此網路爬蟲方法已失效">
&lt;p>經網友提醒網站有改版，這篇文章的方法已過時，我雖然有再嘗試找出發請求的網址，但發現回傳資料有加密過的，要解開的話還要從它的 JS 程式中尋找 KEY 值，因為太麻煩就沒繼續研究了。&lt;/p>
&lt;p>不過後來我還有寫一篇 591 房屋交易「新建案」的搜尋與房屋詳情，有需要的讀者也可以過去逛逛：&lt;a href="https://blog.jiatool.com/posts/newhouse591_spider">[Python爬蟲實例] 591 房屋交易 -「新建案」搜尋與房屋詳情&lt;/a>&lt;/p>
&lt;/div>
&lt;br>
&lt;div class="notices warning" data-title="2025年09月29日 網友補充">
感謝 FB 網友補充 591 反爬蟲機制：&lt;a href="https://www.threads.com/@cjs.shawn/post/DPJil0fga33">https://www.threads.com/@cjs.shawn/post/DPJil0fga33&lt;/a>
&lt;/div>
&lt;br>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/house591_spider/house.jpg" alt="來源：Unsplash" data-caption="來源：Unsplash" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='550px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:550px;height:;"/>
&lt;figcaption style="text-align: center;">
來源：Unsplash
&lt;/figcaption>
&lt;/figure>
&lt;p>備註：此文僅教育學習，切勿用作商業用途，個人實作皆屬個人行為，本作者不負任何法律責任。&lt;/p>
&lt;h2 id="套件">套件&lt;/h2>
&lt;p>此次 Python 爬蟲主要使用到的套件：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Requests [&lt;a href="https://requests.readthedocs.io/en/master/" target="_blank" rel="noopener">
Doc
&lt;/a>] [&lt;a href="https://github.com/psf/requests" target="_blank" rel="noopener">
GitHub
&lt;/a>]&lt;/p>
&lt;/li>
&lt;li>
&lt;p>BeautifulSoup [&lt;a href="https://www.crummy.com/software/BeautifulSoup/bs4/doc/" target="_blank" rel="noopener">
Doc
&lt;/a>] [&lt;a href="https://code.launchpad.net/beautifulsoup" target="_blank" rel="noopener">
Source
&lt;/a>]&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>安裝&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">pip install requests
pip install beautifulsoup4
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;!--adsense-->
&lt;h2 id="搜尋房屋">搜尋房屋&lt;/h2>
&lt;p>首先到「&lt;a href="https://rent.591.com.tw/" target="_blank" rel="noopener">
591 租屋網
&lt;/a>」的搜尋頁面，我們想可以給不同篩選條件，並取得底下結果的房屋資訊。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/house591_spider/search_house_page.jpg" alt="搜尋房屋結果" data-caption="搜尋房屋結果" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
搜尋房屋結果
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="請求路徑與參數">請求路徑與參數&lt;/h3>
&lt;p>打開瀏覽器的 &lt;strong>開發人員工具&lt;/strong> (F12 或 Ctrl + Shift + i) &amp;gt; &lt;strong>Network&lt;/strong> 分頁，在 &amp;quot;Fetch/XHR&amp;quot; 分類中找找看哪個是搜尋房屋結果的請求。&lt;/p>
&lt;p>稍微比對後，即可確定是 &lt;code>https://rent.591.com.tw/home/search/rsList&lt;/code> 這個請求。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/house591_spider/request_rsList.jpg" alt="rsList 請求" data-caption="rsList 請求" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='950px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:950px;height:;"/>
&lt;figcaption style="text-align: center;">
rsList 請求
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>但透過 Python 的 requests 直接發送 &lt;code>https://rent.591.com.tw/home/search/rsList?is_format_data=1&amp;amp;is_new_list=1&amp;amp;type=1&amp;amp;region=3&lt;/code> 請求，卻會收到失敗的訊息。&lt;br />
HTTP 狀態碼 (HTTP Status Code) 為 419，網頁內容顯示 &amp;quot;The page has expired due to inactivity.&amp;quot;，推測可能是我們缺少哪些必要參數。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/house591_spider/httpStatusCode419.png" alt="HTTP 狀態碼 419" data-caption="HTTP 狀態碼 419" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='450px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:450px;height:;"/>
&lt;figcaption style="text-align: center;">
HTTP 狀態碼 419
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>經過我的測試，發現它需要代上 Cookie 與 X-CSRF-TOKEN 這兩個必要參數，才能夠順利取得資料。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/house591_spider/x_csrf_token.png" alt="X-CSRF-TOKEN 參數" data-caption="X-CSRF-TOKEN 參數" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
X-CSRF-TOKEN 參數
&lt;/figcaption>
&lt;/figure>
&lt;p>可以直接在 開發人員工具 &amp;gt; Network 搜尋(Ctrl+F)來尋找這個值是從何來。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/house591_spider/find_x_csrf_token.png" alt="搜尋 X-CSRF-TOKEN 參數" data-caption="搜尋 X-CSRF-TOKEN 參數" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
搜尋 X-CSRF-TOKEN 參數
&lt;/figcaption>
&lt;/figure>
&lt;p>在 &lt;code>https://rent.591.com.tw/&lt;/code> 的 &lt;code>&amp;lt;meta name=&amp;quot;csrf-token&amp;quot;&amp;gt;&lt;/code> 裡能找到此字串。&lt;br />
另外 Cookie 也是請求此網址後可取得。&lt;/p>
&lt;p>因此在我們實際要搜尋房屋資料前，要先請求 &lt;code>https://rent.591.com.tw/&lt;/code> 將 Cookie 與 X-CSRF-TOKEN 這兩個參數字串準備好。&lt;/p>
&lt;br/>
&lt;p>另外，&lt;br />
我們可以透過帶入不同的搜尋參數值，來達到對結果做不同的篩選。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/house591_spider/filter_condition.png" alt="篩選條件參數" data-caption="篩選條件參數" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
篩選條件參數
&lt;/figcaption>
&lt;/figure>
&lt;p>以下我將其全部羅列出來，但第一項 &amp;quot;位置&amp;quot; 有太多種類，就不一一呈現，可以自己選擇後再從 &lt;strong>開發人員工具&lt;/strong> 查看。&lt;/p>
&lt;p>* 以下某些選項在網頁上是可以多選的，則參數的數值用逗號 &lt;code>,&lt;/code> 隔開即可。&lt;br />
* 如 &lt;code>multiArea=10_20,20_30&lt;/code> 坪數 10-20坪 和 20-30坪。&lt;/p>
&lt;p>&lt;strong>房屋類型&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>類型&lt;/th>
&lt;th>kind:&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>不限&lt;/td>
&lt;td>0&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>整層住家&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>獨立套房&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>分租套房&lt;/td>
&lt;td>3&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>雅房&lt;/td>
&lt;td>4&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>車位&lt;/td>
&lt;td>8&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>其他&lt;/td>
&lt;td>24&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>租金&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>租金&lt;/th>
&lt;th>multiPrice:&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>5000元以下&lt;/td>
&lt;td>0_5000&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>5000-10000元&lt;/td>
&lt;td>5000_10000&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>10000-20000元&lt;/td>
&lt;td>10000_20000&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>20000-30000元&lt;/td>
&lt;td>20000_30000&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>30000-40000元&lt;/td>
&lt;td>30000_40000&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>40000元以上&lt;/td>
&lt;td>40000_&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>* 如果要自訂租金範圍，改用 &lt;code>rentprice&lt;/code> 參數(如 &amp;quot;3000~6000元&amp;quot; 要用 &lt;code>rentprice=3000,6000&lt;/code>)。&lt;/p>
&lt;p>&lt;strong>格局&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>格局&lt;/th>
&lt;th>multiRoom:&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>1房&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>2房&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>3房&lt;/td>
&lt;td>3&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>4房以上&lt;/td>
&lt;td>4&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>特色&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>特色&lt;/th>
&lt;th>other:&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>新上架&lt;/td>
&lt;td>newPost&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>近捷運&lt;/td>
&lt;td>near_subway&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>可養寵物&lt;/td>
&lt;td>pet&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>可開伙&lt;/td>
&lt;td>cook&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>有車位&lt;/td>
&lt;td>cartplace&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>有電梯&lt;/td>
&lt;td>lift&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>有陽台&lt;/td>
&lt;td>balcony_1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>可短期租賃&lt;/td>
&lt;td>lease&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;br/>
&lt;p>而以下選項在網頁中需要點擊展開，觀察它 API 再加入以下選項時，還多附加 &lt;code>showMore=1&lt;/code> 參數，但實測貌似沒有影響(？)，但建議還是加上比較保險。&lt;/p>
&lt;p>&lt;strong>型態&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>型態&lt;/th>
&lt;th>shape:&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>公寓&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>電梯大樓&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>透天厝&lt;/td>
&lt;td>3&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>別墅&lt;/td>
&lt;td>4&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>坪數&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>坪數&lt;/th>
&lt;th>multiArea:&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>10坪以下&lt;/td>
&lt;td>0_10&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>10-20坪&lt;/td>
&lt;td>10_20&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>20-30坪&lt;/td>
&lt;td>20_30&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>30-40坪&lt;/td>
&lt;td>30_40&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>40-50坪&lt;/td>
&lt;td>40_50&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>50坪以上&lt;/td>
&lt;td>50_&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>* 如果要自訂坪數範圍，改用 &lt;code>area&lt;/code> 參數(如 &amp;quot;20~50坪&amp;quot; 要用 &lt;code>area=20,50&lt;/code>)。&lt;/p>
&lt;p>&lt;strong>樓層&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>樓層&lt;/th>
&lt;th>multiFloor:&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>1層&lt;/td>
&lt;td>0_1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>2-6層&lt;/td>
&lt;td>2_6&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>6-12層&lt;/td>
&lt;td>6_12&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>12層以上&lt;/td>
&lt;td>12_&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>設備&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>設備&lt;/th>
&lt;th>option:&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>有冷氣&lt;/td>
&lt;td>cold&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>有洗衣機&lt;/td>
&lt;td>washer&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>有冰箱&lt;/td>
&lt;td>icebox&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>有熱水器&lt;/td>
&lt;td>hotwater&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>有天然瓦斯&lt;/td>
&lt;td>naturalgas&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>有網路&lt;/td>
&lt;td>broadband&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>床&lt;/td>
&lt;td>bed&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>須知&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>須知&lt;/th>
&lt;th>multiNotice:&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>男女皆可&lt;/td>
&lt;td>all_sex&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>限男生&lt;/td>
&lt;td>boy&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>限女生&lt;/td>
&lt;td>girl&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>排除頂樓加蓋&lt;/td>
&lt;td>not_cover&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>* 要注意，不同 &amp;quot;類型&amp;quot; 的房屋，可附加的篩選條件有些不同，可以實際在網頁先點選嘗試。&lt;/p>
&lt;br/>
&lt;br/>
&lt;p>&lt;strong>排序&lt;/strong>&lt;/p>
&lt;p>還有可通過帶入不同的排序參數，來對搜尋結果房屋作排序。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>排序依據&lt;/th>
&lt;th>order:&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>發佈時間&lt;/td>
&lt;td>posttime&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>租金&lt;/td>
&lt;td>money&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>坪數&lt;/td>
&lt;td>area&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>排序順序&lt;/th>
&lt;th>orderType:&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>由小到大&lt;/td>
&lt;td>asc&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>由大到小&lt;/td>
&lt;td>desc&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;br/>
&lt;p>&lt;strong>換頁&lt;/strong>&lt;/p>
&lt;p>而一次請求只會傳回 30 筆資料，就等同於網頁顯示&amp;quot;一頁&amp;quot;的資料，我們可以試著在瀏覽器切換不同頁數，觀察請求的網址變化：&lt;/p>
&lt;p>第 1 頁&lt;br />
&lt;code>https://rent.591.com.tw/home/search/rsList?is_format_data=1&amp;amp;is_new_list=1&amp;amp;type=1&amp;amp;&lt;/code>&lt;br />
第 2 頁&lt;br />
&lt;code>https://rent.591.com.tw/home/search/rsList?is_format_data=1&amp;amp;is_new_list=1&amp;amp;type=1&amp;amp;firstRow=30&amp;amp;totalRows=11227&lt;/code>&lt;br />
第 3 頁&lt;br />
&lt;code>https://rent.591.com.tw/home/search/rsList?is_format_data=1&amp;amp;is_new_list=1&amp;amp;type=1&amp;amp;firstRow=60&amp;amp;totalRows=11227&lt;/code>&lt;br />
第 10 頁&lt;br />
&lt;code>https://rent.591.com.tw/home/search/rsList?is_format_data=1&amp;amp;is_new_list=1&amp;amp;type=1&amp;amp;firstRow=270&amp;amp;totalRows=11227&lt;/code>&lt;/p>
&lt;br/>
&lt;p>最後的 &lt;code>totalRows&lt;/code> 是代表此條件的搜尋結果總筆數，但經過我的嘗試，貌似有沒有帶此參數，並不影響結果。&lt;/p>
&lt;p>重點是在 &lt;code>firstRow&lt;/code> 參數，代表要從第幾筆資料開始取得，這跟我們以前在其他文章提過的 &lt;code>offset&lt;/code> 概念類似。&lt;br />
(可參考我之前整理的 &lt;a href="https://blog.jiatool.com/posts/web_crawler_page_method/" target="_blank" rel="noopener">
(圖解) 網路爬蟲 API 常見的 3 種「翻頁」方式
&lt;/a> 文章)&lt;/p>
&lt;p>&lt;code>firstRow=0&lt;/code> -&amp;gt; 代表第 1 頁；&lt;br />
&lt;code>firstRow=30&lt;/code> -&amp;gt; 代表第 2 頁；&lt;br />
&lt;code>firstRow=60&lt;/code> -&amp;gt; 代表第 3 頁；&lt;/p>
&lt;br/>
&lt;p>再補充一點，在以 &amp;quot;鄉鎮&amp;quot; 為條件搜尋時，需要在 cookie 內加入一個參數，否則搜尋出來會沒有結果。&lt;br />
&lt;code>'urlJumpIp', '17', domain='.591.com.tw', path='/'&lt;/code>&lt;/p>
&lt;p>這是經網友留言提問，另一位熱心網由找到解答並回覆，我稍微調整一下寫法，使其加入範例程式碼內。&lt;/p>
&lt;br/>
&lt;h3 id="回傳資料">回傳資料&lt;/h3>
&lt;p>回傳資料會有此條件搜尋出來的房屋總筆數(&lt;code>records&lt;/code>)，以及房屋基本資訊(&lt;code>data&lt;/code> &amp;gt; &lt;code>data&lt;/code>)，而房屋基本資訊會有像是 &amp;quot;標題&amp;quot;、&amp;quot;價格&amp;quot;、&amp;quot;圖片&amp;quot;、&amp;quot;房屋類型&amp;quot;、&amp;quot;樓層&amp;quot;、&amp;quot;地區&amp;quot;、&amp;quot;標籤&amp;quot;&amp;hellip;&amp;hellip;等等，大致上就是你在網頁可以看到的那些資訊。&lt;/p>
&lt;p>回覆資料範例：&lt;a href="https://github.com/it-jia/house591_spider/blob/main/house591_search.json" target="_blank" rel="noopener">
house591_search.json (搜尋房屋)
&lt;/a>&lt;/p>
&lt;br/>
&lt;h3 id="範例程式">範例程式&lt;/h3>
&lt;p>使用 Python 撰寫 &amp;quot;搜尋房屋&amp;quot; 的寫法如下，完整程式碼請至文末參考：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python"> &lt;span class="k">def&lt;/span> &lt;span class="nf">search&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">filter_params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">None&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">sort_params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">None&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">want_page&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34; 搜尋房屋 &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">total_count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="n">house_list&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;span class="n">page&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="c1"># 紀錄 Cookie 取得 X-CSRF-TOKEN&lt;/span>
&lt;span class="n">s&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Session&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://rent.591.com.tw/&amp;#39;&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">s&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">soup&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">BeautifulSoup&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;html.parser&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">token_item&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;meta[name=&amp;#34;csrf-token&amp;#34;]&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">copy&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">headers&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;X-CSRF-TOKEN&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">token_item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;content&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 搜尋房屋&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://rent.591.com.tw/home/search/rsList&amp;#39;&lt;/span>
&lt;span class="n">params&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;is_format_data=1&amp;amp;is_new_list=1&amp;amp;type=1&amp;#39;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">filter_params&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="c1"># 加上篩選參數，要先轉換為 URL 參數字串格式&lt;/span>
&lt;span class="n">params&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;&amp;amp;{key}={value}&amp;#39;&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">filter_params&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">items&lt;/span>&lt;span class="p">()])&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">params&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="s1">&amp;#39;&amp;amp;region=1&amp;amp;kind=0&amp;#39;&lt;/span>
&lt;span class="c1"># 在 cookie 設定地區縣市，避免某些條件無法取得資料&lt;/span>
&lt;span class="n">s&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cookies&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;urlJumpIp&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">filter_params&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;region&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;1&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="n">filter_params&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="s1">&amp;#39;1&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">domain&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;.591.com.tw&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 排序參數&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">sort_params&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">params&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;&amp;amp;{key}={value}&amp;#39;&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">sort_params&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">items&lt;/span>&lt;span class="p">()])&lt;/span>
&lt;span class="k">while&lt;/span> &lt;span class="n">page&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">want_page&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">params&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;&amp;amp;firstRow={page*30}&amp;#39;&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">s&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">params&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;請求失敗&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">break&lt;/span>
&lt;span class="n">page&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">total_count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;records&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="n">house_list&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extend&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;data&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;data&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="c1"># 隨機 delay 一段時間&lt;/span>
&lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">uniform&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">))&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">total_count&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">house_list&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;!--adsense-->
&lt;h2 id="取得房屋詳情">取得房屋詳情&lt;/h2>
&lt;p>&amp;quot;取得房屋詳情&amp;quot; 是指從搜尋頁面選一間房屋後點進來，所呈現關於此房屋的詳細資訊。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/house591_spider/house_detail_page.jpg" alt="房屋詳細資訊" data-caption="房屋詳細資訊" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
房屋詳細資訊
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="請求路徑與參數-1">請求路徑與參數&lt;/h3>
&lt;p>一樣打開瀏覽器的 &lt;strong>開發人員工具&lt;/strong> (F12 或 Ctrl + Shift + i) &amp;gt; &lt;strong>Network&lt;/strong> 分頁，在 &amp;quot;Fetch/XHR&amp;quot; 分類中就可以找到是哪個請求。&lt;/p>
&lt;p>經過比對，確認是 &lt;code>https://bff.591.com.tw/v1/house/rent/detail?id=1254xxxx&lt;/code> 請求，網址後方也可以發現是代表此房屋的 ID，也等同於目前瀏覽器網址後方的數字。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/house591_spider/request_detail.png" alt="detail 請求" data-caption="detail 請求" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='950px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:950px;height:;"/>
&lt;figcaption style="text-align: center;">
detail 請求
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>不過相比 &amp;quot;搜尋房屋&amp;quot; API 所需要的參數，&amp;quot;取得房屋詳情&amp;quot; 還多了 &lt;code>device&lt;/code>、&lt;code>deviceid&lt;/code> 兩個必備參數，&lt;/p>
&lt;p>&lt;code>device&lt;/code> 就固定 &lt;code>pc&lt;/code> 即可，而 &lt;code>deviceid&lt;/code> 我們透過搜尋(Ctrl+F)發現，它隱藏在 &amp;quot;cookie&amp;quot; 之中，所以之後程式要將其字串抓出來代上。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/house591_spider/deviceid.png" alt="deviceid 參數" data-caption="deviceid 參數" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
deviceid 參數
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h3 id="回傳資料-1">回傳資料&lt;/h3>
&lt;p>回傳資料大致上也是與網頁上的一樣，關於此房屋的詳細資訊，你可以挑出需要的欄位來儲存，或進一步判斷執行其他動作。&lt;/p>
&lt;p>回覆資料範例：&lt;a href="https://github.com/it-jia/house591_spider/blob/main/house591_detail.json" target="_blank" rel="noopener">
house591_detail.json (房屋詳情)
&lt;/a>&lt;/p>
&lt;br/>
&lt;h3 id="範例程式-1">範例程式&lt;/h3>
&lt;p>使用 Python 撰寫 &amp;quot;搜尋房屋&amp;quot; 的寫法如下，完整程式碼請至文末參考：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python"> &lt;span class="k">def&lt;/span> &lt;span class="nf">get_house_detail&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">house_id&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34; 房屋詳情 &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="c1"># 紀錄 Cookie 取得 X-CSRF-TOKEN, deviceid&lt;/span>
&lt;span class="n">s&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Session&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://rent.591.com.tw/home/{house_id}&amp;#39;&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">s&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">soup&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">BeautifulSoup&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;html.parser&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">token_item&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;meta[name=&amp;#34;csrf-token&amp;#34;]&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">copy&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">headers&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;X-CSRF-TOKEN&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">token_item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;content&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">headers&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;deviceid&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">s&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cookies&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_dict&lt;/span>&lt;span class="p">()[&lt;/span>&lt;span class="s1">&amp;#39;T591_TOKEN&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="c1"># headers[&amp;#39;token&amp;#39;] = s.cookies.get_dict()[&amp;#39;PHPSESSID&amp;#39;]&lt;/span>
&lt;span class="n">headers&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;device&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;pc&amp;#39;&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://bff.591.com.tw/v1/house/rent/detail?id={house_id}&amp;#39;&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">s&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;請求失敗&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span>
&lt;span class="n">house_detail&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()[&lt;/span>&lt;span class="s1">&amp;#39;data&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">house_detail&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;!--adsense-->
&lt;h2 id="完整程式碼">完整程式碼&lt;/h2>
&lt;p>我將以上兩種請求寫到 class 中，並可以傳入不同的值來篩選，供需要的人參考。&lt;/p>
&lt;p>附上完整程式碼：&lt;a href="https://github.com/it-jia/house591_spider/blob/main/house591_spider.py" target="_blank" rel="noopener">
house591_spider.py | GitHub
&lt;/a>&lt;/p>
&lt;h2 id="延伸練習">延伸練習&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>在上面教學與範例中，我們都是搜尋 &amp;quot;所有物件&amp;quot; 的房屋，那如果我想搜尋 &amp;quot;優選好屋&amp;quot; 該如何帶 API 參數呢？&lt;/p>
&lt;/li>
&lt;li>
&lt;p>你能試著找出全台最貴的租屋要多少租金嗎？並且是在哪個縣市鄉鎮？&lt;/p>
&lt;/li>
&lt;li>
&lt;p>台中市的房屋中 &amp;quot;整層住家&amp;quot;、&amp;quot;獨立套房&amp;quot;、&amp;quot;分租套房&amp;quot;、&amp;quot;雅房&amp;quot; 之間的數量與比例是多少呢？會是分租套房最多嗎？&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>最後也要提醒，不要太頻繁地發出請求，這對伺服器來說算是種攻擊，也容易被擋，建議請求之間要加入 delay。&lt;/p>
&lt;p>如果有找到適合或有趣的題材，會繼續寫一些網站的&lt;a href="https://blog.jiatool.com/series/Python%e7%b6%b2%e8%b7%af%e7%88%ac%e8%9f%b2%e5%af%a6%e4%be%8b/" target="_blank" rel="noopener">
Python網路爬蟲實例
&lt;/a>，如果你正好是剛開始想學爬蟲的新手、想知道某網站如何爬取資料、遇到其他問題，也歡迎在底下留言，或追蹤 FB 粉專『&lt;a href="https://www.facebook.com/jiatool" target="_blank" rel="noopener">
IT空間
&lt;/a>』~ 🔔&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;blockquote>
&lt;p>要成就一件大事業，必須從小事做起。&lt;/p>
&lt;p align="right">—— 列寧&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/house591_spider.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/house591_spider_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Python</category><category>網路爬蟲</category><category>Python網路爬蟲實例</category></item><item><title>「PTX 公共運輸資訊平台」Python 範例程式</title><link>https://blog.jiatool.com/posts/ptx_python/</link><pubDate>Sat, 30 Apr 2022 20:55:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Thu, 03 Nov 2022 21:50:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/ptx_python/</guid><description>因部內目前已收攏資料於TDX運輸資訊整合流通服務平台，本平台預計將於2022/12/1落日，屆時您的會員金鑰將於2022/12/1起停用。 為</description><content:encoded>&lt;br/>
&lt;div class="notices warning" data-title="P t x 平台將停止使用">
因部內目前已收攏資料於TDX運輸資訊整合流通服務平台，本平台預計將於2022/12/1落日，屆時您的會員金鑰將於2022/12/1起停用。&lt;br />
為避免您短時間內需移轉之困擾，即日起本平台不再受理審核會員註冊。&lt;br />
建議您依據身分類型至TDX申請會員，非常感謝您的支持。
&lt;/div>
&lt;h2 id="前言">前言&lt;/h2>
&lt;p>在上一篇文章中，我們介紹了&lt;a href="https://ptx.transportdata.tw/PTX/" target="_blank" rel="noopener">
PTX 公共運輸整合資訊流通服務平台
&lt;/a>，它整合公車、臺鐵、高鐵、捷運等多項公共運輸的資料服務 API，以及說明 OData（Open Data Protocol）標準介面格式如何使用。&lt;/p>
&lt;p>本篇文章將帶你實際使用 Python 來串接 PTX 平台，取得這些相關數據資料 💾。&lt;/p>
&lt;br/>
&lt;p>關於 PTX 平台我寫了三篇文章來介紹與程式教學：&lt;/p>
&lt;ol>
&lt;li>&lt;a href="https://blog.jiatool.com/posts/ptx_intro" target="_blank" rel="noopener">
「PTX 公共運輸資訊平台」API 介紹 (含 Odata 說明)
&lt;/a>&lt;/li>
&lt;li>「PTX 公共運輸資訊平台」Python 範例 &amp;lt;&amp;ndash; 本篇&lt;/li>
&lt;li>&lt;a href="https://blog.jiatool.com/posts/ptx_google_apps_script" target="_blank" rel="noopener">
「PTX 公共運輸資訊平台」Google Apps Script 範例
&lt;/a>&lt;/li>
&lt;/ol>
&lt;br/>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/ptx_intro/ptx_home.jpg" alt="PTX 公共運輸整合資訊流通服務平台" data-caption="PTX 公共運輸整合資訊流通服務平台" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='650px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:650px;height:;"/>
&lt;figcaption style="text-align: center;">
PTX 公共運輸整合資訊流通服務平台
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>後來發現 PTX 竟然只服務到今年(2022年)底，之後會改以 TDX 運輸資訊整合流通服務平台，因此又特別寫一篇文章帶大家快速了解一下 TDX 平台：&lt;br />
&lt;a href="https://blog.jiatool.com/posts/tdx_python" target="_blank" rel="noopener">
「TDX 運輸資料流通服務平臺」含 Python 範例程式，PTX 平台的升級版~
&lt;/a>&lt;/p>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="api-認證授權機制">API 認證授權機制&lt;/h2>
&lt;p>目前 PTX 平台採用 HMAC 認證授權機制，在送出請求時 headers 需代上規定的資料，它會依照 HTTP header 資訊來判別用戶是否有授權身份 🔓。&lt;/p>
&lt;p>官方說明如下：&lt;/p>
&lt;blockquote>
&lt;p>HMAC 機制：以 HMAC 簽章驗證使用者的身份，用戶在請求 API 服務時，將 APP Key 與當下時間(格式請使用GMT時間) 做 HMAC-SHA1 運算後轉成 Base64 格式，帶入 signature 屬性欄位，服務器端將驗證用戶請求時的 header 欄位，驗證使用者的身份及請求服務的時效性。&lt;/p>
&lt;p>HMAC Signature 簽章時效性：於 MOTC Helper 該網頁測試時，請在最上方輸入 API Key 與 API ID (請再次確認是否有把 APP Key 跟 ID 填寫正確，若欄位資訊相反會無法執行)。點選 Explore ，每次請求下方 API 時，會於 header 帶入 Authorization 及 x-date ，依照請求當下的時間 &amp;amp; API Key 製作簽章。&lt;/p>
&lt;/blockquote>
&lt;p>參數如下：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>Key&lt;/th>
&lt;th>Value&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>Authorization&lt;/code>&lt;/td>
&lt;td>&lt;code>hmac username=&amp;quot;APP ID&amp;quot;, algorithm=&amp;quot;hmac-sha1&amp;quot;, headers=&amp;quot;x-date&amp;quot;, signature=&amp;quot;Base64(HMAC-SHA1(&amp;quot;x-date: &amp;quot; + x-date , APP Key))&amp;quot;&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>x-date&lt;/code>&lt;/td>
&lt;td>&lt;code>Wed, 19 Apr 2017 08:37:50 GMT&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>※ 建議於每次請求 API 服務當下建立新的 signature，簽章時效性為 5 分鐘。&lt;/p>
&lt;br/>
&lt;p>如果 HMAC 認證有問題、未符合身份驗證，它會回覆下列訊息：&lt;/p>
&lt;ul>
&lt;li>HTTP Status Code 403：
&lt;ul>
&lt;li>(1) HMAC signature cannot be verified, a valid date or x-date header is required for HMAC Authentication （x-date 的間隔時間超過定義的 clock skew 秒數）&lt;/li>
&lt;li>(2) HMAC signature does not match （日期格式正確，但簽章演算法有問題）&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>HTTP Status Code 401：
&lt;ul>
&lt;li>(1) Unauthorized （未帶簽章，未經授權）&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;br/>
&lt;br/>
&lt;p>依照上方說明，使用 Python 把這個 HMAC 編碼寫出來，這邊我也是參考範例來做修改的。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">class&lt;/span> &lt;span class="nc">Auth&lt;/span>&lt;span class="p">():&lt;/span>
&lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">app_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">app_key&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">app_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">app_id&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">app_key&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">app_key&lt;/span>
&lt;span class="k">def&lt;/span> &lt;span class="nf">get_auth_header&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="n">xdate&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">utcnow&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strftime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;%a, &lt;/span>&lt;span class="si">%d&lt;/span>&lt;span class="s2"> %b %Y %H:%M:%S GMT&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">hashed&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">hmac&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">new&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">app_key&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">encode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;utf8&amp;#39;&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;x-date: {xdate}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">encode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;utf8&amp;#39;&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">sha1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">signature&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">base64&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">b64encode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">hashed&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">digest&lt;/span>&lt;span class="p">())&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">authorization&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;hmac username=&amp;#34;{self.app_id}&amp;#34;, algorithm=&amp;#34;hmac-sha1&amp;#34;&amp;#39;&lt;/span> &lt;span class="o">+&lt;/span>
&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;, headers=&amp;#34;x-date&amp;#34;, signature=&amp;#34;{signature}&amp;#34;&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;Authorization&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">authorization&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;x-date&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">xdate&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;Accept-Encoding&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;gzip&amp;#39;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h2 id="python-程式範例">Python 程式範例&lt;/h2>
&lt;p>我們來實際舉個例子，像是我想抓：&lt;/p>
&lt;p>台鐵&amp;quot;台北&amp;quot;車站即時的列車到離站看板資訊，並且只要&amp;quot;逆行&amp;quot;的列車&lt;/p>
&lt;br/>
&lt;p>先進到 PTX 平台的 Swagger 文件，找到 &amp;quot;&lt;a href="https://ptx.transportdata.tw/MOTC/?urls.primaryName=%E8%BB%8C%E9%81%93V2#/TRA/TRAApi_LiveBoard_2153_1" target="_blank" rel="noopener">
取得指定[車站]列車即時到離站電子看板
&lt;/a>&amp;quot;：&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/ptx_intro/LiveBoard.png" alt="列車即時到離站電子看板" data-caption="列車即時到離站電子看板" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
列車即時到離站電子看板
&lt;/figcaption>
&lt;/figure>
&lt;p>填入 &amp;quot;台北車站&amp;quot; 代碼 &lt;code>1000&lt;/code> (&lt;a href="https://tip.railway.gov.tw/tra-tip-web/tip/tip001/tip111/view" target="_blank" rel="noopener">
車站代碼表
&lt;/a>)，並依照下方 Responses 欄位說明 &amp;quot;Direction&amp;quot; 代表順逆行(0:'順行', 1:'逆行')，在 $filter 填入 &lt;code>Direction eq 1&lt;/code>，指定 &lt;code>JSON&lt;/code> 格式，最後點擊藍色 &amp;quot;Execute&amp;quot; 按鈕，看看回傳結果是不是我們想要的~&lt;/p>
&lt;p>(關於這些 Odata 的寫法，我在&lt;a href="https://blog.jiatool.com/posts/ptx_intro" target="_blank" rel="noopener">
上一篇文章
&lt;/a>有說明，忘記的可以回去看看)&lt;/p>
&lt;br/>
&lt;p>它顯示的 &amp;quot;Request URL&amp;quot; 長得像這樣：&lt;br />
&lt;code>https://ptx.transportdata.tw/MOTC/v2/Rail/TRA/LiveBoard/Station/1000?%24filter=Direction%20eq%201&amp;amp;%24format=JSON&lt;/code>&lt;/p>
&lt;p>這是以下這句經過 URL 編碼後的結果：&lt;br />
(程式中 requests 會自動幫我們編碼，因此輸入底下這句也可以)&lt;br />
&lt;code>https://ptx.transportdata.tw/MOTC/v2/Rail/TRA/LiveBoard/Station/1000?$filter=Direction eq 1&amp;amp;$format=JSON&lt;/code>&lt;/p>
&lt;br/>
&lt;p>接下來將這些代入程式中：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">auth&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Auth&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">app_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">app_key&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;https://ptx.transportdata.tw/MOTC/v2/Rail/TRA/LiveBoard/Station/1000?$filter=Direction eq 1&amp;amp;$format=JSON&amp;#34;&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">auth&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_auth_header&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>如此應該就能順利取得資料 🎉🎉🎉&lt;/p>
&lt;br/>
&lt;h2 id="完整-python-程式範例">完整 Python 程式範例&lt;/h2>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">hmac&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">base64&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="kn">from&lt;/span> &lt;span class="nn">datetime&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">datetime&lt;/span>
&lt;span class="kn">from&lt;/span> &lt;span class="nn">hashlib&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">sha1&lt;/span>
&lt;span class="n">app_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;&amp;lt;YOUR APP ID&amp;gt;&amp;#39;&lt;/span>
&lt;span class="n">app_key&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;&amp;lt;YOUR APP KEY&amp;gt;&amp;#39;&lt;/span>
&lt;span class="k">class&lt;/span> &lt;span class="nc">Auth&lt;/span>&lt;span class="p">():&lt;/span>
&lt;span class="k">def&lt;/span> &lt;span class="fm">__init__&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">app_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">app_key&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">app_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">app_id&lt;/span>
&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">app_key&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">app_key&lt;/span>
&lt;span class="k">def&lt;/span> &lt;span class="nf">get_auth_header&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="n">xdate&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">utcnow&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strftime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;%a, &lt;/span>&lt;span class="si">%d&lt;/span>&lt;span class="s2"> %b %Y %H:%M:%S GMT&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">hashed&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">hmac&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">new&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">app_key&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">encode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;utf8&amp;#39;&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;x-date: {xdate}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">encode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;utf8&amp;#39;&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">sha1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">signature&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">base64&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">b64encode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">hashed&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">digest&lt;/span>&lt;span class="p">())&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">authorization&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;hmac username=&amp;#34;{self.app_id}&amp;#34;, algorithm=&amp;#34;hmac-sha1&amp;#34;&amp;#39;&lt;/span> &lt;span class="o">+&lt;/span>
&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;, headers=&amp;#34;x-date&amp;#34;, signature=&amp;#34;{signature}&amp;#34;&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;Authorization&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">authorization&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;x-date&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">xdate&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;Accept-Encoding&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;gzip&amp;#39;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;__main__&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">auth&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Auth&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">app_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">app_key&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">base_url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;https://ptx.transportdata.tw&amp;#34;&lt;/span>
&lt;span class="c1"># 取得指定[車站]列車即時到離站電子看板(動態前後30分鐘的車次)&lt;/span>
&lt;span class="n">endpoint&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;/MOTC/v2/Rail/TRA/LiveBoard/Station/1000&amp;#34;&lt;/span>
&lt;span class="nb">filter&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;Direction eq 1&amp;#34;&lt;/span> &lt;span class="c1"># 順逆行: [0:&amp;#39;順行&amp;#39;, 1:&amp;#39;逆行&amp;#39;]&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;{base_url}{endpoint}?$filter={filter}&amp;amp;$format=JSON&amp;#34;&lt;/span>
&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">auth&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_auth_header&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h2 id="其他程式範例">其他程式範例&lt;/h2>
&lt;p>除了參考我上面的 Python 範例，PTX 官方也提供不同程式語言的範例程式碼提供開發者下載 (&lt;a href="https://github.com/ptxmotc/Sample-code" target="_blank" rel="noopener">
GitHub
&lt;/a>)。&lt;/p>
&lt;ul>
&lt;li>平台提供
&lt;ul>
&lt;li>ASP.NET&lt;/li>
&lt;li>Java&lt;/li>
&lt;li>JavaScript&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>網友提供
&lt;ul>
&lt;li>Bourne Shell&lt;/li>
&lt;li>C# 與 .NET Standard 2.0&lt;/li>
&lt;li>Go&lt;/li>
&lt;li>Go Client SDK - Code generated by go-swagger&lt;/li>
&lt;li>Node.js&lt;/li>
&lt;li>python&lt;/li>
&lt;li>Ruby&lt;/li>
&lt;li>Swift&lt;/li>
&lt;li>PHP&lt;/li>
&lt;li>Postman&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;br/>
&lt;p>另外，在下一篇文章裡，我會分享 &lt;a href="https://blog.jiatool.com/posts/ptx_google_apps_script" target="_blank" rel="noopener">
Google Apps Script 的範例程式
&lt;/a>，它跟一般 JavaScript 有一些些不同，Google Apps Script 中預設應該是不能使用 jQuery，還有編碼的寫法也有些不同。&lt;/p>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>除了以上文章的解說，也可以看看&lt;a href="https://gist.github.com/ptxmotc/383118204ecf7192bdf96bc0197bb981" target="_blank" rel="noopener">
官方的文件說明
&lt;/a>。&lt;br />
有針對 &amp;quot;航空&amp;quot;、&amp;quot;公車&amp;quot;、&amp;quot;雙鐵(台鐵/高鐵)&amp;quot; 資料做進一步的說明，如果有使用到此 API 服務的人，建議進入先了解。&lt;br />
* 不過我看此文件上次更新時間 2018/04/12，可能有些資料不是最新的。&lt;/p>
&lt;br/>
&lt;p>上一篇了解 &lt;a href="https://blog.jiatool.com/posts/ptx_intro" target="_blank" rel="noopener">
PTX 平台的說明與 OData 介面
&lt;/a>，本篇則教你如何透過 Python 程式來發出請求、獲取資料，快將你有趣的 idea 來動手做實現它吧~&lt;/p>
&lt;br/>
&lt;p>歡迎追蹤『&lt;a href="https://www.facebook.com/jiatool" target="_blank" rel="noopener">
IT空間
&lt;/a>』FB 粉專，取得最新發文通知🔔&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://ptx.transportdata.tw/PTX/" target="_blank" rel="noopener">
公共運輸整合資訊流通服務平台 | 官網
&lt;/a>&lt;br />
&lt;a href="https://gist.github.com/ptxmotc/383118204ecf7192bdf96bc0197bb981" target="_blank" rel="noopener">
PTX 資料服務使用注意事項 | GitHub
&lt;/a>&lt;br />
&lt;a href="https://github.com/ptxmotc/Sample-code" target="_blank" rel="noopener">
PTX 官方範例程式碼 | GitHub
&lt;/a>&lt;/p>
&lt;br/>
&lt;blockquote>
&lt;p>專注你喜歡的事，就能感受到那股強大的力量。&lt;/p>
&lt;p align="right">—— 戴資穎 (台灣羽球國手)&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/ptx_python.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/ptx_python_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>PTX</category><category>API</category><category>交通</category><category>公共運輸</category><category>Python</category><category>分享</category></item><item><title>[Python爬蟲實例] 巴哈姆特 動畫瘋：新手入門基礎網路爬蟲教學</title><link>https://blog.jiatool.com/posts/gamer_ani_spider/</link><pubDate>Sat, 11 Dec 2021 20:55:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sat, 11 Dec 2021 20:55:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/gamer_ani_spider/</guid><description>前言 這次文章比較面向網路爬蟲初學者，以爬取&amp;quot;巴哈姆特 動畫瘋 &amp;quot;的本季新番動畫資訊示範，從如何使用開發人員工具尋找網頁元素，</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>這次文章比較面向網路爬蟲初學者，以爬取&amp;quot;&lt;a href="https://ani.gamer.com.tw/" target="_blank" rel="noopener">
巴哈姆特 動畫瘋
&lt;/a>&amp;quot;的本季新番動畫資訊示範，從如何使用開發人員工具尋找網頁元素，到如何轉為可實際運作的程式碼，從頭到尾的流程。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_ani_spider/animation.jpg" alt="來源：巴哈姆特 動畫瘋" data-caption="來源：巴哈姆特 動畫瘋" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
來源：巴哈姆特 動畫瘋
&lt;/figcaption>
&lt;/figure>
&lt;p>備註：此文僅教育學習，切勿用作商業用途，個人實作皆屬個人行為，本作者不負任何法律責任。&lt;/p>
&lt;h2 id="套件">套件&lt;/h2>
&lt;p>此次 Python 網路爬蟲主要使用到的套件：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Requests [&lt;a href="https://requests.readthedocs.io/en/master/" target="_blank" rel="noopener">
Doc
&lt;/a>] [&lt;a href="https://github.com/psf/requests" target="_blank" rel="noopener">
GitHub
&lt;/a>]&lt;/p>
&lt;/li>
&lt;li>
&lt;p>BeautifulSoup [&lt;a href="https://www.crummy.com/software/BeautifulSoup/bs4/doc/" target="_blank" rel="noopener">
Doc
&lt;/a>] [&lt;a href="https://code.launchpad.net/beautifulsoup" target="_blank" rel="noopener">
Source
&lt;/a>]&lt;/p>
&lt;/li>
&lt;/ul>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="教學">教學&lt;/h2>
&lt;p>先說明本篇網路爬蟲目標，只針對較容易爬取的欄位來教學，分別是&amp;quot;動畫名稱&amp;quot;、&amp;quot;觀看人數&amp;quot;、&amp;quot;動畫集數&amp;quot;、&amp;quot;觀看連結&amp;quot;等資料，以下瀏覽器以 Chrome 版本 96.0.4664.45 示範。&lt;/p>
&lt;p>來到 &amp;quot;&lt;a href="https://ani.gamer.com.tw/" target="_blank" rel="noopener">
巴哈姆特 動畫瘋
&lt;/a>&amp;quot; 網頁後打開&amp;quot;開發人員工具&amp;quot; (F12 或 Ctrl + Shift + i)。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_ani_spider/gamer_ani_page.jpg" alt="巴哈姆特 動畫瘋 網頁" data-caption="巴哈姆特 動畫瘋 網頁" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
巴哈姆特 動畫瘋 網頁
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;br/>
&lt;h3 id="網頁元素架構">網頁元素架構&lt;/h3>
&lt;p>想要知道網頁上的資料在哪個元素中，有個好用的選擇工具，位於開發人員工具地左上角。&lt;br />
點它一下後，可以直接在網頁上點擊想要查看的區塊，Elements(元素)視窗裡的程式碼會自動跳到相應的地方。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_ani_spider/select_tool.png" alt="開發人員工具內的選擇工具" data-caption="開發人員工具內的選擇工具" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
開發人員工具內的選擇工具
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;br/>
&lt;p>但在找元素的定位之前，我們先來觀察元素的架構，這也會影響到後續程式碼的流程。&lt;/p>
&lt;p>搭配以上說的&amp;quot;選擇工具&amp;quot;(Ctrl + Shift + C)，可以看出這部分的架構如下圖：&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_ani_spider/page_structure.jpg" alt="網頁元素架構" data-caption="網頁元素架構" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
網頁元素架構
&lt;/figcaption>
&lt;/figure>
&lt;p>外圈會有一個 &lt;code>&amp;lt;div class=&amp;quot;newanime-block&amp;quot;&amp;gt;&lt;/code> 開頭，一直到下面以 &lt;code>&amp;lt;/div&amp;gt;&lt;/code> 結尾 (因為太長，所以圖片沒有擷取到結尾)，圖片中我以黃色方框表示。&lt;/p>
&lt;p>而裡面每一部動畫的元素我以綠色方框表示，一個黃色框底下包含許多綠色框(動畫資訊)，在右邊開發人員工具中我以灰色框所圈起來的，每一個都對應著左邊網頁中一部動畫資訊。&lt;/p>
&lt;br/>
&lt;br/>
&lt;h3 id="發出請求">發出請求&lt;/h3>
&lt;p>好，來寫網路爬蟲程式吧~💪&lt;br />
從請求網頁開始。&lt;/p>
&lt;br/>
&lt;p>首先引入 requests 套件，來對&amp;quot;巴哈姆特 動畫瘋&amp;quot;網址(&lt;code>https://ani.gamer.com.tw/&lt;/code>)發出 GET 請求，再從它回傳的狀態碼(HTTP Status Code)來判斷請求是否成功。&lt;/p>
&lt;p>* 我們網路爬蟲最常使用的 HTTP 請求方法為 &amp;quot;GET&amp;quot; 和 &amp;quot;POST&amp;quot;，兩者介紹與差異可以參考別人撰寫的文章：&lt;a href="https://totoroliu.medium.com/http-post-%E5%92%8C-get-%E5%B7%AE%E7%95%B0-928829d29914" target="_blank" rel="noopener">
http Post 和 Get 差異 | Medium
&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;https://ani.gamer.com.tw/&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">200&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;請求成功：{r.status_code}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;請求失敗：{r.status_code}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>執行後&amp;hellip;&amp;hellip;ㄟㄟ？！&lt;br />
為什麼請求失敗，回傳的狀態碼是&amp;quot;503&amp;quot;，不過使用瀏覽器網頁卻是正常顯示的。&lt;br />
(各個狀態所代表的意思：&lt;a href="https://zh.wikipedia.org/wiki/HTTP%e7%8b%80%e6%85%8b%e7%a2%bc" target="_blank" rel="noopener">
HTTP狀態碼 | 維基百科
&lt;/a>)&lt;/p>
&lt;p>很有可能是我們送出的請求中缺少某些要素(資料)，以至於動畫瘋的伺服器不回傳資料給我們，&lt;br />
最一開始，可以先加上 Headers 內的 &amp;quot;User-Agent&amp;quot; 試試：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;User-Agent&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;https://ani.gamer.com.tw/&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">200&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;請求成功：{r.status_code}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;請求失敗：{r.status_code}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>果然，這樣再執行程式碼就請求成功了~&lt;/p>
&lt;br/>
&lt;p>你可能會想問「User-Agent」是什麼？ 從哪來的？&lt;/p>
&lt;p>「User-Agent」(使用者代理)簡單來說是要&amp;quot;自我介紹&amp;quot;，說明自己是誰、版本號多少、使用什麼作業系統這類資訊。&lt;br />
例如我這邊是使用 Chrome 瀏覽器、版本為 96.0.4664.45、作業系統為 Windows 10 64 位元。如果你是使用 Android 或 iOS 系統的手機，那它送出去的 User-Agent 也會有所不同。&lt;/p>
&lt;p>「User-Agent」算是一個讓伺服器最簡易判斷送出請求的人是誰，是電腦瀏覽器？是手機瀏覽器？還是Google爬蟲？&lt;br />
不過就像我們上面程式操作的，它也很容易自己去更改。&lt;/p>
&lt;p>* &lt;a href="https://progressbar.tw/posts/234" target="_blank" rel="noopener">
要怎麼辨別使用者瀏覽者用哪種瀏覽器呢？用UserAgent是最簡單的方式喔！
&lt;/a>&lt;/p>
&lt;br/>
&lt;p>那該如何取得請求的「User-Agent」？&lt;/p>
&lt;p>在開發人員工具視窗裡切換到 &amp;quot;Network&amp;quot; 分頁，篩選確認是在 &amp;quot;All&amp;quot;，重整網頁(F5)，這樣它才會抓到我們送出的請求。&lt;br />
然後會在下方列表的最上面看到 &amp;quot;ani.gamer.com.tw&amp;quot; 的請求。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_ani_spider/network.png" alt="開發人員工具 &amp;gt; Network" data-caption="開發人員工具 &amp;gt; Network" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
開發人員工具 &amp;gt; Network
&lt;/figcaption>
&lt;/figure>
&lt;p>點擊 &amp;quot;ani.gamer.com.tw&amp;quot; 請求後，在右邊出現的視窗中切到 &amp;quot;Headers&amp;quot; 分頁 (正常來說預設就是&amp;quot;Headers&amp;quot;分頁)。&lt;br />
找到在 Request Headers 底下的 &amp;quot;user-agent&amp;quot; 欄位，這個數值就是你瀏覽器發出請求時，所包含的 User-Agent。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_ani_spider/headers.png" alt="Headers &amp;gt; Request Headers &amp;gt; user-agent" data-caption="Headers &amp;gt; Request Headers &amp;gt; user-agent" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
Headers &amp;gt; Request Headers &amp;gt; user-agent
&lt;/figcaption>
&lt;/figure>
&lt;p>* 此圖片是後來截圖的，所以瀏覽器版本號有些不同。&lt;/p>
&lt;br/>
&lt;!--adsense-->
&lt;h3 id="解析網頁元素">解析網頁元素&lt;/h3>
&lt;p>我們在請求成功後，將網頁原始碼顯示出來看看：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;p>接下來要從網頁原始碼解析出我們要的資料，雖然你可以直接從網頁原始碼&amp;quot;字串&amp;quot;切出想要的資料，但光想就知道很麻煩。&lt;/p>
&lt;p>網頁原始碼 HTML 是有一定的規則，依循此規則架構可以容易地取出資料。我們將藉助 BeautifulSoup 套件，解析 HTML 文件，方便我們提取資料。&lt;/p>
&lt;p>一樣要先將套件引入：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="kn">from&lt;/span> &lt;span class="nn">bs4&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">BeautifulSoup&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>* BeautifulSoup 基礎常用說明參考：&lt;a href="https://blog.gtwang.org/programming/python-beautiful-soup-module-scrape-web-pages-tutorial/" target="_blank" rel="noopener">
Python 使用 Beautiful Soup 抓取與解析網頁資料，開發網路爬蟲教學
&lt;/a>&lt;/p>
&lt;br/>
&lt;p>將剛剛取得的網頁原始碼傳入，並選擇使用內建的 &lt;code>html.parser&lt;/code> 解析器：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="n">soup&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">BeautifulSoup&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;html.parser&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;br/>
&lt;p>要抓取元素，需要給程式依據，讓它可以正確定位到你想抓取哪個元素。&lt;/p>
&lt;p>那照上面的 &amp;quot;網頁元素架構&amp;quot; 圖片所示，動畫資料的元素都被包在 &lt;code>&amp;lt;div class=&amp;quot;newanime-block&amp;quot;&amp;gt;&lt;/code> 之中，是不是只要抓 class 等於 &lt;code>newanime-block&lt;/code> 就完事了呢？&lt;/p>
&lt;br/>
&lt;p>可惜這樣會有個小問題，在此網頁中 class 等於 &lt;code>newanime-block&lt;/code> 的元素有兩個啊 😕&lt;/p>
&lt;p>怎麼知道的？！&lt;br />
在 &amp;quot;開發人員工具&amp;quot; 的 &amp;quot;Elements&amp;quot; 分頁中開啟搜尋框(鍵盤 Ctrl + F)，並輸入 &lt;code>.newanime-block&lt;/code> (注意前面有小數點)。&lt;br />
&lt;code>.newanime-block&lt;/code> 等於告訴它我要尋找 class 等於 &lt;code>newanime-block&lt;/code> 的元素，可以看見它找到兩個符合此條件的元素。&lt;/p>
&lt;p>* 你可能還不清楚如何寫 CSS Selector (選擇器)，之前我整理一篇常用的幾種寫法，可以搭配練習：&lt;br />
&lt;a href="https://blog.jiatool.com/posts/sorted-out-css-selector/" target="_blank" rel="noopener">
常用網頁 CSS Selector (選擇器)取得元素，搭配 Python BeautifulSoup 套件
&lt;/a>&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_ani_spider/elements_search.png" alt="&amp;#34;Elements&amp;#34; 分頁中搜尋" data-caption="&amp;#34;Elements&amp;#34; 分頁中搜尋" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='750px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:750px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;Elements&amp;#34; 分頁中搜尋
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>原來這兩個分別是代表 &amp;quot;本季新番&amp;quot; 和 &amp;quot;週期表&amp;quot; 的動畫。&lt;/p>
&lt;p>從 &lt;code>&amp;lt;div class=&amp;quot;newanime-block&amp;quot;&amp;gt;&lt;/code> 再往上看一層，會發覺兩者有不同之處(用來定位元素)，一個 class 有 &lt;code>timeline-ver&lt;/code>，另一個是 &lt;code>normal-ver&lt;/code>，因此我們可以改用 &lt;code>.timeline-ver &amp;gt; .newanime-block&lt;/code> 來更準確定位，也就是跟程式說 &amp;quot;我要抓取 class 有包含 timeline-ver 元素底下一層 class 有包含 newanime-block 的元素&amp;quot;。&lt;/p>
&lt;p>* class 不一定要全部都寫，主要找出它代表性的、盡量不要跟別的元素重複的 class 即可。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_ani_spider/timeline_normal_ver.jpg" alt="網頁元素架構" data-caption="網頁元素架構" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
網頁元素架構
&lt;/figcaption>
&lt;/figure>
&lt;p>程式中以這樣撰寫：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="n">newanime_item&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.timeline-ver &amp;gt; .newanime-block&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;p>再往下一層可抓到每一個動畫資料元素，我就以 &lt;code>newanime-date-area&lt;/code> 這個 class 來定位。&lt;br />
每個綠框代表一組動畫的元素。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_ani_spider/newanime_date_area.png" alt="動畫資料元素" data-caption="動畫資料元素" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
動畫資料元素
&lt;/figcaption>
&lt;/figure>
&lt;p>這邊程式碼有一些些不同，剛剛是只要抓一個元素，所以使用 &lt;code>select_one()&lt;/code>，但這邊是要抓全部的動畫元素，有很多個就必須使用 &lt;code>select()&lt;/code>，它會以&amp;quot;陣列&amp;quot;的形式回傳：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="n">anime_items&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">newanime_item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.newanime-date-area&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;p>到目前為止，程式部分如下。&lt;br />
為了察看結果，我先暫時用 &lt;code>len()&lt;/code> 來看共抓到幾組動畫元素。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="kn">from&lt;/span> &lt;span class="nn">bs4&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">BeautifulSoup&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;User-Agent&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;https://ani.gamer.com.tw/&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">200&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;請求成功：{r.status_code}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">soup&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">BeautifulSoup&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;html.parser&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">newanime_item&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.timeline-ver &amp;gt; .newanime-block&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">anime_items&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">newanime_item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.newanime-date-area&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">anime_items&lt;/span>&lt;span class="p">))&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;請求失敗：{r.status_code}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;br/>
&lt;p>終於要進入抓取 &amp;quot;動畫名稱&amp;quot;、&amp;quot;觀看人數&amp;quot;、&amp;quot;動畫集數&amp;quot;、&amp;quot;觀看連結&amp;quot; 的時候了🎉&lt;/p>
&lt;br/>
&lt;p>一樣使用&amp;quot;選擇工具&amp;quot;(Ctrl + Shift + C)輔助，觀察動畫資料元素的架構：&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_ani_spider/ani_elements.jpg" alt="動畫資料元素" data-caption="動畫資料元素" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
動畫資料元素
&lt;/figcaption>
&lt;/figure>
&lt;p>一樣像前面說明，先透過 CSS Selector (選擇器)抓到元素，再來可以使用 &lt;code>text&lt;/code> 提取文字，最後的 &lt;code>strip()&lt;/code> 只是將字串的前後空格和換行去除。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="c1"># 取得元素&lt;/span>
&lt;span class="n">anime_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">anime_item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.anime-name &amp;gt; p&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">anime_name&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;p class=&amp;#34;&amp;#34;&amp;gt;無職轉生，到了異世界就拿出真本事&amp;lt;/p&amp;gt;&lt;/span>
&lt;span class="c1"># 取得元素裡的文字&lt;/span>
&lt;span class="n">anime_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">anime_item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.anime-name &amp;gt; p&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">anime_name&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 無職轉生，到了異世界就拿出真本事&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;p>而 &amp;quot;觀看連結&amp;quot; 稍微特別一點，連結並不是以文字形式被包在元素之間，而是在元素裡的 &lt;code>href&lt;/code> 屬性，這時要透過 &lt;code>get('href')&lt;/code> 方法來取得。&lt;/p>
&lt;p>而且只有網址的後半段，所以我們要再補上前半部才完整。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_ani_spider/ani_link.png" alt="動畫觀看連結" data-caption="動畫觀看連結" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
動畫觀看連結
&lt;/figcaption>
&lt;/figure>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="n">anime_href&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">anime_item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;a.anime-card-block&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;href&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;https://ani.gamer.com.tw/&amp;#39;&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="n">anime_href&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;p>到這部分的程式碼如下：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="kn">from&lt;/span> &lt;span class="nn">bs4&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">BeautifulSoup&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;User-Agent&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;https://ani.gamer.com.tw/&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">200&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;請求成功：{r.status_code}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">soup&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">BeautifulSoup&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;html.parser&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">newanime_item&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.timeline-ver &amp;gt; .newanime-block&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">anime_items&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">newanime_item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.newanime-date-area&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 依序針對每個動畫區塊擷取資料&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">anime_item&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">anime_items&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">anime_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">anime_item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.anime-name &amp;gt; p&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">anime_name&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">anime_watch_number&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">anime_item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.anime-watch-number &amp;gt; p&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">anime_watch_number&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">anime_episode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">anime_item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.anime-episode&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">anime_episode&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">anime_href&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">anime_item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;a.anime-card-block&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;href&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;https://ani.gamer.com.tw/&amp;#39;&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="n">anime_href&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;----------&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;請求失敗：{r.status_code}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;p>好耶~ 快來執行看看~&lt;/p>
&lt;p>怎麼發生錯誤了... OAQ...&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_ani_spider/attribute_error_premium.png" alt="抓取動畫元素失敗" data-caption="抓取動畫元素失敗" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='550px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:550px;height:;"/>
&lt;figcaption style="text-align: center;">
抓取動畫元素失敗
&lt;/figcaption>
&lt;/figure>
&lt;p>檢查後發現，原來是最後這個&amp;quot;付費比例&amp;quot;區塊搞的鬼，它也同樣有 &lt;code>newanime-date-area&lt;/code> 這個 class，一樣會被抓出來，但它沒有動畫名稱，所以才會造成後續在取得文字時發生錯誤。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_ani_spider/premium_block.jpg" alt="付費比例 區塊" data-caption="付費比例 區塊" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
付費比例 區塊
&lt;/figcaption>
&lt;/figure>
&lt;p>沒關係，可以看見它有個獨特的 class &lt;code>premium-block&lt;/code>，我們程式只要使用 &lt;code>:not()&lt;/code> 將其排除即可。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="c1"># 原先寫法&lt;/span>
&lt;span class="n">anime_items&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">newanime_item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.newanime-date-area&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 改成將&amp;#34;付費比例&amp;#34;區塊排除&lt;/span>
&lt;span class="n">anime_items&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">newanime_item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.newanime-date-area:not(.premium-block)&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;br/>
&lt;p>好了，花費九牛二虎之力(?)&lt;br />
網頁中&amp;quot;動畫名稱&amp;quot;、&amp;quot;觀看人數&amp;quot;、&amp;quot;動畫集數&amp;quot;、&amp;quot;觀看連結&amp;quot;的資料都如期取得啦~👍&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_ani_spider/pekora.png" alt="兎田ぺこら" data-caption="兎田ぺこら" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='80px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:80px;height:;"/>
&lt;figcaption style="text-align: center;">
兎田ぺこら
&lt;/figcaption>
&lt;/figure>
&lt;p>最終程式碼如下：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="kn">from&lt;/span> &lt;span class="nn">bs4&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">BeautifulSoup&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;User-Agent&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;https://ani.gamer.com.tw/&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">200&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;請求成功：{r.status_code}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">soup&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">BeautifulSoup&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;html.parser&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">newanime_item&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.timeline-ver &amp;gt; .newanime-block&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">anime_items&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">newanime_item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.newanime-date-area:not(.premium-block)&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">anime_item&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">anime_items&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">anime_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">anime_item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.anime-name &amp;gt; p&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">anime_name&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">anime_watch_number&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">anime_item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.anime-watch-number &amp;gt; p&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">anime_watch_number&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">anime_episode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">anime_item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.anime-episode&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">anime_episode&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">anime_href&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">anime_item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;a.anime-card-block&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;href&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;https://ani.gamer.com.tw/&amp;#39;&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="n">anime_href&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;----------&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;請求失敗：{r.status_code}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;br/>
&lt;p>對了，動畫還有&amp;quot;日期&amp;quot;與&amp;quot;時間&amp;quot;資料，&amp;quot;時間&amp;quot;資料不難取得，和上方教學的方式一樣，不過&amp;quot;日期&amp;quot;在這邊就稍微麻煩點了，本篇文章屬於基礎教學，就先跳過它，但我會附在&amp;quot;完整程式碼&amp;quot;中。&lt;/p>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="完整程式碼">完整程式碼&lt;/h2>
&lt;p>附上完整程式碼供參考：&lt;a href="https://gist.github.com/it-jia/2631658ae0676e11ba5928e607ff1433" target="_blank" rel="noopener">
gamer_ani_spider.py | GitHub
&lt;/a>&lt;/p>
&lt;h2 id="延伸練習">延伸練習&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>你能試著抓取動畫的圖片網址嗎？ 會遇到什麼問題？ 最後如何解決？&lt;/p>
&lt;/li>
&lt;li>
&lt;p>除了&amp;quot;本季新番&amp;quot;這個畫面的資料，它還可以切換到&amp;quot;週期表&amp;quot;的畫面。&lt;br />
這邊交由你試試看，能不能藉由文章的教學，實際自己爬取資料？&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>在上方教學範例中，使用哪些 class 來定位都不是絕對，你可以嘗試不同的組合、不同的寫法。&lt;br />
從實作中摸索、犯錯後尋找解答是學習程式的一個很好的方法。&lt;/p>
&lt;br/>
&lt;p>我陸續都有在寫一些網站的&lt;a href="https://blog.jiatool.com/series/python%e7%b6%b2%e8%b7%af%e7%88%ac%e8%9f%b2%e5%af%a6%e4%be%8b/" target="_blank" rel="noopener">
Python網路爬蟲實例
&lt;/a>，如果你正好是剛開始想學爬蟲的新手、想知道某網站如何爬取資料、遇到其他問題，也歡迎在底下留言🔖，或追蹤 FB 粉專『&lt;a href="https://www.facebook.com/jiatool" target="_blank" rel="noopener">
IT空間
&lt;/a>』~ 🔔&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;blockquote>
&lt;p>我們總是在注意錯過太多，卻不注意自己擁有多少。&lt;/p>
&lt;p align="right">—— 《未聞花名》&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/gamer_ani_spider.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/gamer_ani_spider_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Python</category><category>巴哈姆特</category><category>網路爬蟲</category><category>Python網路爬蟲實例</category></item><item><title>Playwright 瀏覽器自動化工具，應用於網路爬蟲和測試</title><link>https://blog.jiatool.com/posts/playwright/</link><pubDate>Sat, 20 Nov 2021 21:00:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sat, 20 Nov 2021 21:00:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/playwright/</guid><description>前言 你還在使用 Selenium 來網路爬蟲或自動化測試嗎？或許你可以來試試另一個工具 — Playwright。 (圖片來源：Unsplash) [小廣告] 我製作了</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>你還在使用 Selenium 來網路爬蟲或自動化測試嗎？或許你可以來試試另一個工具 — Playwright。&lt;/p>
&lt;figure >
&lt;img data-src="https://images.unsplash.com/photo-1486312338219-ce68d2c6f44d?w=600&amp;amp;q=50" alt="(圖片來源：Unsplash)" data-caption="(圖片來源：Unsplash)" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
(圖片來源：Unsplash)
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;div class="alert alert-info" role="alert" data-dir="ltr">[小廣告] 我製作了一款可愛的「&lt;a href="https://blog.jiatool.com/posts/penguin_wizard_sticker">企鵝魔法師&lt;/a>」貼圖~&lt;br />
歡迎下載：&lt;a href="https://line.me/S/sticker/31703222">LINE 貼圖&lt;/a>、&lt;a href="https://t.me/addstickers/penguin_wizard">Telegram 貼圖 (免費)&lt;/a>&lt;/p>
&lt;img src="https://res.cloudinary.com/jiablog/penguin_wizard_sticker/show.png" caption="企鵝魔法師" width="600px" position="center">&lt;/div>
&lt;h2 id="playwright-套件簡介">Playwright 套件簡介&lt;/h2>
&lt;p>Playwright 是微軟 Microsoft 開發的一個開源瀏覽器自動化工具，可以選擇 Chromium、Firefox、WebKit 瀏覽器，目前有 Python、JavaScript、TypeScript、.NET、Java 的 API 可供使用。&lt;/p>
&lt;p>* 本篇文章以 Python 為範例，但各程式語言的 API 應該是差不多的。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>&lt;/th>
&lt;th>Linux&lt;/th>
&lt;th>macOS&lt;/th>
&lt;th>Windows&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Chromium 98.0.4708.0&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>WebKit 15.4&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Firefox 94.0.1&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;td>✅&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>* 此版本會持續更新，以官方文檔為主。&lt;/p>
&lt;br/>
&lt;p>Playwright 第一次輸入指令就會自動下載瀏覽器，與自己使用的瀏覽器是分開的。不用像 Selenium 要手動下載，版本更新還要去更新驅動。&lt;/p>
&lt;br/>
&lt;p>Playwright 在對元素(elements)操作之前，會自動等待元素準備完成(可見的、啟用的&amp;hellip;)，不用怕元素還沒載入就執行造成錯誤，也不需要自己加等待。&lt;/p>
&lt;p>就像省去了 Selenium 內的 WebDriverWait：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">WebDriverWait&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">driver&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timeout&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">until&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">EC&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">presence_of_element_located&lt;/span>&lt;span class="p">((&lt;/span>&lt;span class="n">By&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CSS_SELECTOR&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;#search&amp;#39;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>* 詳細可以參考官方文檔：&lt;a href="https://playwright.dev/python/docs/actionability">https://playwright.dev/python/docs/actionability&lt;/a>&lt;/p>
&lt;br/>
&lt;p>* Playwright 支援同步和異步(搭配 asyncio)，本篇文章皆使用同步來示範。&lt;br />
* Playwright 甚至能自動產生程式碼，這部分可以參考大數學堂的影片教學：&lt;a href="https://www.youtube.com/watch?v=moeAmM-7ybE" target="_blank" rel="noopener">
[爬蟲實戰] 如何不寫任何一行程式碼透過低代碼Low-Code / No-Code 工具 Playwright撰寫網頁自動化瀏覽程式
&lt;/a>&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://playwright.dev/python/" target="_blank" rel="noopener">
Playwright 官方網站
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://playwright.dev/python/docs/intro" target="_blank" rel="noopener">
Playwright 文檔
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://playwright.dev/python/docs/api/class-playwright" target="_blank" rel="noopener">
Playwright API
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/microsoft/playwright-python" target="_blank" rel="noopener">
Playwright for Python GitHub
&lt;/a>&lt;/li>
&lt;/ul>
&lt;br/>
&lt;br/>
&lt;h2 id="教學">教學&lt;/h2>
&lt;p>先來試試官方文檔內的基本程式：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="kn">from&lt;/span> &lt;span class="nn">playwright.sync_api&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">sync_playwright&lt;/span>
&lt;span class="k">with&lt;/span> &lt;span class="n">sync_playwright&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">browser&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">chromium&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">launch&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">page&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">browser&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">new_page&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">page&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">goto&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;http://playwright.dev&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">page&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">title&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="n">browser&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">close&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>首先創造一個瀏覽器實例，開新分頁，再來前往 &lt;code>http://playwright.dev&lt;/code> 網頁，並取得網頁的 title，最後關閉瀏覽器。&lt;/p>
&lt;br/>
&lt;p>它預設是以「無頭模式」啟動，但為了在寫程式時觀察它運作，我們可以先將其關閉：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">browser&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">p&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">chromium&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">launch&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">headless&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">False&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h3 id="常見的基本操作">常見的基本操作&lt;/h3>
&lt;p>以下是幾種常見的網頁基本操作：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="c1"># 點擊&lt;/span>
&lt;span class="n">page&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">click&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;div&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 輸入文字&lt;/span>
&lt;span class="n">page&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">fill&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;#search&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;query&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 複選框和單選按鈕&lt;/span>
&lt;span class="n">page&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">check&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;#agree&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 下拉選擇欄&lt;/span>
&lt;span class="n">page&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_option&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;select#colors&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;blue&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>更多進階用法與參數可參考官方文檔：&lt;/p>
&lt;ul>
&lt;li>滑鼠 Mouse：&lt;a href="https://playwright.dev/python/docs/api/class-mouse">https://playwright.dev/python/docs/api/class-mouse&lt;/a>&lt;/li>
&lt;li>鍵盤 Keyboard：&lt;a href="https://playwright.dev/python/docs/api/class-keyboard">https://playwright.dev/python/docs/api/class-keyboard&lt;/a>&lt;/li>
&lt;/ul>
&lt;br/>
&lt;h3 id="元素定位">元素定位&lt;/h3>
&lt;p>基本操作或取得元素皆使用 CSS Selector 元素定位。&lt;/p>
&lt;div class="alert alert-info" role="alert" data-dir="ltr">關於 CSS Selector (選擇器)的寫法可以參考我以前整理的文章：&lt;br />
&lt;a href="https://blog.jiatool.com/posts/sorted-out-css-selector/">常用網頁 CSS Selector (選擇器)取得元素，搭配 Python BeautifulSoup 套件&lt;/a>&lt;/div>
&lt;br/>
&lt;p>Playwright 除了有一般的 Selector 用法以外，還有個比較特別且好用的 &amp;quot;文字(text)&amp;quot; 選擇方式：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="c1"># 取得包含此段文字的元素 (不分大小寫)&lt;/span>
&lt;span class="n">page&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">click&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;text=Log in&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 取得與此段文字一模一樣的元素 (注意裡面還有引號)&lt;/span>
&lt;span class="n">page&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">click&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;text=&amp;#34;Log in&amp;#34;&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 如果要與 CSS Selector 結合，要使用以下方式&lt;/span>
&lt;span class="c1"># 概念同等於上方的 &amp;#39;text=Log in&amp;#39;，包含此段文字 (不分大小寫)&lt;/span>
&lt;span class="n">page&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">click&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;button:text(&amp;#34;Log in&amp;#34;)&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 概念同等於上方的 &amp;#39;text=&amp;#34;Log in&amp;#34;&amp;#39;，文字要完全一樣&lt;/span>
&lt;span class="n">page&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">click&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;button:text-is(&amp;#34;Log in&amp;#34;)&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 使用正則表達式&lt;/span>
&lt;span class="n">page&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">click&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;button:text-matches(&amp;#34;[+-]?&lt;/span>&lt;span class="se">\\&lt;/span>&lt;span class="s1">d+&amp;#34;)&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 還有一種是匹配內部包含文字的任何元素，可能在子元素或後代元素中&lt;/span>
&lt;span class="c1"># 例如底下會匹配 &amp;lt;article&amp;gt;&amp;lt;div&amp;gt;Playwright&amp;lt;/div&amp;gt;&amp;lt;/article&amp;gt;。&lt;/span>
&lt;span class="n">element&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">page&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">wait_for_selector&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;article:has-text(&amp;#34;Playwright&amp;#34;)&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>在文字匹配會對空格進行正規化，例如將多個空格轉換為一個，將換行符變成空格並忽略開頭和結尾的空格。&lt;/p>
&lt;p>因為這部分有多種狀況、較複雜，我只是初步嘗試，如有錯誤歡迎底下留言告知。&lt;br />
參考：&lt;a href="https://playwright.dev/python/docs/selectors/#text-selector">https://playwright.dev/python/docs/selectors/#text-selector&lt;/a>&lt;/p>
&lt;br/>
&lt;p>以及一些其他的選擇方式：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="c1"># 返回 &amp;lt;article&amp;gt; 具有 &amp;lt;div class=promo&amp;gt; 內部元素的文本內容&lt;/span>
&lt;span class="n">page&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text_content&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;article:has(div.promo)&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 僅點擊可見 class=button 的元素&lt;/span>
&lt;span class="n">page&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">click&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;.button:visible&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h3 id="選取元素">選取元素&lt;/h3>
&lt;p>如果要取得元素，可以使用：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="c1"># 取得元素&lt;/span>
&lt;span class="n">page&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">query_selector&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;#promo&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 取得元素，加入等待&lt;/span>
&lt;span class="n">page&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">wait_for_selector&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;#promo&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;p>獲取元素的文字及屬性：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="c1"># 取得元素的文字&lt;/span>
&lt;span class="n">page&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">query_selector&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;h3&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text_content&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="c1"># 取得元素的屬性(attribute)&lt;/span>
&lt;span class="n">page&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">query_selector&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;section&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_attribute&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;class&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h3 id="瀏覽器參數">瀏覽器參數&lt;/h3>
&lt;p>在教學一開始說到無頭模式，在 &lt;code>launch&lt;/code> 加入 &lt;code>headless=False&lt;/code>，它還有其他參數可以設定。&lt;br />
詳見：&lt;a href="https://playwright.dev/python/docs/api/class-browsertype#browser-type-launch">https://playwright.dev/python/docs/api/class-browsertype#browser-type-launch&lt;/a>&lt;/p>
&lt;p>像是傳遞給瀏覽器實例的附加參數，想讓它靜音就使用：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">browser&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">playwright&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">chromium&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">launch&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">args&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;--mute-audio&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1"># 靜音&lt;/span>
&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>更多 Chromium flags 的列表：&lt;a href="https://peter.sh/experiments/chromium-command-line-switches/">https://peter.sh/experiments/chromium-command-line-switches/&lt;/a>&lt;/p>
&lt;br/>
&lt;h3 id="cookies-和-local-storage">Cookies 和 Local Storage&lt;/h3>
&lt;p>儲存與載入 Cookies 和 Local Storage，可以用作保存登入狀態。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="c1"># 將存儲狀態保存到文件中&lt;/span>
&lt;span class="n">storage&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">context&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">storage_state&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">path&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;state.json&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 使用保存的存儲狀態創建新上下文(context)&lt;/span>
&lt;span class="n">context&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">browser&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">new_context&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">storage_state&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;state.json&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;!--adsense-->
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>它還有個 GUI 工具 Trace Viewer，可以在程式執行後幫助探索操作過程，感覺非常的厲害，但這部分我就還沒嘗試過，有興趣可以參考：&lt;a href="https://playwright.dev/python/docs/trace-viewer">https://playwright.dev/python/docs/trace-viewer&lt;/a>&lt;/p>
&lt;br/>
&lt;p>Playwright 相比 Selenium 來說是比較新出來的工具(不過都已經是正式版了)，許多功能更好用，如果你原先是使用 Selenium 來寫網路爬蟲或做自動化測試，或許可以試試 Playwright，搞不好你就會愛上囉。😆&lt;/p>
&lt;br/>
&lt;p>歡迎追蹤『&lt;a href="https://www.facebook.com/jiatool" target="_blank" rel="noopener">
IT空間
&lt;/a>』FB 粉專，取得最新發文通知🔔&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://playwright.dev/python/" target="_blank" rel="noopener">
Playwright 官方網站
&lt;/a>&lt;br />
&lt;a href="https://playwright.dev/python/docs/intro" target="_blank" rel="noopener">
Playwright 文檔
&lt;/a>&lt;br />
&lt;a href="https://playwright.dev/python/docs/api/class-playwright" target="_blank" rel="noopener">
Playwright API
&lt;/a>&lt;br />
&lt;a href="https://github.com/microsoft/playwright-python" target="_blank" rel="noopener">
Playwright for Python GitHub
&lt;/a>&lt;/p>
&lt;br/>
&lt;blockquote>
&lt;p>對於自己想做的事，就放手去挑戰吧！不是因為覺得能成功就去做，而是發自內心的想要嘗試看看，這樣不管結果如何，自己都不會後悔。&lt;/p>
&lt;p align="right">—— 鈴木一朗 (棒球選手)&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/playwright.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/playwright_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Playwright</category><category>瀏覽器</category><category>自動化</category><category>套件</category><category>Python</category><category>分享</category><category>Python套件</category></item><item><title>FinMind API 取得"台股、匯率、黃金"等金融相關資料</title><link>https://blog.jiatool.com/posts/stock_finmind/</link><pubDate>Sun, 17 Oct 2021 20:40:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sun, 17 Oct 2021 20:40:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/stock_finmind/</guid><description>前言 許多人接觸到 Python，開始學習&amp;quot;網路爬蟲 &amp;quot;、&amp;quot;資料分析&amp;quot;、&amp;quot;機器學習&amp;quot;，</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>許多人接觸到 Python，開始學習&amp;quot;&lt;a href="https://blog.jiatool.com/categories/%e7%b6%b2%e8%b7%af%e7%88%ac%e8%9f%b2/" target="_blank" rel="noopener">
網路爬蟲
&lt;/a>&amp;quot;、&amp;quot;資料分析&amp;quot;、&amp;quot;機器學習&amp;quot;，有一部分的人是因為「股票」。但要自己爬取資料確實有點麻煩，而且不同網站可能還有反爬蟲的機制，這對於想要資料來做資料分析、預測股價的人來說，可能就是一個卡在前面的阻礙。&lt;/p>
&lt;p>之前我發現一個 FinMind API，主要以台股為主，提供很多項的金融開源數據，方便讓我們來使用。&lt;/p>
&lt;p>本篇文章會挑幾項功能來說明，以及 Python 範例程式碼。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/stock_finmind/chart.jpg" alt="(圖片來源：Unsplash)" data-caption="(圖片來源：Unsplash)" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
(圖片來源：Unsplash)
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="finmind-套件簡介">FinMind 套件簡介&lt;/h2>
&lt;p>FinMind 提供以台股為主，超過 50 種金融相關數據資料，除了 API 可以取得資料、回測、繪製 k 線圖、儀表板，也提供網頁版的操作介面、策略分析與資料集下載功能。&lt;/p>
&lt;p>因為是透過 API 串接，不限制程式，你想要使用 Python、JavaScript、PHP、C++、Java、Ruby&amp;hellip;&amp;hellip;都可，或直接透過它的官網下載資料，對於想要做大數據、資料分析、預測股價的人來說，應該算是一個很方便的工具。&lt;/p>
&lt;br/>
&lt;p>從官方 API 文檔可以看到大概有以下資料：&lt;/p>
&lt;blockquote>
&lt;p>技術面 : 台股股價 daily、歷史 tick 逐筆交易、PER、PBR、每5秒委託成交統計、台股加權指數。&lt;br />
基本面 : 綜合損益表、現金流量表、資產負債表、股利政策表、除權除息結果表、月營收。&lt;br />
籌碼面 : 外資持股、股權分散表、融資融券、三大法人買賣、借券成交明細。&lt;br />
消息面 : 台股相關新聞。&lt;br />
衍生性商品 : 期貨、選擇權 daily data、交易明細、期貨三大法人買賣，期貨各卷商每日交易、選擇權各卷商每日交易。&lt;br />
國際市場 : 美股股價 daily、minute、美國債券殖利率、貨幣發行量(美國)、黃金價格、原油價格、G8 央行利率、G8 匯率、&lt;/p>
&lt;/blockquote>
&lt;p>ℹ 但比較可惜的一點是目前「不提供即時資料」，看文檔的說明是說由於資料源問題，移除即時報價：&lt;a href="https://finmind.github.io/WhatIsNew/">https://finmind.github.io/WhatIsNew/&lt;/a>&lt;/p>
&lt;br/>
&lt;br/>
&lt;h2 id="教學">教學&lt;/h2>
&lt;p>&lt;a href="https://finmind.github.io" target="_blank" rel="noopener">
FinMind API 文檔
&lt;/a> 內都有簡單的程式碼範例，這邊我就挑其中的五種來示範說明。&lt;/p>
&lt;p>程式一開始，先將需要的套件匯入，&lt;code>pandas&lt;/code> 不一定要有(這裡只是拿來方便看資料)：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">pandas&lt;/span> &lt;span class="kn">as&lt;/span> &lt;span class="nn">pd&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h3 id="股價日成交資訊">股價日成交資訊&lt;/h3>
&lt;p>這項資料就是臺灣證交所的&lt;a href="https://www.twse.com.tw/zh/page/trading/exchange/STOCK_DAY.html" target="_blank" rel="noopener">
個股日成交資訊
&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;https://api.finmindtrade.com/api/v4/data&amp;#34;&lt;/span>
&lt;span class="n">parameter&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;dataset&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;TaiwanStockPrice&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;data_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2330&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;start_date&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2021-09-13&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;end_date&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2021-09-17&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">parameter&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">stock_deal_info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;data&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">stock_deal_info&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>輸出結果如下：&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/stock_finmind/output01.png" alt="股價日成交資訊 輸出結果" data-caption="股價日成交資訊 輸出結果" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
股價日成交資訊 輸出結果
&lt;/figcaption>
&lt;/figure>
&lt;p>欄位依序代表：&amp;ldquo;日期&amp;rdquo;、&amp;ldquo;股票代碼&amp;rdquo;、&amp;ldquo;成交股數&amp;rdquo;、&amp;ldquo;成交金額&amp;rdquo;、&amp;ldquo;開盤價&amp;rdquo;、&amp;ldquo;最高價&amp;rdquo;、&amp;ldquo;最低價&amp;rdquo;、&amp;ldquo;收盤價&amp;rdquo;、&amp;ldquo;漲跌價差&amp;rdquo;、&amp;ldquo;成交筆數&amp;rdquo;&lt;/p>
&lt;br/>
&lt;h3 id="股票當日逐筆成交資訊">股票當日逐筆成交資訊&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;https://api.finmindtrade.com/api/v4/data&amp;#34;&lt;/span>
&lt;span class="n">parameter&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;dataset&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;TaiwanStockPriceTick&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;data_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2330&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;start_date&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2021-09-27&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">parameter&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">stock_history_info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;data&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">stock_history_info&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tail&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="c1"># 顯示最後五筆資料&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>輸出結果如下：&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/stock_finmind/output02.png" alt="股票當日逐筆成交資訊 輸出結果" data-caption="股票當日逐筆成交資訊 輸出結果" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='550px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:550px;height:;"/>
&lt;figcaption style="text-align: center;">
股票當日逐筆成交資訊 輸出結果
&lt;/figcaption>
&lt;/figure>
&lt;p>欄位依序代表：&amp;ldquo;日期&amp;rdquo;、&amp;ldquo;股票代碼&amp;rdquo;、&amp;ldquo;成交金額&amp;rdquo;、&amp;ldquo;成交量&amp;rdquo;、&amp;ldquo;時間&amp;rdquo;、&amp;ldquo;漲跌(1:漲；2跌)&amp;rdquo;&lt;/p>
&lt;br/>
&lt;h3 id="股票綜合損益表">股票綜合損益表&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;https://api.finmindtrade.com/api/v4/data&amp;#34;&lt;/span>
&lt;span class="n">parameter&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;dataset&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;TaiwanStockFinancialStatements&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;data_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2330&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;start_date&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2021-06-01&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;end_date&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2021-09-01&amp;#34;&lt;/span> &lt;span class="c1"># 不加則抓到現在日期&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">parameter&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">stock_income_statement&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;data&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">stock_income_statement&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>輸出結果如下：&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/stock_finmind/output03.png" alt="股票綜合損益表 輸出結果" data-caption="股票綜合損益表 輸出結果" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='750px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:750px;height:;"/>
&lt;figcaption style="text-align: center;">
股票綜合損益表 輸出結果
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h3 id="股利政策表">股利政策表&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;https://api.finmindtrade.com/api/v4/data&amp;#34;&lt;/span>
&lt;span class="n">parameter&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;dataset&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;TaiwanStockDividend&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;data_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2330&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;start_date&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2021-01-01&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">parameter&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">stock_dividend&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;data&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">stock_dividend&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">head&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="c1"># 顯示前五筆資料&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>輸出結果如下：&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/stock_finmind/output04.png" alt="股利政策表 輸出結果" data-caption="股利政策表 輸出結果" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='750px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:750px;height:;"/>
&lt;figcaption style="text-align: center;">
股利政策表 輸出結果
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;h3 id="外幣對台幣匯率">外幣對台幣匯率&lt;/h3>
&lt;p>共有 19 種幣別與新臺幣(TWD)的匯率，資料來源為台灣銀行，應該就是&lt;a href="https://rate.bot.com.tw/xrt" target="_blank" rel="noopener">
此網頁
&lt;/a>。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;https://api.finmindtrade.com/api/v4/data&amp;#34;&lt;/span>
&lt;span class="n">parameter&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;dataset&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;TaiwanExchangeRate&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;data_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;USD&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;start_date&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2021-01-01&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">parameter&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">exchange_rate&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;data&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">exchange_rate&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tail&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="c1"># 顯示最後五筆資料&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>輸出結果如下：&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/stock_finmind/output05.png" alt="外幣對台幣匯率 輸出結果" data-caption="外幣對台幣匯率 輸出結果" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='550px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:550px;height:;"/>
&lt;figcaption style="text-align: center;">
外幣對台幣匯率 輸出結果
&lt;/figcaption>
&lt;/figure>
&lt;p>欄位依序代表：&amp;ldquo;日期&amp;rdquo;、&amp;ldquo;貨幣&amp;rdquo;、&amp;ldquo;現金匯率&amp;gt;銀行買入&amp;rdquo;、&amp;ldquo;現金匯率&amp;gt;銀行賣出&amp;rdquo;、&amp;ldquo;即期匯率&amp;gt;銀行買入&amp;rdquo;、&amp;ldquo;即期匯率&amp;gt;銀行賣出&amp;rdquo;&lt;/p>
&lt;br/>
&lt;br/>
&lt;h2 id="範例程式碼">範例程式碼&lt;/h2>
&lt;p>我將以上功能包裝成 class 的完整範例程式碼，附上給需要的人參考。&lt;/p>
&lt;p>GitHub Gist：&lt;a href="https://gist.github.com/it-jia/9ca6d3e6922a6804d8ff0a65902d925a" target="_blank" rel="noopener">
stock_finmind.py
&lt;/a>&lt;/p>
&lt;br/>
&lt;br/>
&lt;h2 id="流量限制--會員機制">流量限制 &amp;amp; 會員機制&lt;/h2>
&lt;p>FinMind API 有流量限制，每小時最多 300 次請求，如果註冊成為會員(免費)，則提升至 600 次 / 小時。&lt;/p>
&lt;p>另外還有兩種付款的會員，除了差在每小時的請求限制外，某些功能只有付費會員能使用，例如一次拿特定日期中全部股票的資料。&lt;/p>
&lt;p>更多詳細會員機制的 &amp;quot;贊助方案&amp;quot; 參考官網說明：&lt;a href="https://finmindtrade.com/analysis/#/Sponsor/sponsor">https://finmindtrade.com/analysis/#/Sponsor/sponsor&lt;/a>。&lt;/p>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>以上是直接對 API 請求，如果你是使用 Python，還有官方包裝好的套件(&lt;a href="https://github.com/FinMind/FinMind/" target="_blank" rel="noopener">
GitHub
&lt;/a>)，還幫你寫好幾項量化工具 (回測、K 線、客製化看盤儀表板) 可方便使用。&lt;/p>
&lt;p>更多其他資料或範例，參考 &lt;a href="https://finmind.github.io" target="_blank" rel="noopener">
FinMind API 官方文檔
&lt;/a>。&lt;/p>
&lt;br/>
&lt;p>除了本篇介紹的 FinMind，還有其他許多股票相關的套件可以嘗試：&lt;/p>
&lt;ul>
&lt;li>twstock &lt;a href="https://github.com/mlouielu/twstock">https://github.com/mlouielu/twstock&lt;/a>&lt;/li>
&lt;li>yahooquery &lt;a href="https://github.com/dpguthrie/yahooquery">https://github.com/dpguthrie/yahooquery&lt;/a>&lt;/li>
&lt;li>pandas-datareader &lt;a href="https://github.com/pydata/pandas-datareader">https://github.com/pydata/pandas-datareader&lt;/a>&lt;/li>
&lt;/ul>
&lt;br/>
&lt;p>歡迎追蹤『&lt;a href="https://www.facebook.com/jiatool" target="_blank" rel="noopener">
IT空間
&lt;/a>』FB 粉專，取得最新發文通知🔔&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://finmindtrade.com/" target="_blank" rel="noopener">
FinMind 官方網站
&lt;/a>&lt;br />
&lt;a href="https://finmind.github.io" target="_blank" rel="noopener">
FinMind API 文檔
&lt;/a>&lt;br />
&lt;a href="https://github.com/FinMind/FinMind/" target="_blank" rel="noopener">
FinMind GitHub
&lt;/a>&lt;/p>
&lt;br/>
&lt;blockquote>
&lt;p>People at work, money at work.&lt;br />
人可以工作，錢也可以幹活。&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/stock_finmind.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/stock_finmind_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Python</category><category>股票</category><category>套件</category><category>分享</category><category>Python套件</category></item><item><title>[Python爬蟲實例] 104人力銀行：抓取更詳細的職缺資訊，搶先別人一步收到通知！</title><link>https://blog.jiatool.com/posts/job104_spider/</link><pubDate>Sat, 07 Aug 2021 20:30:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Wed, 08 Dec 2021 20:40:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/job104_spider/</guid><description>前言 最近這兩年受到疫情的衝擊，不少人遭到公司裁員，接下來可能就該思考尋找下份工作了。 台灣老字號、最大的人力銀行—104人力銀行 ，我們來看看其</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>最近這兩年受到疫情的衝擊，不少人遭到公司裁員，接下來可能就該思考尋找下份工作了。&lt;/p>
&lt;p>台灣老字號、最大的人力銀行—&lt;a href="https://www.104.com.tw/" target="_blank" rel="noopener">
104人力銀行
&lt;/a>，我們來看看其網頁是如何向後端請求職缺資料，實際用 Python 來在 104 上搜尋職缺、查看職缺詳細資料。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/job104_spider/plan.jpg" alt="來源：Unsplash" data-caption="來源：Unsplash" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
來源：Unsplash
&lt;/figcaption>
&lt;/figure>
&lt;p>備註：此文僅教育學習，切勿用作商業用途，個人實作皆屬個人行為，本作者不負任何法律責任。&lt;/p>
&lt;h2 id="套件">套件&lt;/h2>
&lt;p>此次 Python 爬蟲主要使用到的套件：&lt;/p>
&lt;ul>
&lt;li>Requests [&lt;a href="https://requests.readthedocs.io/en/master/" target="_blank" rel="noopener">
Doc
&lt;/a>] [&lt;a href="https://github.com/psf/requests" target="_blank" rel="noopener">
GitHub
&lt;/a>]&lt;/li>
&lt;/ul>
&lt;p>安裝&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">pip install requests
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;!--adsense-->
&lt;h2 id="搜尋職缺">搜尋職缺&lt;/h2>
&lt;p>當在104人力銀行網頁上方，輸入職缺的篩選條件後搜尋，下方會顯示出搜尋結果，中間也有許多篩選條件、排序方式供我們使用。&lt;/p>
&lt;p>我們來找找&amp;quot;python&amp;quot;在&amp;quot;台北市&amp;quot;內現在有哪些職缺吧~&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/job104_spider/search.jpg" alt="搜尋職缺 104人力銀行" data-caption="搜尋職缺 104人力銀行" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
搜尋職缺 104人力銀行
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="請求路徑與參數">請求路徑與參數&lt;/h3>
&lt;p>跟以前的步驟一樣，一開始先打開瀏覽器的 &lt;strong>開發人員工具&lt;/strong> (F12 或 Ctrl + Shift + i) &amp;gt; &lt;strong>Network&lt;/strong>(網路) &amp;gt; &lt;strong>XHR&lt;/strong> 分頁，找找網頁有沒有透過動態載入的方式請求職缺資料。&lt;/p>
&lt;p>此時重新整理(F5)網頁，好像沒看見有關職缺資料的請求。&lt;br />
先別放棄，可以往下滾頁面或更改篩選條件，有了！發現到一個 list 開頭的請求，包含著職缺相關資料。&lt;/p>
&lt;p>* 一開始點搜尋、網頁第一次載入卻沒有職缺的請求，應該是因為它已經崁入在網頁內一起傳送過來顯示了。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/job104_spider/search_xhr.jpg" alt="搜尋職缺請求 104人力銀行" data-caption="搜尋職缺請求 104人力銀行" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
搜尋職缺請求 104人力銀行
&lt;/figcaption>
&lt;/figure>
&lt;p>切回到 &lt;strong>Headers&lt;/strong> 查看請求的方式與參數。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/job104_spider/search_request.png" alt="&amp;#34;搜尋職缺&amp;#34;請求的方式與參數" data-caption="&amp;#34;搜尋職缺&amp;#34;請求的方式與參數" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;搜尋職缺&amp;#34;請求的方式與參數
&lt;/figcaption>
&lt;/figure>
&lt;p>並且在用程式測試此請求時，發現還要帶上 Headers 內的 &lt;code>Referer&lt;/code> 參數，才可正常取得資料。&lt;/p>
&lt;p>將其整理出來，相關參數如下：&lt;br />
&lt;div class="box">&lt;p>Request URL：&lt;code>https://www.104.com.tw/jobs/search/list&lt;/code>&lt;br />
Request Methon：&lt;code>GET&lt;/code>&lt;br />
Headers Referer：&lt;code>https://www.104.com.tw/jobs/search/&lt;/code>&lt;/p>
&lt;p>Query String Parameters：&lt;/p>
&lt;pre>&lt;code>ro: 0
kwop: 7
keyword: python
expansionType: area,spec,com,job,wf,wktm
area: 6001001000
order: 1
asc: 0
page: 1
mode: s
jobsource: 2018indexpoc
&lt;/code>&lt;/pre>&lt;/div>&lt;/p>
&lt;br/>
&lt;p>請求網址後方代的參數有很多，代表我們對職缺的篩選條件與排序條件，經過我的實測整理出以下。&lt;/p>
&lt;h4 id="篩選條件">篩選條件&lt;/h4>
&lt;p>某些條件可以多選(使用 &lt;code>,&lt;/code> 連接)，某些條件只能單選。&lt;br />
例如我要查詢&amp;quot;台北市&amp;quot;與&amp;quot;新北市&amp;quot;的職缺，就需要帶上 &lt;code>area=6001001000,6001002000&lt;/code>。&lt;/p>
&lt;ul>
&lt;li>
&lt;p>頁數 &lt;code>page&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>關鍵字 &lt;code>keyword&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>地區 &lt;code>area&lt;/code>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>地區&lt;/th>
&lt;th>數值&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>台北市&lt;/td>
&lt;td>6001001000&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>新北市&lt;/td>
&lt;td>6001002000&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>桃園市&lt;/td>
&lt;td>6001005000&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>台中市&lt;/td>
&lt;td>6001008000&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>彰化縣&lt;/td>
&lt;td>6001010000&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>台南市&lt;/td>
&lt;td>6001014000&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>高雄市&lt;/td>
&lt;td>6001016000&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;ul>
&lt;li>上班時段 &lt;code>s9&lt;/code>&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>上班時段&lt;/th>
&lt;th>數值&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>日班&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>夜班&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>大夜班&lt;/td>
&lt;td>4&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>假日班&lt;/td>
&lt;td>8&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;ul>
&lt;li>是否輪班 &lt;code>s5&lt;/code>&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>是否輪班&lt;/th>
&lt;th>數值&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>不需輪班&lt;/td>
&lt;td>0&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>輪班&lt;/td>
&lt;td>256&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;ul>
&lt;li>休假制度 &lt;code>wktm&lt;/code>&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>休假制度&lt;/th>
&lt;th>數值&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>沒有週休二日&lt;/td>
&lt;td>0&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>週休二日&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;ul>
&lt;li>更新日期 &lt;code>isnew&lt;/code>&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>更新日期&lt;/th>
&lt;th>數值&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>本日最新&lt;/td>
&lt;td>0&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>三日內&lt;/td>
&lt;td>3&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>一週內&lt;/td>
&lt;td>7&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>兩週內&lt;/td>
&lt;td>14&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>一個月內&lt;/td>
&lt;td>30&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;ul>
&lt;li>經歷要求 &lt;code>jobexp&lt;/code>&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>經歷要求&lt;/th>
&lt;th>數值&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>1 年以下&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>1-3 年&lt;/td>
&lt;td>3&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>3-5 年&lt;/td>
&lt;td>5&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>5-10 年&lt;/td>
&lt;td>10&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>10 年以上&lt;/td>
&lt;td>99&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;ul>
&lt;li>科技園區 &lt;code>newZone&lt;/code>&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>科技園區&lt;/th>
&lt;th>數值&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>竹科&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>中科&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>南科&lt;/td>
&lt;td>3&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>內湖&lt;/td>
&lt;td>4&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>南港&lt;/td>
&lt;td>5&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;ul>
&lt;li>公司類型 &lt;code>zone&lt;/code>&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>公司類型&lt;/th>
&lt;th>數值&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>上市上櫃&lt;/td>
&lt;td>16&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>外商一般&lt;/td>
&lt;td>5&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>外商資訊&lt;/td>
&lt;td>4&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;ul>
&lt;li>福利制度 &lt;code>wf&lt;/code>&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>福利制度&lt;/th>
&lt;th>數值&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>年終獎金&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>三節獎金&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>員工旅遊&lt;/td>
&lt;td>3&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>分紅配股&lt;/td>
&lt;td>4&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>設施福利&lt;/td>
&lt;td>5&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>休假福利&lt;/td>
&lt;td>6&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>津貼/補助&lt;/td>
&lt;td>7&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>彈性上下班&lt;/td>
&lt;td>8&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>健康檢查&lt;/td>
&lt;td>9&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>團體保險&lt;/td>
&lt;td>10&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;ul>
&lt;li>學歷要求 &lt;code>edu&lt;/code>&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>學歷要求&lt;/th>
&lt;th>數值&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>高中職以下&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>高中職&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>專科&lt;/td>
&lt;td>3&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>大學&lt;/td>
&lt;td>4&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>碩士&lt;/td>
&lt;td>5&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>博士&lt;/td>
&lt;td>6&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;ul>
&lt;li>上班型態 &lt;code>remoteWork&lt;/code>&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>上班型態&lt;/th>
&lt;th>數值&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>完全遠端&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>部分遠端&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;ul>
&lt;li>
&lt;p>排除關鍵字 &lt;code>excludeJobKeyword&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>只搜尋職務名稱 &lt;code>kwop&lt;/code>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>只搜尋職務名稱&lt;/th>
&lt;th>數值&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>只搜尋職務名稱&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;br/>
&lt;h4 id="排序條件">排序條件&lt;/h4>
&lt;ul>
&lt;li>排序依據 &lt;code>order&lt;/code>&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>排序依據&lt;/th>
&lt;th>數值&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>符合度&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>日期&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>經歷&lt;/td>
&lt;td>3&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>學歷&lt;/td>
&lt;td>4&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>應徵人數&lt;/td>
&lt;td>7&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>待遇&lt;/td>
&lt;td>13&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;ul>
&lt;li>排序順序 &lt;code>asc&lt;/code>&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>排序順序&lt;/th>
&lt;th>數值&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>由大到小&lt;/td>
&lt;td>0&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>由小到大&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h3 id="回傳資料">回傳資料&lt;/h3>
&lt;p>切換到此請求的 &lt;strong>Preview&lt;/strong> 分頁，能讓我們方便的檢視回傳資料，了解它的資料結構。&lt;br />
資料為 JSON 格式(原始資料可至 &lt;strong>Response&lt;/strong> 分頁查看)。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/job104_spider/search_preview.png" alt="&amp;#34;搜尋職缺&amp;#34;請求的回傳資料" data-caption="&amp;#34;搜尋職缺&amp;#34;請求的回傳資料" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;搜尋職缺&amp;#34;請求的回傳資料
&lt;/figcaption>
&lt;/figure>
&lt;p>依照我觀察到的推測，來說明個欄位所代表的數值意思：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;code>status&lt;/code>、&lt;code>statusMsg&lt;/code>、&lt;code>errorMsg&lt;/code>：請求狀態與訊息。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>pageNo&lt;/code>：頁數。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>data &amp;gt; count&lt;/code>：各種類的職缺數量，如下圖藍框圈選內顯示數量。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/job104_spider/result_count.png" alt="各種類的職缺數量" data-caption="各種類的職缺數量" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
各種類的職缺數量
&lt;/figcaption>
&lt;/figure>
&lt;/li>
&lt;li>
&lt;p>&lt;code>data &amp;gt; totalCount&lt;/code>：搜尋結果的職缺&amp;quot;總數&amp;quot;。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>data &amp;gt; totalPage&lt;/code>：搜尋結果的職缺&amp;quot;總頁數&amp;quot;。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>data &amp;gt; list&lt;/code>：搜尋職缺結果，包含各職缺名稱、簡介、公司等等資訊，通常一次最多 20 筆資料。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>data &amp;gt; query&lt;/code>：搜尋職缺的 query 參數，也就是我們送出請求所夾帶的篩選條件，像是地區、經歷要求、上班時段。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>data &amp;gt; queryDesc&lt;/code>：搜尋職缺的 query 參數所代表的意思。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;br/>
&lt;div class="alert alert-info" role="alert" data-dir="ltr">&amp;quot;搜尋職缺&amp;quot;回覆資料範例：&lt;a href="https://github.com/it-jia/job104_spider/blob/main/104_search.json">104_search.json&lt;/a>&lt;/div>
&lt;p>* 其中得到的資料，有些還要進一步轉換或挑選，因此我們還可以再寫個函式來執行此步驟，可參考&amp;quot;&lt;a href="#%e5%ae%8c%e6%95%b4%e7%a8%8b%e5%bc%8f%e7%a2%bc" target="_blank" rel="noopener">
完整程式碼
&lt;/a>&amp;quot;。&lt;/p>
&lt;h3 id="範例程式">範例程式&lt;/h3>
&lt;p>使用 Python 搭配 requests 套件的寫法如下，：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">time&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">random&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="k">def&lt;/span> &lt;span class="nf">search_job&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">keyword&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">max_mun&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">filter_params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">None&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">sort_type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;符合度&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">is_sort_asc&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">False&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;搜尋職缺&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">jobs&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;span class="n">total_count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://www.104.com.tw/jobs/search/list&amp;#39;&lt;/span>
&lt;span class="n">query&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;ro=0&amp;amp;kwop=7&amp;amp;keyword={keyword}&amp;amp;expansionType=area,spec,com,job,wf,wktm&amp;amp;mode=s&amp;amp;jobsource=2018indexpoc&amp;#39;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">filter_params&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="c1"># 加上篩選參數，要先轉換為 URL 參數字串格式&lt;/span>
&lt;span class="n">query&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;&amp;amp;{key}={value}&amp;#39;&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">filter_params&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">items&lt;/span>&lt;span class="p">()])&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;User-Agent&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;Referer&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;https://www.104.com.tw/jobs/search/&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="c1"># 加上排序條件&lt;/span>
&lt;span class="n">sort_dict&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;符合度&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;1&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;日期&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;2&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;經歷&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;3&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;學歷&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;4&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;應徵人數&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;7&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;待遇&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;13&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">sort_params&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;&amp;amp;order={sort_dict.get(sort_type, &amp;#39;1&amp;#39;)}&amp;#34;&lt;/span>
&lt;span class="n">sort_params&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="s1">&amp;#39;&amp;amp;asc=1&amp;#39;&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="n">is_sort_asc&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="s1">&amp;#39;&amp;amp;asc=0&amp;#39;&lt;/span>
&lt;span class="n">query&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">sort_params&lt;/span>
&lt;span class="n">page&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;span class="k">while&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">jobs&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">max_mun&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">params&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;{query}&amp;amp;page={page}&amp;#39;&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">params&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;請求失敗&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;status&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;statusMsg&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;errorMsg&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="k">break&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">total_count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;data&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;totalCount&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="n">jobs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extend&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;data&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;list&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">page&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;data&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;totalPage&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span> &lt;span class="ow">or&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;data&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;totalPage&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="k">break&lt;/span>
&lt;span class="n">page&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">uniform&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">))&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">total_count&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">jobs&lt;/span>&lt;span class="p">[:&lt;/span>&lt;span class="n">max_mun&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="n">filter_params&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;area&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;6001001000&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># (地區) 台北市&lt;/span>
&lt;span class="s1">&amp;#39;s9&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;1&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># (上班時段) 日班&lt;/span>
&lt;span class="s1">&amp;#39;isnew&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;0&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># (更新日期) 本日最新&lt;/span>
&lt;span class="s1">&amp;#39;jobexp&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;1,3&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># (經歷要求) 1年以下,1-3年&lt;/span>
&lt;span class="s1">&amp;#39;zone&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;16&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># (公司類型) 上市上櫃&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">total_count&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">jobs&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">search_job&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;python&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">max_mun&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">filter_params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">filter_params&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;搜尋結果職缺總數：&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">total_count&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;br/>
&lt;h2 id="取得職缺詳細資料">取得職缺詳細資料&lt;/h2>
&lt;p>透過上一步&amp;quot;搜尋職缺&amp;quot;所得到的職缺資料還不太完整，接下來我們來尋找取得職缺詳細資料的辦法。&lt;/p>
&lt;p>這邊以&lt;a href="https://www.104.com.tw/job/71gqf" target="_blank" rel="noopener">
此職缺
&lt;/a>為範例說明。&lt;/p>
&lt;h3 id="請求路徑與參數-1">請求路徑與參數&lt;/h3>
&lt;p>如果你點進職缺介紹網頁後，在 &lt;strong>開發人員工具&lt;/strong> (F12 或 Ctrl + Shift + i) &amp;gt; &lt;strong>Network&lt;/strong>(網路) &amp;gt; &lt;strong>XHR&lt;/strong> 分頁，會發現它也是動態載入的方式請求。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/job104_spider/job_request.png" alt="&amp;#34;取得職缺詳細資料&amp;#34;請求的方式與參數" data-caption="&amp;#34;取得職缺詳細資料&amp;#34;請求的方式與參數" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;取得職缺詳細資料&amp;#34;請求的方式與參數
&lt;/figcaption>
&lt;/figure>
&lt;p>後方的 &lt;code>71gqf&lt;/code> 代表此職缺的 ID。&lt;/p>
&lt;p>還有請求一樣需要帶上 Headers 內的 &lt;code>Referer&lt;/code> 參數，才可正常取得資料。&lt;/p>
&lt;p>將其整理出來，相關參數如下：&lt;br />
&lt;div class="box">Request URL：&lt;code>https://www.104.com.tw/job/ajax/content/71gqf&lt;/code>&lt;br />
Request Methon：&lt;code>GET&lt;/code>&lt;br />
Headers Referer：&lt;code>https://www.104.com.tw/job/71gqf&lt;/code>&lt;/div>&lt;/p>
&lt;h3 id="回傳資料-1">回傳資料&lt;/h3>
&lt;p>切換到此請求的 &lt;strong>Preview&lt;/strong> 分頁，能讓我們方便的檢視回傳資料，了解它的資料結構。&lt;br />
資料為 JSON 格式(原始資料可至 &lt;strong>Response&lt;/strong> 分頁查看)。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/job104_spider/job_preview.png" alt="&amp;#34;取得職缺詳細資料&amp;#34;請求的回傳資料" data-caption="&amp;#34;取得職缺詳細資料&amp;#34;請求的回傳資料" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;取得職缺詳細資料&amp;#34;請求的回傳資料
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;br/>
&lt;p>依照我觀察到的推測，來說明個欄位所代表的數值意思，在 &lt;code>data&lt;/code> 底下：&lt;/p>
&lt;ul>
&lt;li>&lt;code>header&lt;/code>：&lt;strong>標題&lt;/strong>。&lt;/li>
&lt;/ul>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/job104_spider/header_web.jpg" alt="&amp;#34;標題&amp;#34;網頁區塊" data-caption="&amp;#34;標題&amp;#34;網頁區塊" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='400px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:400px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;標題&amp;#34;網頁區塊
&lt;/figcaption>
&lt;/figure>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/job104_spider/header_json.png" alt="&amp;#34;標題&amp;#34;JSON" data-caption="&amp;#34;標題&amp;#34;JSON" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;標題&amp;#34;JSON
&lt;/figcaption>
&lt;/figure>
&lt;ul>
&lt;li>&lt;code>jobDetail&lt;/code>：&lt;strong>工作內容&lt;/strong>。&lt;/li>
&lt;/ul>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/job104_spider/jobDetail_web.jpg" alt="&amp;#34;工作內容&amp;#34;網頁區塊" data-caption="&amp;#34;工作內容&amp;#34;網頁區塊" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='450px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:450px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;工作內容&amp;#34;網頁區塊
&lt;/figcaption>
&lt;/figure>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/job104_spider/jobDetail_json.png" alt="&amp;#34;工作內容&amp;#34;JSON" data-caption="&amp;#34;工作內容&amp;#34;JSON" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;工作內容&amp;#34;JSON
&lt;/figcaption>
&lt;/figure>
&lt;ul>
&lt;li>&lt;code>condition&lt;/code>：&lt;strong>條件要求&lt;/strong>，例如工作經歷、學歷要求、語文條件、擅長工具、工作技能等等。&lt;/li>
&lt;/ul>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/job104_spider/condition_web.jpg" alt="&amp;#34;條件要求&amp;#34;網頁區塊" data-caption="&amp;#34;條件要求&amp;#34;網頁區塊" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='450px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:450px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;條件要求&amp;#34;網頁區塊
&lt;/figcaption>
&lt;/figure>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/job104_spider/condition_json.png" alt="&amp;#34;條件要求&amp;#34;JSON" data-caption="&amp;#34;條件要求&amp;#34;JSON" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;條件要求&amp;#34;JSON
&lt;/figcaption>
&lt;/figure>
&lt;ul>
&lt;li>&lt;code>environmentPic&lt;/code>：&lt;strong>公司環境照片&lt;/strong>。&lt;/li>
&lt;/ul>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/job104_spider/environmentPic_web.jpg" alt="&amp;#34;公司環境照片&amp;#34;網頁區塊" data-caption="&amp;#34;公司環境照片&amp;#34;網頁區塊" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='400px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:400px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;公司環境照片&amp;#34;網頁區塊
&lt;/figcaption>
&lt;/figure>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/job104_spider/environmentPic_json.png" alt="&amp;#34;公司環境照片&amp;#34;JSON" data-caption="&amp;#34;公司環境照片&amp;#34;JSON" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='550px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:550px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;公司環境照片&amp;#34;JSON
&lt;/figcaption>
&lt;/figure>
&lt;ul>
&lt;li>&lt;code>welfare&lt;/code>：&lt;strong>福利制度&lt;/strong>。&lt;/li>
&lt;/ul>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/job104_spider/welfare_web.jpg" alt="&amp;#34;福利制度&amp;#34;網頁區塊" data-caption="&amp;#34;福利制度&amp;#34;網頁區塊" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='450px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:450px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;福利制度&amp;#34;網頁區塊
&lt;/figcaption>
&lt;/figure>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/job104_spider/welfare_json.png" alt="&amp;#34;福利制度&amp;#34;JSON" data-caption="&amp;#34;福利制度&amp;#34;JSON" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='550px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:550px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;福利制度&amp;#34;JSON
&lt;/figcaption>
&lt;/figure>
&lt;ul>
&lt;li>&lt;code>contact&lt;/code>：&lt;strong>聯絡方式&lt;/strong>，例如聯絡人、連絡電話等等。&lt;/li>
&lt;/ul>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/job104_spider/contact_web.jpg" alt="&amp;#34;聯絡方式&amp;#34;網頁區塊" data-caption="&amp;#34;聯絡方式&amp;#34;網頁區塊" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='350px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:350px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;聯絡方式&amp;#34;網頁區塊
&lt;/figcaption>
&lt;/figure>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/job104_spider/contact_json.png" alt="&amp;#34;聯絡方式&amp;#34;JSON" data-caption="&amp;#34;聯絡方式&amp;#34;JSON" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='350px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:350px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;聯絡方式&amp;#34;JSON
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;div class="alert alert-info" role="alert" data-dir="ltr">&amp;quot;取得職缺詳細資料&amp;quot;回覆資料範例：&lt;a href="https://github.com/it-jia/job104_spider/blob/main/104_job.json">104_job.json&lt;/a>&lt;/div>
&lt;h3 id="範例程式-1">範例程式&lt;/h3>
&lt;p>使用 Python 搭配 requests 套件的寫法如下，：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="k">def&lt;/span> &lt;span class="nf">get_job&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">job_id&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;取得職缺詳細資料&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://www.104.com.tw/job/ajax/content/{job_id}&amp;#39;&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;User-Agent&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;Referer&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://www.104.com.tw/job/{job_id}&amp;#39;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;請求失敗&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;data&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="n">job_info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_job&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;71gqf&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">job_info&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;!--adsense-->
&lt;h2 id="完整程式碼">完整程式碼&lt;/h2>
&lt;p>我將&amp;quot;搜尋職缺&amp;quot;與&amp;quot;取得職缺詳細資料&amp;quot;包成一個 class，可以傳入不同的值來篩選，供需要的人參考。&lt;/p>
&lt;p>附上完整程式碼：&lt;a href="https://github.com/it-jia/job104_spider/blob/main/job104_spider.py" target="_blank" rel="noopener">
job104_spider.py | GitHub
&lt;/a>&lt;/p>
&lt;h2 id="其他說明">其他說明&lt;/h2>
&lt;p>&amp;quot;搜尋職缺&amp;quot;送出的請求中，我發現如果排序依據是選擇&amp;quot;符合度排序&amp;quot;，它送出的請求第一頁是 &lt;code>order: 1&lt;/code>，第二頁之後卻變成 &lt;code>order: 15&lt;/code>。&lt;br />
如果有網友知道原因，歡迎底下留言跟我說(也可到 &lt;a href="https://www.facebook.com/jiatool" target="_blank" rel="noopener">
FB粉專
&lt;/a> 留言)，我再補上說明，感謝~&lt;/p>
&lt;h2 id="延伸練習">延伸練習&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>在上方文章的&amp;quot;搜尋職缺&amp;quot;章節中，說了很多篩選參數(上班時段、經歷要求、學歷要求)，但還是有些網頁上有的篩選條件沒有說到，例如&amp;quot;薪資待遇&amp;quot;、&amp;quot;外語要求&amp;quot;，這部分你可以試著將它添加到程式內嗎？&lt;br />
(要注意的事，一個篩選條件不一定只有影響一個篩選參數)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>試著自己做個&amp;quot;自動職缺通知&amp;quot;，設定好篩選條件後，以日期排序，每天晚上就排程執行程式，如果有新的職缺，馬上透過 Line 或 Email 通知你，讓你搶先別人一步收到訊息。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>除了後續可以嘗試自製 &amp;quot;自動職缺通知&amp;quot; 以外，從回傳的資料中，還可以發現有些網頁上沒列出來的資訊呢！&lt;br />
像是顯示 &amp;quot;11~30人應徵&amp;quot;，到底準確是幾個人應徵，也可以從回傳資料中找到。&lt;/p>
&lt;br/>
&lt;p>之後會繼續陸續寫一些網站的&lt;a href="https://blog.jiatool.com/series/Python%e7%b6%b2%e8%b7%af%e7%88%ac%e8%9f%b2%e5%af%a6%e4%be%8b/" target="_blank" rel="noopener">
Python網路爬蟲實例
&lt;/a>，如果你正好是剛開始想學爬蟲的新手、想知道某網站如何爬取資料、遇到其他問題，也歡迎在底下留言，或追蹤 FB 粉專『&lt;a href="https://www.facebook.com/jiatool" target="_blank" rel="noopener">
IT空間
&lt;/a>』~ 🔔&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;blockquote>
&lt;p>相信所有的挫折，都是最好的安排。&lt;/p>
&lt;p align="right">—— 郭婞淳 (台灣舉重國手)&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/job104_spider.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/job104_spider_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Python</category><category>104人力銀行</category><category>網路爬蟲</category><category>Python網路爬蟲實例</category></item><item><title>[Python爬蟲實例] 教你爬取"foodpanda"餐飲外送平台</title><link>https://blog.jiatool.com/posts/foodpanda_spider/</link><pubDate>Tue, 22 Jun 2021 20:30:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Tue, 22 Jun 2021 20:30:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/foodpanda_spider/</guid><description>前言 現在疫情肆虐，全台提升至第三級警戒，餐廳也被限制不能內用，只能被迫發展外帶(外送)或休店，因而許多人開始轉往像 foodpanda、Ube</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>現在疫情肆虐，全台提升至第三級警戒，餐廳也被限制不能內用，只能被迫發展外帶(外送)或休店，因而許多人開始轉往像 foodpanda、Ubereats 此類餐飲外送平台來訂餐，也避免外出與人接觸的風險。&lt;/p>
&lt;p>今天的&lt;a href="https://blog.jiatool.com/series/Python%e7%b6%b2%e8%b7%af%e7%88%ac%e8%9f%b2%e5%af%a6%e4%be%8b/" target="_blank" rel="noopener">
Python網路爬蟲實例
&lt;/a>系列將來介紹 foodpanda(網頁版) 該如何搜尋餐廳、查看餐廳資訊與菜單，看看它是如何發出請求、解析回傳資料。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/foodpanda_spider/food.jpg" alt="餐點 (來源：Unsplash)" data-caption="餐點 (來源：Unsplash)" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
餐點 (來源：Unsplash)
&lt;/figcaption>
&lt;/figure>
&lt;p>備註：此文僅教育學習，切勿用作商業用途，個人實作皆屬個人行為，本作者不負任何法律責任。&lt;/p>
&lt;h2 id="套件">套件&lt;/h2>
&lt;p>此次 Python 爬蟲主要使用到的套件：&lt;/p>
&lt;ul>
&lt;li>Requests [&lt;a href="https://requests.readthedocs.io/en/master/" target="_blank" rel="noopener">
Doc
&lt;/a>] [&lt;a href="https://github.com/psf/requests" target="_blank" rel="noopener">
GitHub
&lt;/a>]&lt;/li>
&lt;/ul>
&lt;p>安裝&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">pip install requests
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;!--adsense-->
&lt;h2 id="搜尋餐廳">搜尋餐廳&lt;/h2>
&lt;h3 id="請求路徑與參數">請求路徑與參數&lt;/h3>
&lt;p>假如我目前位在&amp;quot;高雄車站&amp;quot;，想要喝杯&amp;quot;星巴克&amp;quot;的美式咖啡，因此我到 foodpanda 搜尋&amp;quot;星巴克&amp;quot;，點擊&amp;quot;搜尋&amp;quot;。&lt;/p>
&lt;p>此時，你的網址會長的大概像這樣：&lt;br />
&lt;a href="https://www.foodpanda.com.tw/restaurants/new?lat=22.639473&amp;amp;lng=120.3025185&amp;amp;vertical=restaurants&amp;amp;expedition=delivery&amp;amp;query=%E6%98%9F%E5%B7%B4%E5%85%8B">https://www.foodpanda.com.tw/restaurants/new?lat=22.639473&amp;amp;lng=120.3025185&amp;amp;vertical=restaurants&amp;amp;expedition=delivery&amp;amp;query=%E6%98%9F%E5%B7%B4%E5%85%8B&lt;/a>&lt;/p>
&lt;p>此時在瀏覽器的 &lt;strong>開發人員工具&lt;/strong> (F12 或 Ctrl + Shift + i) &amp;gt; &lt;strong>Network&lt;/strong>(網路) &amp;gt; &lt;strong>XHR&lt;/strong> 分頁，會看見一個 feed 的請求(如果沒出現再重新搜尋)，裡面放的即是搜尋出來的餐廳結果。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/foodpanda_spider/search.jpg" alt="開發人員工具 &amp;gt; Network &amp;gt; XHR &amp;gt; feed" data-caption="開發人員工具 &amp;gt; Network &amp;gt; XHR &amp;gt; feed" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
開發人員工具 &amp;gt; Network &amp;gt; XHR &amp;gt; feed
&lt;/figcaption>
&lt;/figure>
&lt;p>切到 &lt;strong>Headers&lt;/strong> 查看請求的方式與參數。&lt;/p>
&lt;p>網址是 &lt;code>https://disco.deliveryhero.io/search/api/v1/feed&lt;/code>、使用 &lt;code>POST&lt;/code> 方法、需要帶的 &lt;code>payload&lt;/code>。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/foodpanda_spider/feed_headers.png" alt="&amp;#34;搜尋餐廳&amp;#34;請求的方式與參數" data-caption="&amp;#34;搜尋餐廳&amp;#34;請求的方式與參數" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;搜尋餐廳&amp;#34;請求的方式與參數
&lt;/figcaption>
&lt;/figure>
&lt;p>我將其整理出來，相關參數如下：&lt;br />
&lt;div class="box">&lt;p>Request URL：&lt;code>https://disco.deliveryhero.io/search/api/v1/feed&lt;/code>&lt;br />
Request Methon：&lt;code>POST&lt;/code>&lt;/p>
&lt;p>Request Payload：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;q&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;星巴克&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;location&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;point&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;latitude&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">22.639473&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;longitude&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">120.3025185&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;config&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Variant21&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;customer_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;vertical_types&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="s2">&amp;#34;restaurants&amp;#34;&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;include_component_types&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="s2">&amp;#34;vendors&amp;#34;&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;include_fields&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="s2">&amp;#34;feed&amp;#34;&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;language_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;6&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;opening_type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;delivery&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;platform&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;web&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;session_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;language_code&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;zh&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;customer_type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;regular&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;limit&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">48&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;offset&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;dps_session_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;eyJzZXNzaX2lk......MjM1zOTl9&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;dynamic_pricing&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;brand&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;foodpanda&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;country_code&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;tw&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;use_free_delivery_label&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;/div>&lt;/p>
&lt;br/>
&lt;p>foodpanda 會依照你附近的餐廳去搜尋，因此請求內需要帶入經緯度，你可以用自己目前所在的位置，或指定特定位置。&lt;br />
例如我使用 Google 地圖點擊地點後，在網址列的部分可以看到此地點的經緯度：&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/foodpanda_spider/khh_station.png" alt="高雄車站經緯度" data-caption="高雄車站經緯度" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
高雄車站經緯度
&lt;/figcaption>
&lt;/figure>
&lt;p>&lt;code>q&lt;/code> 參數就是放入搜尋的關鍵字。&lt;/p>
&lt;p>&lt;code>limit&lt;/code> 與 &lt;code>offset&lt;/code> 即是限制此次請求的最大資料筆數與偏移值，如果請求你使用 &lt;code>limit:48 offset:0&lt;/code> (第一頁)，那改成 &lt;code>limit:48 offset:48&lt;/code> 就是第二頁。&lt;/p>
&lt;p>其餘參數照原樣帶入即可，以及有些可以刪除。&lt;/p>
&lt;div class="notices info" data-title="小細節提醒">
有一點要注意，搜尋結果只會顯示目前還在營業時間內的餐廳。所以我自己在測試時，一開始還覺得奇怪，怎麼有時候搜的到這家店，但有時候又搜不到 XDDD
&lt;/div>
&lt;h3 id="回傳資料">回傳資料&lt;/h3>
&lt;p>回傳資料內，&lt;code>data['feed']['count']&lt;/code> 會顯示此搜尋的餐廳總數，在 &lt;code>data['feed']['items'][0]['items']&lt;/code> 存放著搜尋結果(餐廳列表)。&lt;/p>
&lt;p>餐廳列表包含著每一間餐廳的基本資訊，像是&amp;quot;餐廳名稱&amp;quot;、&amp;quot;地址&amp;quot;、&amp;quot;評分&amp;quot;、&amp;quot;評論數量&amp;quot;、&amp;quot;餐廳圖片&amp;quot;等等，詳細可參考底下 JSON 內資料。&lt;/p>
&lt;p>回覆資料範例：&lt;a href="https://github.com/it-jia/foodpanda_spider/blob/main/fp_search.json" target="_blank" rel="noopener">
fp_search.json (單一一間餐廳)
&lt;/a>&lt;/p>
&lt;h3 id="範例程式">範例程式&lt;/h3>
&lt;p>使用 Python 搭配 requests 套件的寫法如下：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">json&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://disco.deliveryhero.io/search/api/v1/feed&amp;#39;&lt;/span>
&lt;span class="n">payload&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;q&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;星巴克&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;location&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;point&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;longitude&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">120.3025185&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 經度&lt;/span>
&lt;span class="s1">&amp;#39;latitude&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">22.639473&lt;/span> &lt;span class="c1"># 緯度&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="s1">&amp;#39;config&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;Variant17&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;vertical_types&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;restaurants&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="s1">&amp;#39;include_component_types&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;vendors&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="s1">&amp;#39;include_fields&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;feed&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="s1">&amp;#39;language_id&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;6&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;opening_type&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;delivery&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;platform&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;web&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;language_code&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;zh&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;customer_type&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;regular&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;limit&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">48&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 一次最多顯示幾筆(預設 48 筆)&lt;/span>
&lt;span class="s1">&amp;#39;offset&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 偏移值，想要獲取更多資料時使用&lt;/span>
&lt;span class="s1">&amp;#39;dynamic_pricing&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;brand&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;foodpanda&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;country_code&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;tw&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;use_free_delivery_label&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">False&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;content-type&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;application/json&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">post&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dumps&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">payload&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">restaurants&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;feed&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;items&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;items&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">restaurant&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">restaurants&lt;/span>&lt;span class="p">[:&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">restaurant&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;name&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;請求失敗&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>* 傳入 Payload 前需要用 &lt;code>json.dumps()&lt;/code> 將其轉成 JSON 格式。&lt;br />
* Headers 內要加入 &lt;code>content-type(HTTP 內容類型)&lt;/code> 來表明用 JSON 格式來傳遞參數資料。&lt;/p>
&lt;br/>
&lt;p>除了透過&amp;quot;搜尋關鍵字&amp;quot;來取得餐廳列表，接下來介紹常見的&amp;quot;附近所有餐廳&amp;quot;、&amp;quot;分類推薦的餐廳&amp;quot;兩種方式。&lt;/p>
&lt;h2 id="取得附近所有餐廳">取得附近所有餐廳&lt;/h2>
&lt;h3 id="請求路徑與參數-1">請求路徑與參數&lt;/h3>
&lt;p>網址是 &lt;code>https://disco.deliveryhero.io/listing/api/v1/pandora/vendors&lt;/code>、使用 &lt;code>GET&lt;/code> 方法以及需要的查詢參數&lt;code>Query String Parameters&lt;/code>。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/foodpanda_spider/all_nearby_restaurants.jpg" alt="&amp;#34;附近所有餐廳&amp;#34;請求的方式與參數" data-caption="&amp;#34;附近所有餐廳&amp;#34;請求的方式與參數" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;附近所有餐廳&amp;#34;請求的方式與參數
&lt;/figcaption>
&lt;/figure>
&lt;p>經過測試，請求的標頭還需要帶上&lt;code>'x-disco-client-id': 'web'&lt;/code>。&lt;/p>
&lt;br/>
&lt;p>整理出來，相關參數如下：&lt;br />
&lt;div class="box">&lt;p>Request URL：&lt;code>https://disco.deliveryhero.io/listing/api/v1/pandora/vendors&lt;/code>&lt;br />
Request Methon：&lt;code>GET&lt;/code>&lt;br />
Request Headers：&lt;code>{'x-disco-client-id': 'web'}&lt;/code>&lt;/p>
&lt;p>Query String Parameters：&lt;/p>
&lt;pre>&lt;code>latitude: 22.6394088
longitude: 120.3025474
language_id: 6
include: characteristics
dynamic_pricing: 0
configuration: Original
country: tw
customer_id:
customer_hash:
budgets:
cuisine:
sort:
food_characteristic:
use_free_delivery_label: false
vertical: restaurants
limit: 48
offset: 0
customer_type: regular
&lt;/code>&lt;/pre>&lt;/div>&lt;/p>
&lt;br/>
&lt;p>還可以透過帶入不同的參數值，來達到對結果做不同的篩選。&lt;/p>
&lt;p>&lt;strong>取餐方式&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>
&lt;p>外送&lt;br />
vertical: restaurants&lt;/p>
&lt;/li>
&lt;li>
&lt;p>外帶自取&lt;br />
vertical: restaurants&lt;br />
opening_type: pickup&lt;/p>
&lt;/li>
&lt;li>
&lt;p>生鮮雜貨&lt;br />
vertical: shop&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>排序方式&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>排序&lt;/th>
&lt;th>sort:&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>排序(預設)&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>評分最高&lt;/td>
&lt;td>rating_desc&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>最快送達&lt;/td>
&lt;td>delivery_time_asc&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>距離&lt;/td>
&lt;td>distance_asc&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>例如想將結果的餐廳依照&amp;quot;評分最高到低&amp;quot;排序，則只需要將 sort 帶入 rating_desc (&lt;code>sort:rating_desc&lt;/code>)。&lt;/p>
&lt;p>&lt;strong>有折扣&lt;/strong>&lt;br />
has_discount: 1&lt;/p>
&lt;p>&lt;strong>料理種類&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>料理種類&lt;/th>
&lt;th>cuisine:&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>中港&lt;/td>
&lt;td>166&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>健康餐&lt;/td>
&lt;td>225&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>小吃&lt;/td>
&lt;td>214&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>披薩&lt;/td>
&lt;td>165&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>日韓&lt;/td>
&lt;td>164&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>東南亞&lt;/td>
&lt;td>252&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>歐式&lt;/td>
&lt;td>175&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>漢堡&lt;/td>
&lt;td>177&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>甜點&lt;/td>
&lt;td>176&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>異國&lt;/td>
&lt;td>183&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>素食&lt;/td>
&lt;td>186&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>美式&lt;/td>
&lt;td>179&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>飲料&lt;/td>
&lt;td>181&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>麵食料理&lt;/td>
&lt;td>201&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>可多選，例如：&amp;ldquo;日韓&amp;quot;和&amp;quot;麵食料理&amp;quot;就是 &lt;code>cuisine:164,201&lt;/code>。&lt;/p>
&lt;p>&lt;strong>特色種類&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>特色&lt;/th>
&lt;th>food_characteristic:&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&amp;lt;pro專屬優惠&amp;gt;&lt;/td>
&lt;td>257&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&amp;lt;店內價&amp;gt;&lt;/td>
&lt;td>55&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&amp;lt;每月推薦&amp;gt;&lt;/td>
&lt;td>206&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&amp;lt;熱搜人氣餐廳&amp;gt;&lt;/td>
&lt;td>207&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&amp;lt;米其林推薦&amp;gt;&lt;/td>
&lt;td>205&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&amp;lt;聚餐首選&amp;gt;&lt;/td>
&lt;td>241&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&amp;lt;買一送一&amp;gt;&lt;/td>
&lt;td>239&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Vogue野餐日&lt;/td>
&lt;td>258&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>三明治&lt;/td>
&lt;td>162&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>便當&lt;/td>
&lt;td>58&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>咖哩&lt;/td>
&lt;td>155&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>咖啡輕食&lt;/td>
&lt;td>191&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>早餐&lt;/td>
&lt;td>159&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>滷味&lt;/td>
&lt;td>158&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>火鍋&lt;/td>
&lt;td>160&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>炸雞&lt;/td>
&lt;td>154&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>粥 &amp;amp; 湯&lt;/td>
&lt;td>161&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>鐵板燒&lt;/td>
&lt;td>156&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>餃子&lt;/td>
&lt;td>157&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>與&amp;quot;料理種類&amp;quot;一樣可多選。&lt;/p>
&lt;p>&lt;strong>預算高低&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>預算&lt;/th>
&lt;th>budgets:&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>低&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>中&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>高&lt;/td>
&lt;td>3&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>同樣可多選。&lt;/p>
&lt;h3 id="回傳資料-1">回傳資料&lt;/h3>
&lt;p>回傳資料內，&lt;br />
&lt;code>data['status_code']&lt;/code> 與 &lt;code>data['message']&lt;/code> 顯示本次請求狀態；&lt;br />
&lt;code>data['data']['available_count']&lt;/code> 會顯示可用的餐廳總數；&lt;br />
&lt;code>data['data']['aggregations']['cuisines']&lt;/code> 顯示各種&amp;quot;料理種類&amp;quot;的餐廳數量；&lt;br />
&lt;code>data['data']['aggregations']['foodCharacteristics']&lt;/code> 顯示各個&amp;quot;特色&amp;quot;的餐廳數量；&lt;br />
&lt;code>data['data']['items']&lt;/code> 列出此次回傳的餐廳列表。&lt;/p>
&lt;p>至於餐廳列表中，各餐廳的資訊與文章前一節&amp;quot;搜尋餐廳&amp;quot;的雷同，在此就不再贅述。&lt;/p>
&lt;p>回覆資料範例：&lt;a href="https://github.com/it-jia/foodpanda_spider/blob/main/fp_nearby_restaurants.json" target="_blank" rel="noopener">
fp_nearby_restaurants.json
&lt;/a>&lt;/p>
&lt;h3 id="範例程式-1">範例程式&lt;/h3>
&lt;p>使用 Python 搭配 requests 套件的寫法如下：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://disco.deliveryhero.io/listing/api/v1/pandora/vendors&amp;#39;&lt;/span>
&lt;span class="n">query&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;longitude&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">120.3025185&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 經度&lt;/span>
&lt;span class="s1">&amp;#39;latitude&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">22.639473&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 緯度&lt;/span>
&lt;span class="s1">&amp;#39;language_id&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">6&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;include&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;characteristics&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;dynamic_pricing&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;configuration&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;Variant1&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;country&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;tw&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;budgets&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;cuisine&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;sort&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;food_characteristic&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;use_free_delivery_label&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">False&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;vertical&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;restaurants&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;limit&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">48&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;offset&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;customer_type&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;regular&amp;#39;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;x-disco-client-id&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;web&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">restaurants&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;data&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;items&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">restaurant&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">restaurants&lt;/span>&lt;span class="p">[:&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">restaurant&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;name&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;請求失敗&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="取得分類推薦的餐廳">取得分類推薦的餐廳&lt;/h2>
&lt;p>這邊我不太知道要把它叫做什麼名稱，指的是剛進來首頁底下推薦的部分，如下圖：&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/foodpanda_spider/category_restaurant_page.jpg" alt="各分類餐廳" data-caption="各分類餐廳" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
各分類餐廳
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="請求路徑與參數-2">請求路徑與參數&lt;/h3>
&lt;p>網址是 &lt;code>https://disco.deliveryhero.io/core/api/v1/swimlanes&lt;/code>、使用 &lt;code>GET&lt;/code> 方法以及需要的查詢參數&lt;code>Query String Parameters&lt;/code>。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/foodpanda_spider/category_restaurant.jpg" alt="&amp;#34;分類推薦的餐廳&amp;#34;請求的方式與參數" data-caption="&amp;#34;分類推薦的餐廳&amp;#34;請求的方式與參數" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;分類推薦的餐廳&amp;#34;請求的方式與參數
&lt;/figcaption>
&lt;/figure>
&lt;p>整理出來，相關參數如下：&lt;br />
&lt;div class="box">&lt;p>Request URL：&lt;code>https://disco.deliveryhero.io/core/api/v1/swimlanes&lt;/code>&lt;br />
Request Methon：&lt;code>GET&lt;/code>&lt;/p>
&lt;p>Query String Parameters：&lt;/p>
&lt;pre>&lt;code>brand: foodpanda
config: Original
latitude: 22.6394088
longitude: 120.3025474
language_code: zh
language_id: 6
country_code: tw
dynamic_pricing: 0
vertical_type: restaurants
opening_type: delivery
use_free_delivery_label: false
customer_type: regular
&lt;/code>&lt;/pre>&lt;/div>&lt;/p>
&lt;br/>
&lt;p>&lt;strong>取餐方式&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>
&lt;p>外送&lt;br />
config: Original&lt;br />
vertical_type: restaurants&lt;br />
opening_type: delivery&lt;/p>
&lt;/li>
&lt;li>
&lt;p>外帶自取&lt;br />
config: pickup-control&lt;br />
vertical_type: restaurants&lt;br />
opening_type: pickup&lt;/p>
&lt;/li>
&lt;li>
&lt;p>生鮮雜貨&lt;br />
config: shops-variant&lt;br />
vertical_type: shop,darkstores&lt;br />
opening_type: delivery&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h3 id="回傳資料-2">回傳資料&lt;/h3>
&lt;p>從回傳資料的 &lt;code>data['data']['items']&lt;/code> 裡列出不同的推薦分類，例如&amp;quot;優惠主打星⭐&amp;quot;、&amp;quot;在家吃遍全世界&amp;quot;、&amp;quot;本月推薦&amp;quot;等等，各推薦分類底下的 &lt;code>vendors&lt;/code> 中也列出各家餐廳。&lt;/p>
&lt;p>而各家餐廳的資訊與文章&amp;quot;搜尋餐廳&amp;quot;的說明雷同，在此就不再贅述。&lt;/p>
&lt;p>回覆資料範例：&lt;a href="https://github.com/it-jia/foodpanda_spider/blob/main/fp_category_restaurant.json" target="_blank" rel="noopener">
fp_category_restaurant.json
&lt;/a>&lt;/p>
&lt;h3 id="範例程式-2">範例程式&lt;/h3>
&lt;p>使用 Python 搭配 requests 套件的寫法如下：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://disco.deliveryhero.io/core/api/v1/swimlanes&amp;#39;&lt;/span>
&lt;span class="n">query&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;longitude&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">120.3025185&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 經度&lt;/span>
&lt;span class="s1">&amp;#39;latitude&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">22.639473&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 緯度&lt;/span>
&lt;span class="s1">&amp;#39;brand&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;foodpanda&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;language_code&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;zh&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;language_id&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">6&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;country_code&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;tw&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;dynamic_pricing&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;use_free_delivery_label&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">False&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;customer_type&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;regular&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;config&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;Original&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;vertical_type&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;restaurants&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;opening_type&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;delivery&amp;#39;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">recommendations&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;data&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;items&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">recommendation&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">recommendations&lt;/span>&lt;span class="p">[:&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">recommendation&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;headline&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;請求失敗&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="取得餐廳基本資料與菜單">取得餐廳基本資料與菜單&lt;/h2>
&lt;p>餐廳基本資料與菜單是在同一個請求中。&lt;/p>
&lt;h3 id="請求路徑與參數-3">請求路徑與參數&lt;/h3>
&lt;p>網址是 &lt;code>https://tw.fd-api.com/api/v5/vendors/{餐廳代碼}&lt;/code>、使用 &lt;code>GET&lt;/code> 方法以及需要的查詢參數&lt;code>Query String Parameters&lt;/code>。&lt;/p>
&lt;p>&amp;quot;餐廳代碼&amp;quot;從上方各種取得餐貼列表的方式，其中餐廳資訊裡的 &lt;code>code&lt;/code> 欄位即顯示著此餐廳的代碼。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/foodpanda_spider/restaurant_info.jpg" alt="&amp;#34;餐廳基本資料與菜單&amp;#34;請求的方式與參數" data-caption="&amp;#34;餐廳基本資料與菜單&amp;#34;請求的方式與參數" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;餐廳基本資料與菜單&amp;#34;請求的方式與參數
&lt;/figcaption>
&lt;/figure>
&lt;p>整理出來，相關參數如下：&lt;br />
&lt;div class="box">&lt;p>Request URL：&lt;code>https://tw.fd-api.com/api/v5/vendors/{餐廳代碼}&lt;/code>&lt;br />
Request Methon：&lt;code>GET&lt;/code>&lt;/p>
&lt;p>Query String Parameters：&lt;/p>
&lt;pre>&lt;code>include: menus
language_id: 6
dynamic_pricing: 0
opening_type: delivery
latitude: 22.639473
longitude: 120.3025185
&lt;/code>&lt;/pre>&lt;/div>&lt;/p>
&lt;br/>
&lt;div class="notices info" data-title="小細節提醒">
有一點要注意，傳入的當前座標如果離店家太遠，會導致無法取得資料。&lt;br />
此時可以改成距離較近的座標，或者乾脆不要帶入座標(但會導致回傳資料的距離不正確)。
&lt;/div>
&lt;h3 id="回傳資料-3">回傳資料&lt;/h3>
&lt;p>從回傳資料的 &lt;code>data['data']&lt;/code> 包含此餐廳的資訊，例如前面餐廳列表就有的店名、地址、最低訂購金額外，像是營業時間、折扣活動、餐廳分類、付款類型也有。還有重要的菜單資訊、配料資訊等等，都在這個請求的回應資料裡了。&lt;/p>
&lt;p>回覆資料範例：&lt;a href="https://github.com/it-jia/foodpanda_spider/blob/main/fp_info_menu.json" target="_blank" rel="noopener">
fp_info_menu.json
&lt;/a>&lt;/p>
&lt;h3 id="範例程式-3">範例程式&lt;/h3>
&lt;p>使用 Python 搭配 requests 套件的寫法如下：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://tw.fd-api.com/api/v5/vendors/g1mk&amp;#39;&lt;/span>
&lt;span class="n">query&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;include&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;menus&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;language_id&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;6&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;dynamic_pricing&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;0&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;opening_type&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;delivery&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;longitude&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">120.3025185&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 經度&lt;/span>
&lt;span class="s1">&amp;#39;latitude&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">22.639473&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 緯度&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;店名:&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;data&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;name&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;地址:&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;data&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;address&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;距離(公里):&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;data&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;distance&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;請求失敗&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;!--adsense-->
&lt;h2 id="完整程式碼">完整程式碼&lt;/h2>
&lt;p>我將以上四種請求寫在同一個 class 中，並可以傳入不同的值來篩選，供需要的人參考。&lt;/p>
&lt;p>附上完整程式碼：&lt;a href="https://github.com/it-jia/foodpanda_spider/blob/main/foodpanda_spider.py" target="_blank" rel="noopener">
foodpanda_spider.py | GitHub
&lt;/a>&lt;/p>
&lt;h2 id="延伸練習">延伸練習&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>在&amp;quot;搜尋餐廳&amp;quot;與&amp;quot;取得附近所有餐廳&amp;quot;章節中，說到能透過 &lt;code>limit&lt;/code> 和 &lt;code>offset&lt;/code> 來抓到更多的餐廳，試著自己實際寫寫看吧。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>試著輸入餐廳代碼後，程式自動顯示餐廳的&amp;quot;基本資訊&amp;quot;與隨機五樣&amp;quot;餐點資訊&amp;quot;。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>之後會繼續陸續寫一些網站的&lt;a href="https://blog.jiatool.com/series/Python%e7%b6%b2%e8%b7%af%e7%88%ac%e8%9f%b2%e5%af%a6%e4%be%8b/" target="_blank" rel="noopener">
Python網路爬蟲實例
&lt;/a>，如果你正好是剛開始想學爬蟲的新手、想知道某網站如何爬取資料、遇到其他問題，也歡迎在底下留言，或追蹤 FB 粉專『&lt;a href="https://www.facebook.com/jiatool" target="_blank" rel="noopener">
IT空間
&lt;/a>』~ 🔔&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;blockquote>
&lt;p>還能回頭說明旅途還沒有開始，當你無法回頭的時候，才是真正的旅途。&lt;/p>
&lt;p align="right">—— 《比宇宙更遠的地方》&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/foodpanda_spider.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/foodpanda_spider_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Python</category><category>網路爬蟲</category><category>Python網路爬蟲實例</category></item><item><title>LINE Bot 聊天機器人如何更改顯示圖示、名稱？以 Python 的 line-bot-sdk 為例</title><link>https://blog.jiatool.com/posts/line_change_display/</link><pubDate>Sat, 05 Jun 2021 20:25:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sat, 05 Jun 2021 20:25:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/line_change_display/</guid><description>前言 我們一般創造 LINE Bot 聊天機器人，讓它推送或回覆訊息時，通常是如下截圖所示，會顯示與我們對話的 Bot 大頭貼(在一對一對話中並不會顯示名稱)： 聊天訊</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>我們一般創造 LINE Bot 聊天機器人，讓它推送或回覆訊息時，通常是如下截圖所示，會顯示與我們對話的 Bot 大頭貼(在一對一對話中並不會顯示名稱)：&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/line_change_display/original.jpg" alt="聊天訊息" data-caption="聊天訊息" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
聊天訊息
&lt;/figcaption>
&lt;/figure>
&lt;p>但是！！&lt;br />
你知道這可以隨我們自己改嗎？！&lt;/p>
&lt;figure >
&lt;img data-src="https://developers.line.biz/assets/img/icon-nickname-switch.7ad52e1a.jpg" alt="來源：LINE Developers" data-caption="來源：LINE Developers" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
來源：LINE Developers
&lt;/figcaption>
&lt;/figure>
&lt;p>* 為了防止用戶誤認為 LINE 官方賬號，所以在你顯示的帳號名稱後方會有 &lt;code>From 'account name'&lt;/code> 文字。&lt;/p>
&lt;p>LINE Developers 的 Messaging API 就有提供我們可以「&lt;a href="https://developers.line.biz/zh-hant/docs/messaging-api/icon-nickname-switch/" target="_blank" rel="noopener">
更改顯示圖示、名稱
&lt;/a>」，&lt;br />
接下來，我以給 &lt;a href="https://github.com/line/line-bot-sdk-python" target="_blank" rel="noopener">
Python 的 SDK 套件
&lt;/a>來示範，跟著一起看看如何使用吧~&lt;/p>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="套件">套件&lt;/h2>
&lt;p>這次教學主要使用到的 Python 套件：&lt;/p>
&lt;ul>
&lt;li>line-bot-sdk [&lt;a href="https://line-bot-sdk-python.readthedocs.io/en/stable/" target="_blank" rel="noopener">
Doc
&lt;/a>] [&lt;a href="https://github.com/line/line-bot-sdk-python" target="_blank" rel="noopener">
GitHub
&lt;/a>]&lt;/li>
&lt;/ul>
&lt;p>安裝&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">pip install line-bot-sdk
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="實際介紹教學">實際介紹教學&lt;/h2>
&lt;p>首先，我們可以在 LINE 官方 Messaging API 文檔中，查詢到&lt;a href="https://developers.line.biz/zh-hant/docs/messaging-api/icon-nickname-switch/" target="_blank" rel="noopener">
相關介紹
&lt;/a>，以及在 Messaging API reference 中查到&lt;a href="https://developers.line.biz/en/reference/messaging-api/#message-common-properties" target="_blank" rel="noopener">
送出請求的參數和規範
&lt;/a>。&lt;/p>
&lt;p>此設定可以使用在&amp;quot;推送訊息&amp;quot;和&amp;quot;回覆訊息&amp;quot;，而為了防止用戶誤認為 LINE 官方賬號，在你顯示的帳號名稱後方會再自動加上 &lt;code>From 'account name'&lt;/code> 文字。&lt;/p>
&lt;figure >
&lt;img data-src="https://developers.line.biz/assets/img/icon-nickname-switch.7ad52e1a.jpg" alt="來源：LINE Developers" data-caption="來源：LINE Developers" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
來源：LINE Developers
&lt;/figcaption>
&lt;/figure>
&lt;p>如果你跟我一樣使用 Python，也使用 line-bot-sdk 套件。在 &lt;a href="https://github.com/line/line-bot-sdk-python" target="_blank" rel="noopener">
GitHub 的 README
&lt;/a> 並沒有寫出來這部分的實際範例。&lt;br />
但我到此套件的 &lt;a href="https://line-bot-sdk-python.readthedocs.io/en/stable/" target="_blank" rel="noopener">
API 文檔
&lt;/a>尋找，它還是有把「更改顯示圖示、名稱」這部分實做出來：&lt;a href="https://line-bot-sdk-python.readthedocs.io/en/stable/linebot.models.html#linebot.models.send_messages.Sender" target="_blank" rel="noopener">
linebot.models.send_messages.Sender
&lt;/a>。&lt;/p>
&lt;br/>
&lt;p>程式一開始，需要將 Sender class 匯入到程式中：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="kn">from&lt;/span> &lt;span class="nn">linebot.models&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Sender&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>這邊以&amp;quot;回覆訊息&amp;quot;為例子，一般純文字的訊息回覆程式碼如下：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">line_bot_api&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">reply_message&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">event&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">reply_token&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">TextSendMessage&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">text&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;你說：{event.message.text}&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">)&lt;/span>
&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/line_change_display/original.jpg" alt="偏偏注定要落腳(預設訊息格式)" data-caption="偏偏注定要落腳(預設訊息格式)" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
偏偏注定要落腳(預設訊息格式)
&lt;/figcaption>
&lt;/figure>
&lt;p>而要「更改顯示圖示、名稱」很簡單，只需要加上 &lt;code>sender&lt;/code> 參數：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">line_bot_api&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">reply_message&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">event&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">reply_token&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">TextSendMessage&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">text&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;這是則文字訊息。&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">sender&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">Sender&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&amp;lt;顯示名稱&amp;gt;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">icon_url&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;&amp;lt;顯示圖示網址&amp;gt;&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">)&lt;/span>
&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Sender 有兩個參數，分別是：&lt;/p>
&lt;p>&lt;code>name&lt;/code> 參數&lt;br />
設定顯示的帳號名稱。&lt;/p>
&lt;ul>
&lt;li>字數上限：20&lt;/li>
&lt;li>某些詞（例如LINE）可能會被限制無法使用。&lt;/li>
&lt;/ul>
&lt;p>&lt;code>icon_url&lt;/code> 參數&lt;br />
設定顯示的帳號圖示網址。&lt;/p>
&lt;ul>
&lt;li>字數上限：1000&lt;/li>
&lt;li>網址只能用 https 的&lt;/li>
&lt;li>圖片格式需為 PNG&lt;/li>
&lt;li>圖片長寬比需為 1：1 (正方形) 不然可能會變形&lt;/li>
&lt;li>資料大小不能超過 1 MB&lt;/li>
&lt;/ul>
&lt;p>* 我試過使用 JPG 格式的圖片也能正常顯示，但建議還是依照官方文件的規範。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">line_bot_api&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">reply_message&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">event&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">reply_token&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">TextSendMessage&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">text&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;這是則文字訊息。&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">sender&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">Sender&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;顯示名稱&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">icon_url&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;https://res.cloudinary.com/jiablog/coffee.png&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">)&lt;/span>
&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/line_change_display/customize01.jpg" alt="自定義訊息格式" data-caption="自定義訊息格式" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
自定義訊息格式
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>當然~&lt;br />
也可以像一般回覆，一次回覆多則訊息：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">message1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">TextSendMessage&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">text&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;以下為&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">{event.message.text}&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">的搜尋結果...&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">sender&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">Sender&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;Google&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">icon_url&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;https://storage.googleapis.com/support-kms-prod/ZAl1gIwyUsvfwxoW9ns47iJFioHXODBbIkrK&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">)&lt;/span>
&lt;span class="n">message2&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">TextSendMessage&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">text&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;請為您的信仰加值&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">sender&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">Sender&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;Apple&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">icon_url&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;https://www.yusgroup.com.hk/wp-content/uploads/2012/03/Apple-Logo.jpg&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">)&lt;/span>
&lt;span class="n">message3&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">TextSendMessage&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">text&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;您想買&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">{event.message.text}&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">嗎？ 我們都有！&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">sender&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">Sender&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;Amazon&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">icon_url&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;https://pngimg.com/uploads/amazon/amazon_PNG27.png&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">)&lt;/span>
&lt;span class="n">message4&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">TextSendMessage&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">text&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;[已取得您的個資]&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">sender&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">Sender&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;Facebook&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">icon_url&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;https://upload.wikimedia.org/wikipedia/commons/0/05/Facebook_Logo_&lt;/span>&lt;span class="si">%282019%&lt;/span>&lt;span class="s2">29.png&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">)&lt;/span>
&lt;span class="n">messages&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">message1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">message2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">message3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">message4&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="n">line_bot_api&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">reply_message&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">event&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">reply_token&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">messages&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/line_change_display/customize02.jpg" alt="Amazon 請小心你的發言..." data-caption="Amazon 請小心你的發言..." src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
Amazon 請小心你的發言...
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>完整對話(手機版和電腦版)&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/line_change_display/line_complete.jpg" alt="完整對話(手機版和電腦版)" data-caption="完整對話(手機版和電腦版)" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
完整對話(手機版和電腦版)
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="範例程式碼">範例程式碼&lt;/h2>
&lt;p>這邊附上完整範例程式碼，給需要的人參考&lt;br />
GitHub Gist：&lt;a href="https://gist.github.com/it-jia/620d09ad89ae4b81850b598687d2220e" target="_blank" rel="noopener">
line_bot.py
&lt;/a>&lt;/p>
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>之前都沒注意到 LINE Bot 聊天機器人能更改聊天對話中顯示的&amp;quot;圖示&amp;quot;、&amp;quot;名稱&amp;quot;呢，感覺可以拿來做一些有趣的應用~&lt;/p>
&lt;p>歡迎追蹤『&lt;a href="https://www.facebook.com/jiatool" target="_blank" rel="noopener">
IT空間
&lt;/a>』FB 粉專，取得最新發文通知🔔&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://developers.line.biz/zh-hant/docs/messaging-api/" target="_blank" rel="noopener">
LINE 官方 Messaging API 文檔
&lt;/a>&lt;br />
&lt;a href="https://developers.line.biz/en/reference/messaging-api/" target="_blank" rel="noopener">
LINE 官方 Messaging API reference
&lt;/a>&lt;br />
&lt;a href="https://github.com/line/line-bot-sdk-python" target="_blank" rel="noopener">
LINE Messaging API SDK for Python 的 GitHub
&lt;/a>&lt;br />
&lt;a href="https://line-bot-sdk-python.readthedocs.io/en/stable/" target="_blank" rel="noopener">
LINE Messaging API SDK for Python 的 文檔
&lt;/a>&lt;/p>
&lt;br/>
&lt;blockquote>
&lt;p>Nothing is necessary. Everything is a choice.&lt;br />
沒有什麼事是必要的，每件事都是一個選擇。&lt;/p>
&lt;p align="right">—— 電影《玩命關頭 8》&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/line_change_display.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/line_change_display_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Python</category><category>LINE</category><category>聊天機器人</category></item><item><title>Streamlit 超快速又輕鬆建立網頁 Dashboard</title><link>https://blog.jiatool.com/posts/streamlit/</link><pubDate>Sun, 23 May 2021 20:50:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Wed, 06 Oct 2021 09:40:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/streamlit/</guid><description>前言 後來時隔兩年，我有整理更新的版本，請改去這邊： (2023年新版) 使用 Streamlit 快速又輕鬆建立 Dashboard 網頁 Streamlit 是個可快速製作出 Web 網頁應用程式的套件，而且不</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>後來時隔兩年，我有整理更新的版本，請改去這邊：&lt;br />
&lt;a href="https://blog.jiatool.com/posts/streamlit_2023" target="_blank" rel="noopener">
(2023年新版) 使用 Streamlit 快速又輕鬆建立 Dashboard 網頁
&lt;/a>&lt;/p>
&lt;br/>
&lt;br/>
&lt;p>Streamlit 是個可快速製作出 Web 網頁應用程式的套件，而且不需要任何前端技術，全部都採用 Python 語法，讓你將網路爬蟲、數據科學、機器學習資料簡單地呈現出來分享，是一個很方便的套件。&lt;/p>
&lt;h2 id="demo">Demo&lt;/h2>
&lt;p>這是最後將程式碼放到 GitHub，並使用 Streamlit 部署的成果。&lt;/p>
&lt;div class="alert alert-info" role="alert" data-dir="ltr">Streamlit 成果範例：&lt;a href="https://share.streamlit.io/it-jia/streamlit_demo/streamlit_app.py">streamlit_demo&lt;/a>&lt;/div>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="安裝與執行">安裝與執行&lt;/h2>
&lt;ul>
&lt;li>Streamlit [&lt;a href="https://streamlit.io/" target="_blank" rel="noopener">
官方網站
&lt;/a>] [&lt;a href="https://docs.streamlit.io/en/stable/" target="_blank" rel="noopener">
官方文檔
&lt;/a>]&lt;/li>
&lt;/ul>
&lt;p>安裝&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">pip install streamlit
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>執行&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">streamlit run &amp;lt;py程式檔案路徑&amp;gt;
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>如果想指定 Streamlit 的 port 埠號，只要在後方加上&lt;code>--server.port&lt;/code> 參數：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">streamlit run &amp;lt;py程式檔案路徑&amp;gt; --server.port &lt;span class="m">8888&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>需要終止該應用程式只需在終端中按 &lt;strong>Ctrl + c&lt;/strong>。&lt;/p>
&lt;h2 id="範例教學">範例教學&lt;/h2>
&lt;p>底下流程是參考&lt;a href="https://docs.streamlit.io/en/stable/" target="_blank" rel="noopener">
官方文檔
&lt;/a>的流程操作。&lt;/p>
&lt;h3 id="創建一個-streamlit-應用程式">創建一個 Streamlit 應用程式&lt;/h3>
&lt;p>新創建一個 Python 檔案 &lt;code>streamlit_app.py&lt;/code>，以下教學都只會編輯這個檔案。&lt;/p>
&lt;p>打開它，在一開始導入 Streamlit 與其他套件：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">time&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">streamlit&lt;/span> &lt;span class="kn">as&lt;/span> &lt;span class="nn">st&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">numpy&lt;/span> &lt;span class="kn">as&lt;/span> &lt;span class="nn">np&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">pandas&lt;/span> &lt;span class="kn">as&lt;/span> &lt;span class="nn">pd&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>打開&amp;quot;命令提示字元&amp;quot;或&amp;quot;終端機&amp;quot;，開始執行程式：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">streamlit run streamlit_app.py
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>它應該會顯示如下資訊，並自動開啟一個瀏覽器網頁。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit/run_streamlit.png" alt="執行 Streamlit 程式" data-caption="執行 Streamlit 程式" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
執行 Streamlit 程式
&lt;/figcaption>
&lt;/figure>
&lt;p>然後網頁裡面顯示&amp;hellip; 一片空白？！&lt;br />
沒錯！我們又還沒有添加元件進去，怎麼會有東西呢~ 😆&lt;/p>
&lt;h3 id="添加文字和數據">添加文字和數據&lt;/h3>
&lt;p>先幫我們的應用程式加上個標題，加入以下程式碼：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">title&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;我的第一個應用程式&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>存檔，回到瀏覽器的網頁上。&lt;br />
可以重整網頁，或點擊右上角&amp;quot;Rerun&amp;quot;的按鈕，&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit/rerun.png" alt="網頁重跑" data-caption="網頁重跑" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
網頁重跑
&lt;/figcaption>
&lt;/figure>
&lt;p>網頁上就會顯示一個標題文字了：&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit/first_title.png" alt="加入標題" data-caption="加入標題" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
加入標題
&lt;/figcaption>
&lt;/figure>
&lt;p>如何？簡單吧，那我們再繼續接著下去~&lt;/p>
&lt;h3 id="使用-magic-commands">使用 Magic Commands&lt;/h3>
&lt;p>在 Streamlit 內有個神奇的指令，他們把它叫 &lt;a href="https://docs.streamlit.io/en/stable/api.html#magic-commands" target="_blank" rel="noopener">
Magic commands
&lt;/a>，不管你給它&amp;quot;字串&amp;quot;、&amp;quot;Markdown&amp;quot;、&amp;quot;數據資料&amp;quot;、&amp;quot;Matplotlib figures&amp;quot;、&amp;quot;Altair charts&amp;quot;，Streamlit 都會辨別並以合適的方式顯示出來。&lt;/p>
&lt;p>甚至在程式碼中單一行只有變數或字串，根本不需要使用 st.write()，它都會自動套用並顯示。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;嘗試創建**表格**：&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">df&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">({&lt;/span>
&lt;span class="s1">&amp;#39;first column&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">4&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="s1">&amp;#39;second column&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">20&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">30&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">40&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="p">})&lt;/span>
&lt;span class="n">df&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit/magic_commands.jpg" alt="Markdown 與 表格" data-caption="Markdown 與 表格" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
Markdown 與 表格
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="繪製圖表和地圖">繪製圖表和地圖&lt;/h3>
&lt;p>&lt;strong>繪製折線圖&lt;/strong>&lt;br />
使用 Numpy 生成一個隨機樣本，然後將其繪製成圖表。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">chart_data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">20&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">),&lt;/span>
&lt;span class="n">columns&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;a&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;b&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;c&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">line_chart&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">chart_data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>而且它本身有下載、全螢幕觀看等功能。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit/line_chart.jpg" alt="繪製折線圖" data-caption="繪製折線圖" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
繪製折線圖
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>&lt;strong>繪製地圖&lt;/strong>&lt;br />
使用 Numpy 生成一個隨機樣本，繪製到地圖上。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">map_data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">100&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mi">50&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">50&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mf">22.7&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">120.3&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="n">columns&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;lat&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;lon&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">map&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">map_data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit/map.jpg" alt="繪製地圖" data-caption="繪製地圖" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
繪製地圖
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="加入小工具">加入小工具&lt;/h3>
&lt;p>除了上述標題、圖表，還有其他小工具，像是複選框、選擇框、按鈕、滑塊等等。&lt;/p>
&lt;p>使用複選框來顯示/隱藏數據，例如在剛剛繪製地圖的程式上方加入：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">if&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">checkbox&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;顯示地圖圖表&amp;#39;&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="n">map_data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">randn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">100&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mi">50&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">50&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mf">22.7&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">120.3&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="n">columns&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;lat&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;lon&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">map&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">map_data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>但你可能會注意到，每次點擊複選框時，上方的折線圖也會產生變化。&lt;br />
這是因為 Streamlit 只要元件有輸入值的改變，整個程式(網頁)就會重新運行，因此折線圖裡的 random 才會出來不同資料。&lt;/p>
&lt;br/>
&lt;p>使用選擇框進行選擇：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">option&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">selectbox&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="s1">&amp;#39;你喜歡哪種動物？&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;狗&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;貓&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;鸚鵡&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;天竺鼠&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="s1">&amp;#39;你的答案：&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">option&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit/checkbox_selectbox.png" alt="複選框 與 選擇框" data-caption="複選框 與 選擇框" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
複選框 與 選擇框
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="調整佈局">調整佈局&lt;/h3>
&lt;p>我們也能將元件移到側邊欄中，這邊範例將上方選擇框移入側邊欄：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">option&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sidebar&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">selectbox&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="s1">&amp;#39;你喜歡哪種動物？&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;狗&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;貓&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;鸚鵡&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;天竺鼠&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="s1">&amp;#39;你的答案：&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">option&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit/sidebar.jpg" alt="將元件移到側邊欄" data-caption="將元件移到側邊欄" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='750px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:750px;height:;"/>
&lt;figcaption style="text-align: center;">
將元件移到側邊欄
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>也有左右兩邊的方式來排列：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">left_column&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">right_column&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">beta_columns&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">left_column&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;這是左邊欄位。&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">right_column&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;這是右邊欄位。&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;p>或通過 st.beta_expander 來隱藏大量內容來節省空間。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">expander&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">beta_expander&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;點擊來展開...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">expander&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;如果你要顯示很多文字，但又不想佔大半空間，可以使用這種方式。&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit/expander.png" alt="將內容摺疊起來" data-caption="將內容摺疊起來" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='650px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:650px;height:;"/>
&lt;figcaption style="text-align: center;">
將內容摺疊起來
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="加入進度條">加入進度條&lt;/h3>
&lt;p>這邊使用 &lt;code>time.sleep()&lt;/code> 來模擬進度：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="c1"># 增加一個空白元件，等等要放文字&lt;/span>
&lt;span class="n">latest_iteration&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">empty&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">bar&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">progress&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">100&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="n">latest_iteration&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;目前進度 {i+1} %&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">bar&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">progress&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">i&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">0.1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>而且網頁右上角還會顯示&amp;quot;RUNNING&amp;hellip;&amp;quot;，並有多個運動圖示跳動，讓使用者知道目前網頁中還有東西正在運行。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit/running.png" alt="網頁 RUNNING... 字樣" data-caption="網頁 RUNNING... 字樣" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='400px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:400px;height:;"/>
&lt;figcaption style="text-align: center;">
網頁 RUNNING... 字樣
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="使用快取">使用快取&lt;/h3>
&lt;p>如同前面所述，只要元件輸入值有改變，整個程式(網頁)就會重新運行，但假如有較耗費時間、資源的運算，會造成使用者每調一個參數，就浪費時間在等。&lt;/p>
&lt;p>因此 Streamlit 內提供一個緩存機制，可以使用 &lt;code>@st.cache&lt;/code> 裝飾器，將之前運算過的結果快取起來，如果下次遇到一樣的輸入值，就能直接使用之前的結果，節省時間。&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://docs.streamlit.io/en/stable/caching.html" target="_blank" rel="noopener">
官方說明 Improve app performance
&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>要使用 &lt;code>@st.cache&lt;/code> 裝飾器，就需要將運算部分的程式碼包成函式(def)。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="nd">@st.cache&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">suppress_st_warning&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">def&lt;/span> &lt;span class="nf">expensive_computation&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;沒有快取：expensive_computation({a})&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">2&lt;/span>
&lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">slider&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;選擇一個數字&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">expensive_computation&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;結果：&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit/cache.png" alt="cache 快取" data-caption="cache 快取" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
cache 快取
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="網頁配置設定">網頁配置設定&lt;/h3>
&lt;p>要寫在程式內所有 Streamlit 命令之前，而且只能設定一次。&lt;/p>
&lt;p>此函式有四個參數：&lt;/p>
&lt;ul>
&lt;li>page_title：網頁標題，顯示在瀏覽器分頁的標籤上，預設是程式碼的檔名。&lt;/li>
&lt;li>page_icon：網頁圖標，顯示在網頁標題前，可以使用 &lt;code>st.image&lt;/code> 或 Emoji，或者使用&amp;quot;random&amp;quot;讓它隨機產生XD。&lt;/li>
&lt;li>layout：網頁中佈局寬度，預設是&amp;quot;centered&amp;quot;，還可以使用&amp;quot;wide&amp;quot;。&lt;/li>
&lt;li>initial_sidebar_state：側邊欄顯示狀態，&amp;quot;expanded&amp;quot;打開或&amp;quot;collapsed&amp;quot;隱藏，預設是&amp;quot;auto&amp;quot;，代表在手機尺寸的設備上是隱藏，否則是打開顯示。&lt;/li>
&lt;/ul>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit/web_page.png" alt="網頁標題與 icon" data-caption="網頁標題與 icon" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
網頁標題與 icon
&lt;/figcaption>
&lt;/figure>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">st&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">set_page_config&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="n">page_title&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;自定義網頁標題&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">page_icon&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;random&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">layout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;centered&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">initial_sidebar_state&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;collapsed&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="網頁選單設定">網頁選單設定&lt;/h3>
&lt;p>在網頁右上方有個選單，包含之前提過的 Rerun，以及清除快取、連結到官方文件論壇，甚至還有螢幕錄影功能，將你的操作流程直接錄影起來，展示給其他人。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit/menu.jpg" alt="網頁選單" data-caption="網頁選單" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='400px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:400px;height:;"/>
&lt;figcaption style="text-align: center;">
網頁選單
&lt;/figcaption>
&lt;/figure>
&lt;p>而選單內的&amp;quot;設定&amp;quot;有幾個選項：&lt;/p>
&lt;ul>
&lt;li>Run on save：程式存檔後網頁自動重跑，不需要再手動點 Rerun&lt;/li>
&lt;li>Wide mode：佈局寬度調寬&lt;/li>
&lt;li>Theme：佈景主題&lt;/li>
&lt;/ul>
&lt;p>* 自定義主題可參考&lt;a href="https://blog.streamlit.io/introducing-theming/" target="_blank" rel="noopener">
官方介紹說明
&lt;/a>。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/streamlit/settings.jpg" alt="網頁設定" data-caption="網頁設定" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
網頁設定
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="部署應用程式">部署應用程式&lt;/h3>
&lt;p>官方提供一種方式部署，只需要將你的 Streamlit 應用程式放在 GitHub 上，即可登入 share.streamlit.io 去部署運行起來。&lt;/p>
&lt;p>完整部署介紹請參考&lt;a href="https://docs.streamlit.io/en/stable/deploy_streamlit_app.html" target="_blank" rel="noopener">
官方說明
&lt;/a>：&lt;/p>
&lt;ol>
&lt;li>先確認你的資料夾內有 &lt;a href="https://docs.streamlit.io/en/stable/deploy_streamlit_app.html#python-dependencies" target="_blank" rel="noopener">
Python 依賴文件
&lt;/a>，例如 &lt;code>requirements.txt&lt;/code>、&lt;code>Pipfile&lt;/code>、&lt;code>pyproject.toml&lt;/code>、&lt;code>environment.yml&lt;/code> 這幾種，或者還有 &lt;a href="https://docs.streamlit.io/en/stable/deploy_streamlit_app.html#apt-get-dependencies" target="_blank" rel="noopener">
apt-get 依賴
&lt;/a>。&lt;/li>
&lt;li>將你的 Streamlit 應用程式推到自己的 GitHub 公開 Repository。&lt;/li>
&lt;li>前往&lt;a href="https://streamlit.io/" target="_blank" rel="noopener">
官網
&lt;/a>註冊登入，並到 &lt;a href="https://streamlit.io/sharing-sign-up" target="_blank" rel="noopener">
Get an invite to Streamlit sharing
&lt;/a> 設定。&lt;/li>
&lt;li>打開網址、查看結果~&lt;/li>
&lt;/ol>
&lt;p>註冊 Streamlit sharing 後要等到邀請的 Email 回信，我的經驗是等了一天。&lt;/p>
&lt;br/>
&lt;p>&lt;strong>應用程式網址格式&lt;/strong>&lt;/p>
&lt;p>你的網址格式為：&lt;br />
&lt;code>https://share.streamlit.io/[user name]/[repo name]/[branch name]/[app path]&lt;/code>&lt;br />
例如我上面的範例是：&lt;br />
&lt;code>https://share.streamlit.io/it-jia/streamlit_demo/master/streamlit_app.py&lt;/code>&lt;/p>
&lt;p>而如果你 Git 分支是 &lt;code>master&lt;/code>，或應用程式檔案名稱為 &lt;code>streamlit_app.py&lt;/code>，甚至可以簡化成：&lt;br />
&lt;code>https://share.streamlit.io/[user name]/[repo name]&lt;/code>&lt;br />
我的範例簡化成：&lt;br />
&lt;code>https://share.streamlit.io/it-jia/streamlit_demo&lt;/code>&lt;/p>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="完整範例程式碼">完整範例程式碼&lt;/h2>
&lt;p>附上完整範例程式碼：&lt;a href="https://github.com/it-jia/streamlit_demo/blob/master/streamlit_app.py" target="_blank" rel="noopener">
streamlit_app.py
&lt;/a>&lt;/p>
&lt;p>此範例程式碼部署在 share.streamlit.io 的 Demo：&lt;/p>
&lt;div class="alert alert-info" role="alert" data-dir="ltr">Streamlit 成果範例：&lt;a href="https://share.streamlit.io/it-jia/streamlit_demo/streamlit_app.py">streamlit_demo&lt;/a>&lt;/div>
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>實際安裝使用後，發現這個套件真的可以很容易、快速的建立一個顯示資料用的儀表板(Dashboard)，因此寫這篇文章來分享給大家~&lt;/p>
&lt;p>官方有將 API 濃縮成一頁，方便快速尋找：&lt;br />
&lt;a href="https://share.streamlit.io/daniellewisdl/streamlit-cheat-sheet/app.py">https://share.streamlit.io/daniellewisdl/streamlit-cheat-sheet/app.py&lt;/a>&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://streamlit.io/" target="_blank" rel="noopener">
Streamlit 官方網站
&lt;/a>&lt;br />
&lt;a href="https://docs.streamlit.io/en/stable/" target="_blank" rel="noopener">
Streamlit 官方文檔
&lt;/a>&lt;br />
&lt;a href="https://neutron0916.medium.com/c433e1da1559" target="_blank" rel="noopener">
Streamlit極簡易的Dashboard開發 - Neutron
&lt;/a>&lt;br />
&lt;a href="https://officeguide.cc/python-streamlit-build-web-data-analysis-app-tutorial-examples/" target="_blank" rel="noopener">
Python 以 Streamlit 建立網頁資料分析應用程式教學與範例 - Office指南
&lt;/a>&lt;/p>
&lt;br/>
&lt;blockquote>
&lt;p>選擇，比努力更重要。&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/streamlit.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/streamlit_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Python</category><category>Streamlit</category><category>Dashboard</category><category>套件</category><category>分享</category><category>Python套件</category></item><item><title>[Python爬蟲實例] PChome 線上購物 (下篇)</title><link>https://blog.jiatool.com/posts/pchome_spider02/</link><pubDate>Sun, 02 May 2021 20:50:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sun, 02 May 2021 20:50:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/pchome_spider02/</guid><description>前言 在之前的爬蟲實例講解過蝦皮購物 ，而今日要來講解同樣在台灣非常多人使用的「PChome 線上購物 」🛒。 因為 PChome 在一個頁面中針對不同部分的資料有</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>在之前的爬蟲實例講解過&lt;a href="https://blog.jiatool.com/posts/shopee_spider/" target="_blank" rel="noopener">
蝦皮購物
&lt;/a>，而今日要來講解同樣在台灣非常多人使用的「&lt;a href="https://shopping.pchome.com.tw/" target="_blank" rel="noopener">
PChome 線上購物
&lt;/a>」🛒。&lt;/p>
&lt;p>因為 PChome 在一個頁面中針對不同部分的資料有送出不同的請求，整理成一篇會太長，因此我將分為上下篇來介紹。&lt;br />
上一篇 PChome 線上購物介紹到 &lt;a href="https://ecshweb.pchome.com.tw/search/v3.3/?q=%E6%BB%91%E9%BC%A0" target="_blank" rel="noopener">
PChome 搜尋頁面
&lt;/a> 的相關資料，而本篇將講解如何取到 &lt;a href="https://24h.pchome.com.tw/prod/DCAN8J-A9008YONC" target="_blank" rel="noopener">
商品頁面
&lt;/a> 的資料。&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://blog.jiatool.com/posts/pchome_spider01" target="_blank" rel="noopener">
PChome 線上購物 網路爬蟲實例 (上篇)
&lt;/a>&lt;/li>
&lt;li>PChome 線上購物 網路爬蟲實例 (下篇) =&amp;gt; 本篇&lt;/li>
&lt;/ul>
&lt;br/>
&lt;p>* 「&lt;a href="https://shopping.pchome.com.tw/" target="_blank" rel="noopener">
PChome 線上購物
&lt;/a>」與「&lt;a href="https://24h.pchome.com.tw/" target="_blank" rel="noopener">
PChome 24h購物
&lt;/a>」兩者的商品搜尋都是導到同樣的頁面，因此實際上是一樣的。&lt;/p>
&lt;p>備註：此文僅教育學習，切勿用作商業用途，個人實作皆屬個人行為，本作者不負任何法律責任&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider02/online_shopping.jpg" alt="線上購物 (來源：Pixabay)" data-caption="線上購物 (來源：Pixabay)" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
線上購物 (來源：Pixabay)
&lt;/figcaption>
&lt;/figure>
&lt;h2 id="套件">套件&lt;/h2>
&lt;p>此次 Python 爬蟲主要使用到的套件：&lt;/p>
&lt;ul>
&lt;li>Requests [&lt;a href="https://requests.readthedocs.io/en/master/" target="_blank" rel="noopener">
Doc
&lt;/a>] [&lt;a href="https://github.com/psf/requests" target="_blank" rel="noopener">
GitHub
&lt;/a>]&lt;/li>
&lt;/ul>
&lt;p>安裝&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">pip install requests
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;!--adsense-->
&lt;h2 id="商品基本資料">商品基本資料&lt;/h2>
&lt;p>這邊以&lt;a href="https://24h.pchome.com.tw/prod/DHAFI0-A900BAPXK" target="_blank" rel="noopener">
此商品
&lt;/a>為例，其網址為：&lt;a href="https://24h.pchome.com.tw/prod/DHAFI0-A900BAPXK">https://24h.pchome.com.tw/prod/DHAFI0-A900BAPXK&lt;/a>&lt;/p>
&lt;p>「商品基本資料」請求資料會有像是商品名稱、圖片、價格，與一些此商品的設定等等。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider02/product_info.jpg" alt="商品名稱、圖片" data-caption="商品名稱、圖片" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
商品名稱、圖片
&lt;/figcaption>
&lt;/figure>
&lt;p>* 商品名稱下方的資訊又是在其他請求XD，文章之後章節會提到。&lt;/p>
&lt;h3 id="請求路徑與參數">請求路徑與參數&lt;/h3>
&lt;div class="notices info" data-title="商品基本資料 請求">
請求網址：&lt;code>https://ecapi.pchome.com.tw/ecshop/prodapi/v2/prod/DHAFI0-A900BAPXK&amp;amp;_callback=jsonp_prod&lt;/code>&lt;br />
請求方法：&lt;code>GET&lt;/code>
&lt;/div>
&lt;br/>
&lt;p>也可以透過 &lt;code>fields&lt;/code> 參數來指定你想要哪些欄位，例如我只要商品名稱、商品價格、是否有24小時到達：&lt;br />
&lt;code>https://ecapi.pchome.com.tw/ecshop/prodapi/v2/prod/DHAFI0-A900BAPXK&amp;amp;fields=Name,Price,isArrival24h&amp;amp;_callback=jsonp_prod&lt;/code>&lt;/p>
&lt;p>原先網頁上抓到它有帶以下欄位：&lt;br />
&lt;code>fields=Seq,Id,Name,Nick,Store,PreOrdDate,SpeOrdDate,Price,Discount,Pic,Weight,ISBN,Qty,Bonus,isBig,isSpec,isCombine,isDiy,isRecyclable,isCarrier,isMedical,isBigCart,isSnapUp,isDescAndIntroSync,isFoodContents,isHuge,isEnergySubsidy,isPrimeOnly,isPreOrder24h,isWarranty,isLegalStore,isFresh,isBidding,isSet,Volume,isArrival24h,isETicket,ShipType,isO2O&lt;/code>&lt;/p>
&lt;p>我還有發現如果不加上&amp;quot;fields&amp;quot;參數，回傳的欄位反而會少其中幾個。&lt;/p>
&lt;h3 id="回傳資料">回傳資料&lt;/h3>
&lt;p>跟上篇的&amp;quot;商品規格種類&amp;quot;一樣，回傳資料前後會有一段 JS 語法，我們要先將其字串移除後，才是正確的 JSON 格式。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-JSON" data-lang="JSON">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;DHAFI0-A900BAPXK-000&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;Name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;ASUS E410MA-0341PN4020 玫瑰金(Celeron N4020/4G/128G/Windows 10 Home S/HD/14)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Price&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;M&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;P&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">11900&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Prime&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;isArrival24h&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Seq&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">26650490&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DHAFI0-A900BAPXK-000&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Nick&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;font color=#5c18d8&amp;gt;&amp;lt;b&amp;gt;小資輕薄機首選!★輕1.3kg★內附Microsoft365&amp;lt;/font&amp;gt;&amp;lt;/b&amp;gt;&amp;lt;Br&amp;gt;ASUS E410MA-0341PN4020 玫瑰金&amp;lt;BR&amp;gt;14吋輕薄文書筆電&amp;lt;BR&amp;gt;&amp;lt;font size=3&amp;gt;&amp;lt;font color=#FF00CC&amp;gt;★內含S模式作業系統 &amp;lt;/font&amp;gt;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Store&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DHAFI0&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;PreOrdDate&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;SpeOrdDate&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Discount&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Pic&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;B&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;/items/DHAFI0A900BAPXK/000001_1619679669.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;S&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;/items/DHAFI0A900BAPXK/000002_1619679669.jpg&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;Weight&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">2.1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;ISBN&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Qty&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Bonus&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isBig&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isSpec&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isCombine&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isDiy&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isRecyclable&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isCarrier&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isMedical&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isBigCart&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isSnapUp&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isDescAndIntroSync&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isFoodContents&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isHuge&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isEnergySubsidy&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isPrimeOnly&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isPreOrder24h&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isWarranty&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isLegalStore&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isFresh&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isBidding&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isSet&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Volume&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;Length&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">43&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Width&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">27&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Height&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">7&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;isETicket&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;ShipType&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Consign&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isO2O&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>其中 &lt;code>Name&lt;/code> 欄位和 &lt;code>Nick&lt;/code> 欄位可能資料會很像，&lt;code>Name&lt;/code> 欄位在搜尋頁面會出現，代表商品的真正名稱，而 &lt;code>Nick&lt;/code> 欄位是在商品頁面出現，會加上一些修飾標語跟文字樣式(HTML 格式)，如下兩張圖片所示：&lt;/p>
&lt;p>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider02/product_name.jpg" alt="Name 欄位代表資料" data-caption="Name 欄位代表資料" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='850px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:850px;height:;"/>
&lt;figcaption style="text-align: center;">
Name 欄位代表資料
&lt;/figcaption>
&lt;/figure>&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider02/product_nick.jpg" alt="Nick 欄位代表資料" data-caption="Nick 欄位代表資料" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
Nick 欄位代表資料
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>上次有說到，商品圖片分為&amp;quot;picS&amp;quot;與&amp;quot;picB&amp;quot;，查看後我猜測&amp;quot;picS&amp;quot;是在搜尋頁面的圖片，而&amp;quot;picB&amp;quot;是位於商品本身頁面的。&lt;/p>
&lt;p>前方再加上 &lt;code>https://d.ecimg.tw&lt;/code> 即圖片完整網址。&lt;br />
如 &lt;code>https://d.ecimg.tw/items/DHAFI0A900BAPXK/000001_1619679669.jpg&lt;/code>。&lt;/p>
&lt;p>而其他 &lt;code>is&lt;/code> 開頭的欄位代表此商品的其他特性(?)，或者說是 PChome 給它加上的屬性，例如是否有24小時到達、長寬高是多少(這邊應該是指包裝的，而不是商品本身的規格)、是否醫療相關、是否有食材相關標示&amp;hellip;&amp;hellip;等等，可能會用在顯示圖示或是否有其他請求去抓更多資料。&lt;/p>
&lt;h3 id="範例程式">範例程式&lt;/h3>
&lt;p>&amp;quot;商品基本資料&amp;quot;部分範例程式如下，完整程式碼在文章最後會附上。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_product_info&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">product_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">fields&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">None&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;取得商品基本資訊
&lt;/span>&lt;span class="s2">
&lt;/span>&lt;span class="s2"> :param product_id: 商品 ID
&lt;/span>&lt;span class="s2"> :param fields: 指定欄位
&lt;/span>&lt;span class="s2"> :return data: 商品基本資訊
&lt;/span>&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="c1"># fields=Seq,Id,Name,Nick,Store,PreOrdDate,SpeOrdDate,Price,Discount,Pic,Weight,ISBN,Qty,Bonus,isBig,isSpec,isCombine,isDiy,isRecyclable,isCarrier,isMedical,isBigCart,isSnapUp,isDescAndIntroSync,isFoodContents,isHuge,isEnergySubsidy,isPrimeOnly,isPreOrder24h,isWarranty,isLegalStore,isFresh,isBidding,isSet,Volume,isArrival24h,isETicket,ShipType,isO2O&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://ecapi.pchome.com.tw/ecshop/prodapi/v2/prod/{product_id}&amp;#39;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">fields&lt;/span> &lt;span class="ow">is&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="bp">None&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;&amp;amp;fields={fields}&amp;#39;&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="s1">&amp;#39;&amp;amp;_callback=jsonp_prod&amp;#39;&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">request_get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">to_json&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">False&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 去除前後 JS 語法字串&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">loads&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">15&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">48&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">data&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="商品描述標語規格備註">商品描述(標語、規格、備註)&lt;/h2>
&lt;p>此章節所說的商品描述，包括位於商品圖片右方、標題下方的&amp;quot;標語&amp;quot;，還有商品頁面最下面的&amp;quot;配備&amp;quot;、&amp;quot;規格&amp;quot;、&amp;quot;備註&amp;quot;，甚至更下方的&amp;quot;售後服務&amp;quot;等等。&lt;/p>
&lt;p>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider02/product_slogan.jpg" alt="商品標語" data-caption="商品標語" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
商品標語
&lt;/figcaption>
&lt;/figure>&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider02/product_stmt.jpg" alt="商品規格、備註" data-caption="商品規格、備註" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
商品規格、備註
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;h3 id="請求路徑與參數-1">請求路徑與參數&lt;/h3>
&lt;div class="notices info" data-title="商品描述 請求">
請求網址：&lt;code>https://ecapi-pchome.cdn.hinet.net/cdn/ecshop/prodapi/v2/prod/DHAFI0-A900BAPXK/desc&amp;amp;_callback=jsonp_prod&lt;/code>&lt;br />
請求方法：&lt;code>GET&lt;/code>
&lt;/div>
&lt;br/>
&lt;p>一樣可以透過 &lt;code>fields&lt;/code> 參數來指定你想要哪些欄位。&lt;/p>
&lt;h3 id="回傳資料-1">回傳資料&lt;/h3>
&lt;p>拿到回傳資料後，一樣要先將前後的 JS 語法去除，才可以正確地解析 JSON 格式。&lt;br />
不過這部分並不是每樣商品都會有每個欄位，像是假如商品它沒有&amp;quot;備註&amp;quot;，那&amp;quot;Remark&amp;quot;那個欄位的值就是空字串。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-JSON" data-lang="JSON">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;DHAFI0-A900BAPXK&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;Id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DHAFI0-A900BAPXK&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Stmt&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;a name=\&amp;#34;規格說明\&amp;#34;&amp;gt;ASUS E410MA-0341PN4020 玫瑰金 詳細規格表&amp;lt;/a&amp;gt;\r\nLCD尺寸 (解析度)：14.0&amp;#39;//200nits//HD 1366x768 16:9//Anti-Glare//NTSC: 45%\r\n&amp;lt;font color=\&amp;#34;RED\&amp;#34;&amp;gt;CPU：Intel® Celeron® N4020 Processor 1.1 GHz (4M Cache, up to 2.8 GHz)&amp;lt;/font&amp;gt;\r\n記憶體：4GB DDR4 on board\r\n容量：128G EMMC\r\nWLAN無線網路：Wi-Fi 5(802.11ac)+Bluetooth 4.1 (Dual band) 1*1\r\nODD光碟機：無\r\n\r\n&amp;lt;HR&amp;gt;\r\n輸入輸出介面(I/O)\r\n\&amp;#34;1x 3.5mm Combo Audio Jack\r\n1x HDMI 1.4//1x USB 2.0 Type-A\r\n1x USB 3.2 Gen 1 Type-A\r\n1x USB 3.2 Gen 1 Type-C//Micro SD card reader\&amp;#34;\r\n\r\n&amp;lt;HR&amp;gt;\r\n尺寸：32.50 x 21.70 x 1.80 ~ 1.84 cm\r\n重量：1.3KG\r\n保固：二年全球保固/首年完美保固\r\n&amp;lt;font color=\&amp;#34;RED\&amp;#34;&amp;gt;作業系統：Windows 10 Home S (S模式)&amp;lt;/font&amp;gt;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Equip&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;變壓器 無附包,無附鼠&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Remark&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;font color=\&amp;#34;RED\&amp;#34;&amp;gt;此為通用文案 實際規格以賣場為主&amp;lt;/font&amp;gt;\r\nS模式作業系統,使用者需於Windows市集做標準版作業系統轉換&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Liability&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;B&amp;gt;華碩筆記型電腦兩年保固&amp;lt;/B&amp;gt;&amp;lt;BR&amp;gt;台灣區自2002年2月1日起凡購買華碩筆記型電腦即可享有兩年產品保固服務。&amp;lt;BR&amp;gt;◎關於電池保固問題 &amp;lt;BR&amp;gt;電池為消耗性之產品，其保固期為壹年&amp;lt;BR&amp;gt;電池使用時間與充放電之次數成反比，因此使用時間縮短為正常現象，不屬於一年保固範圍&amp;lt;BR&amp;gt;&amp;lt;B&amp;gt;華碩筆記型電腦免費送修&amp;lt;/B&amp;gt;&amp;lt;BR&amp;gt;為提供本公司產品用戶有更完善的售後服務，我們特別推出了筆記型電腦本島免費快遞送修的服務，讓客戶有維修需求時能有效快速的透過物流收送，回廠進行維修流程，及完修後安全迅速的將機台送回，達成客戶滿意之依據。&amp;lt;BR&amp;gt;適用本公司出售之華碩筆記型電腦產品於保固內有維修需求時，給予回廠免費收送服務。&amp;lt;BR&amp;gt;◎只限台灣本島︰不限地點可收件。&amp;lt;BR&amp;gt;◎請撥客服電話：0800-093-456， 客服人員將為與您聯絡相關事宜。&amp;lt;BR&amp;gt;為了保障您的權益， 請立即在線上註冊您的商品。若您是第一次註冊，請先加入華碩一般會員，謝謝您!&amp;lt;BR&amp;gt;◆線上註冊→ &amp;lt;A href=\&amp;#34; http://support.asus.com.tw/repair/repair.aspx?no=99&amp;amp;SLanguage=zh-tw TARGET=\&amp;#34; _NEW?&amp;gt;&amp;lt;U&amp;gt;請前往原廠網站&amp;lt;/U&amp;gt;&amp;lt;/A&amp;gt;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Kword&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;E410MA^ASUS^筆電^小筆電^14吋^玫瑰金^虛擬數字鍵盤&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Brand&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;華碩&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Slogan&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;font color=\&amp;#34;RED\&amp;#34;&amp;gt; ★虛擬數字鍵 /180度螢幕轉軸設計\r\n★可自行升級M.2 SSD \r\n★最高電池續航力12小時&amp;lt;/font&amp;gt;\r\n\r\n&amp;lt;font size=2&amp;gt;&amp;lt;LI&amp;gt;&amp;lt;font color=red&amp;gt;處理器：Intel® Celeron® N4020 Processor 1.1 GHz&amp;lt;/font&amp;gt;\r\n&amp;lt;LI&amp;gt;記憶體：4GB DDR4 on board\r\n&amp;lt;LI&amp;gt;容量：EMMC 128GB\r\n&amp;lt;LI&amp;gt;LCD尺寸：14\&amp;#34;HD 霧面寬螢幕(LED)\r\n&amp;lt;LI&amp;gt;無線網路：802.11ac+Bluetooth 4.1 (Dual band) 1*1\r\n&amp;lt;LI&amp;gt;光碟機：無\r\n&amp;lt;LI&amp;gt;其他：HDMI、USB 3.2\r\n&amp;lt;LI&amp;gt;重量：1.3KG\r\n&amp;lt;font color=red&amp;gt;&amp;lt;LI&amp;gt;其他：內含 Microsoft365 個人版一年(市價2190元)&amp;lt;/font&amp;gt;\r\n&amp;lt;font color=red&amp;gt;&amp;lt;LI&amp;gt;作業系統：Windows 10 Home S (S模式) &amp;lt;/font&amp;gt;\r\n&amp;lt;LI&amp;gt;保固：二年全球保固/首年完美保固\r\n\r\n&amp;lt;a href=\&amp;#34; //a.ecimg.tw/img/projects/personal/v0/upload_file/US00010362/Office-introduce.jpg \&amp;#34;target=”_blank”&amp;gt;&amp;lt;img src=\&amp;#34;https://a.ecimg.tw/img/projects/personal/v0/upload_file/US00010362/office/2019-1.jpg \&amp;#34;alt=\&amp;#34;↑買NB加購Office 詳細請點\&amp;#34;&amp;gt;&amp;lt;/a&amp;gt;\r\n&amp;lt;a href=\&amp;#34;#規格說明\&amp;#34;&amp;gt;&amp;lt;img src=\&amp;#34;https://a.ecimg.tw/img/projects/personal/v0/upload_file/US00000208/add/icon.jpg\&amp;#34;&amp;gt;本商品詳細規格&amp;lt;/a&amp;gt;&amp;lt;/a&amp;gt;\r\n&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Author&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Transman&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Pubunit&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Pubdate&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Meta&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;Brand&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;BrandEng&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;MarcoMatchName&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="s2">&amp;#34;ASUS&amp;#34;&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="食物類商品缺少規格">食物類商品缺少規格？&lt;/h4>
&lt;p>但在抓取某些商品時會發現，像是底下這個食物類的標示，怎麼規格缺少了上方內容物、保存期限、廠商資訊之類的？！&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider02/food_stmt.jpg" alt="食物類商品缺少規格？" data-caption="食物類商品缺少規格？" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
食物類商品缺少規格？
&lt;/figcaption>
&lt;/figure>
&lt;p>我實際尋找後發現，這部分要再透過另一個請求去取得：&lt;/p>
&lt;p>請求網址：&lt;code>https://ecapi-pchome.cdn.hinet.net/cdn/ecshop/prodapi/v2/prod/DBAEF6-A900AK8ZY/foodcontents&amp;amp;_callback=jsonp_fooddesc&lt;/code>&lt;br />
請求方法：&lt;code>GET&lt;/code>&lt;/p>
&lt;p>可是還有個問題，我要怎麼資料它是不是食物呢？&lt;br />
這就回到「&lt;a href="#%e5%95%86%e5%93%81%e5%9f%ba%e6%9c%ac%e8%b3%87%e6%96%99" target="_blank" rel="noopener">
商品規格
&lt;/a>」章節中的&amp;quot;回傳資料&amp;quot;，回傳資料內就有一個&amp;quot;isFoodContents&amp;quot;欄位，就會寫到是否有食物含量，就可以知道是否還要再送出這個請求，來取得完整的資料。&lt;/p>
&lt;p>當然，除了食物類的商品，我猜應該還有許多其他商品會又另外的請求。&lt;/p>
&lt;h3 id="範例程式-1">範例程式&lt;/h3>
&lt;p>&amp;quot;商品描述(標語、規格、備註)&amp;quot;部分範例程式如下，完整程式碼在文章最後會附上。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_product_description&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">product_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">fields&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">None&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;取得商品描述(標語、規格、備註)
&lt;/span>&lt;span class="s2">
&lt;/span>&lt;span class="s2"> :param product_id: 商品 ID
&lt;/span>&lt;span class="s2"> :param fields: 指定欄位
&lt;/span>&lt;span class="s2"> :return data: 商品描述資料
&lt;/span>&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="c1"># &amp;amp;fields=Id,Stmt,Equip,Remark,Liability,Kword,Slogan,Author,Brand,Meta,Transman,Pubunit,Pubdate,Approve&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://ecapi-pchome.cdn.hinet.net/cdn/ecshop/prodapi/v2/prod/{product_id}/desc&amp;#39;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">fields&lt;/span> &lt;span class="ow">is&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="bp">None&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;&amp;amp;fields={fields}&amp;#39;&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="s1">&amp;#39;&amp;amp;_callback=jsonp_prod&amp;#39;&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">request_get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">to_json&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">False&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 去除前後 JS 語法字串&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">loads&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">15&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">48&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">data&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="商品詳細介紹">商品詳細介紹&lt;/h2>
&lt;p>這邊所說的商品詳細介紹，是指商品頁面中間的&amp;quot;本商品詳細介紹&amp;quot;，內容可能有文字、圖片或影片。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider02/product_intro.jpg" alt="商品詳細介紹" data-caption="商品詳細介紹" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
商品詳細介紹
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="請求路徑與參數-2">請求路徑與參數&lt;/h3>
&lt;div class="notices info" data-title="商品詳細介紹 請求">
請求網址：&lt;code>https://ecapi-pchome.cdn.hinet.net/cdn/ecshop/prodapi/v2/prod/DHAFI0-A900BAPXK/intro&amp;amp;_callback=jsonp_intro&lt;/code>&lt;br />
請求方法：&lt;code>GET&lt;/code>
&lt;/div>
&lt;br/>
&lt;p>同樣也有 &lt;code>fields&lt;/code> 參數來指定你想要哪些欄位。&lt;/p>
&lt;h3 id="回傳資料-2">回傳資料&lt;/h3>
&lt;p>這邊範例我使用&lt;a href="https://24h.pchome.com.tw/prod/DEBB55-A900AUAHM" target="_blank" rel="noopener">
另個商品
&lt;/a>示範，因為它有包含文字、圖片跟影片。&lt;/p>
&lt;p>將回傳資料去除前後 JS 語法後，可以看出裡頭是以陣列(列表)的形式，每部分裡有 &lt;code>Sort&lt;/code> 標示著順序，資料有文字 &lt;code>Intro&lt;/code> 與圖片 &lt;code>Pic&lt;/code> 兩種，圖片路徑需加上 &lt;code>https://e.ecimg.tw&lt;/code> 才是完整的網址。&lt;br />
文字又是以 HTML 的格式紀錄，因此也可以崁入 YouTube 影片，像是底下範例中的第三部分。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-JSON" data-lang="JSON">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;DEBB55-A900AUAHM&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;Id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DEBB55-A900AUAHM&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Pic&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Pstn&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;M&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Intro&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;p align=\&amp;#34;center\&amp;#34;&amp;gt;&amp;lt;strong&amp;gt;&amp;lt;span style=\&amp;#34;font-family: 標楷體; font-size: xx-large; color: #ff0000;\&amp;#34;&amp;gt;【PX 大通】 C52G 夜視高畫質GPS行車記錄器&amp;lt;/span&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Sort&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;1&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;Id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DEBB55-A900AUAHM&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Pic&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;/items/DEBB55A900AUAHM/i010002_1600054259.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Pstn&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;M&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Intro&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Sort&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;2&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;Id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DEBB55-A900AUAHM&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Pic&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Pstn&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;M&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Intro&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;lt;center&amp;gt;&amp;lt;iframe src=\&amp;#34;https://www.youtube.com/embed/S28ZIbO9QJw\&amp;#34; frameborder=\&amp;#34;0\&amp;#34; width=\&amp;#34;1040\&amp;#34; height=\&amp;#34;765\&amp;#34;&amp;gt;&amp;lt;/iframe&amp;gt;&amp;lt;center&amp;gt;&amp;lt;iframe src=\&amp;#34;https://www.youtube.com/embed/BEw8bT3uPpw\&amp;#34; frameborder=\&amp;#34;0\&amp;#34; width=\&amp;#34;1040\&amp;#34; height=\&amp;#34;765\&amp;#34;&amp;gt;&amp;lt;/iframe&amp;gt;&amp;lt;/center&amp;gt;&amp;lt;/center&amp;gt;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Sort&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;3&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;Id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DEBB55-A900AUAHM&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Pic&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;/items/DEBB55A900AUAHM/i010015_1598511521.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Pstn&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;M&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Intro&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Sort&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;4&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="範例程式-2">範例程式&lt;/h3>
&lt;p>&amp;quot;商品詳細介紹&amp;quot;部分範例程式如下，完整程式碼在文章最後會附上。&lt;br />
這邊我是讓它依照 &lt;code>Sort&lt;/code> 數字由小到大排順序，再用字串拼接起來。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_product_introduction&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">product_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">fields&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">None&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;取得商品詳細介紹(包含圖片、影片)
&lt;/span>&lt;span class="s2">
&lt;/span>&lt;span class="s2"> :param product_id: 商品 ID
&lt;/span>&lt;span class="s2"> :param fields: 指定欄位
&lt;/span>&lt;span class="s2"> :return introduction: 商品詳細介紹字串
&lt;/span>&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="c1"># &amp;amp;fields=Id,Pic,Pstn,Intro,Sort&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://ecapi-pchome.cdn.hinet.net/cdn/ecshop/prodapi/v2/prod/{product_id}/intro&amp;#39;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">fields&lt;/span> &lt;span class="ow">is&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="bp">None&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;&amp;amp;fields={fields}&amp;#39;&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="s1">&amp;#39;&amp;amp;_callback=jsonp_intro&amp;#39;&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">request_get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">to_json&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">False&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 去除前後 JS 語法字串&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">loads&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">16&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">48&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="n">introduction&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>
&lt;span class="c1"># 依照 Sort 欄位數字由小到大排順序&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">sorted&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">product_id&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="n">key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="k">lambda&lt;/span> &lt;span class="n">k&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">k&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;Sort&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">intro&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">intro&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;Pic&amp;#39;&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;span class="n">introduction&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">introduction&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="s1">&amp;#39;https://e.ecimg.tw&amp;#39;&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">intro&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;Pic&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">introduction&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">introduction&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">intro&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;Intro&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">introduction&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="加購商品">加購商品&lt;/h2>
&lt;p>在商品的頁面，有時會出現&amp;quot;加購商品&amp;quot;這個區塊，但不是每個商品都有。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider02/add_buy.jpg" alt="加購商品" data-caption="加購商品" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
加購商品
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="請求路徑與參數-3">請求路徑與參數&lt;/h3>
&lt;div class="notices info" data-title="加購商品 請求">
請求網址：&lt;code>https://ecapi-pchome.cdn.hinet.net/cdn/ecshop/prodapi/v2/prod/DHAFI0-A900BAPXK/add&amp;amp;_callback=jsonp_add&lt;/code>&lt;br />
請求方法：&lt;code>GET&lt;/code>
&lt;/div>
&lt;br/>
&lt;p>這邊我發現如果不加 &lt;code>fields&lt;/code> 參數，預設回傳資料內會缺少 &lt;code>Price&lt;/code>、&lt;code>isWarranty&lt;/code> 欄位。&lt;/p>
&lt;p>原先網站給的 &lt;code>fields=Seq,Id,Name,Spec,Group,Price,Pic,Qty,isWarranty&lt;/code>。&lt;/p>
&lt;h3 id="回傳資料-3">回傳資料&lt;/h3>
&lt;p>一樣先要將回傳資料去除前後的 JS 語法，如果多項贈品，那這邊也會顯示多個，字典的 key(鍵) 代表此商品的 ID。&lt;br />
(此範例商品應該會有三個贈品，但為了讓文章版面不要太長，我有將其刪減)&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-JSON" data-lang="JSON">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;DHAA2D-A900AQGVA&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;Seq&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">24988216&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DHAA2D-A900AQGVA-000&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;【加購現省】中文 Microsoft 365 家用版一年盒裝&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Spec&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Group&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Price&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="nt">&amp;#34;M&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">4190&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nt">&amp;#34;P&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">2790&lt;/span>&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;Pic&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;B&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;/items/DHAA2DA900AQGVA/000001_1593137612.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;S&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;/items/DHAA2DA900AQGVA/000002_1593137612.jpg&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;Qty&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">20&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isWarranty&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;DSAEAW-A900B8SRF&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;Seq&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">26572469&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DSAEAW-A900B8SRF-000&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Microsoft 365 個人版 15個月訂閱-ESD金鑰卡(不能退貨)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Spec&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Group&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Price&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="nt">&amp;#34;M&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nt">&amp;#34;P&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">2190&lt;/span>&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;Pic&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;B&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;/items/DSAEAWA900B8SRF/000001_1618314609.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;S&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;/items/DSAEAWA900B8SRF/000002_1618314609.jpg&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;Qty&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">20&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isWarranty&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="加購商品介紹">加購商品介紹&lt;/h4>
&lt;p>順帶一提，如果你想取得加購商品的簡介(下圖綠色方框)的話，需要透過另外一個請求。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider02/add_buy_slogan.jpg" alt="加購商品" data-caption="加購商品" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
加購商品
&lt;/figcaption>
&lt;/figure>
&lt;p>請求網址：&lt;code>https://ecapi-pchome.cdn.hinet.net/cdn/ecshop/prodapi/v2/prod/desc&amp;amp;id=DHAA2D-A900AQGVA,DSAEAW-A900B8SRF&amp;amp;_callback=jsonp_adddesc&lt;/code>&lt;br />
請求方法：&lt;code>GET&lt;/code>&lt;/p>
&lt;p>&lt;code>id&lt;/code> 請改成贈品的 ID，一次帶入多個商品一樣將商品 ID 以 &lt;code>,&lt;/code> 連接即可。&lt;/p>
&lt;br/>
&lt;p>而且我發現他請求網址跟「&lt;a href="#%e5%95%86%e5%93%81%e6%8f%8f%e8%bf%b0%28%e6%a8%99%e8%aa%9e%e3%80%81%e8%a6%8f%e6%a0%bc%e3%80%81%e5%82%99%e8%a8%bb%29" target="_blank" rel="noopener">
商品描述(標語、規格、備註)
&lt;/a>」的非常像，取得的回傳資料也是一模一樣，所以我猜兩這是通用的。&lt;br />
&amp;quot;商品描述&amp;quot;請求網址：&lt;code>https://ecapi-pchome.cdn.hinet.net/cdn/ecshop/prodapi/v2/prod/DHAFI0-A900BAPXK/desc&lt;/code>&lt;/p>
&lt;h3 id="範例程式-3">範例程式&lt;/h3>
&lt;p>&amp;quot;加購商品&amp;quot;部分範例程式如下，完整程式碼在文章最後會附上。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_add_buy_product&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">product_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">fields&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">None&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;取得加購商品
&lt;/span>&lt;span class="s2">
&lt;/span>&lt;span class="s2"> :param product_id: 商品 ID
&lt;/span>&lt;span class="s2"> :param fields: 指定欄位
&lt;/span>&lt;span class="s2"> :return data: 加購商品
&lt;/span>&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="c1"># &amp;amp;fields=Seq,Id,Name,Spec,Group,Price,Pic,Qty,isWarranty&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://ecapi-pchome.cdn.hinet.net/cdn/ecshop/prodapi/v2/prod/{product_id}/add&amp;#39;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">fields&lt;/span> &lt;span class="ow">is&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="bp">None&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;&amp;amp;fields={fields}&amp;#39;&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="s1">&amp;#39;&amp;amp;_callback=jsonp_add&amp;#39;&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">request_get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">to_json&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">False&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 去除前後 JS 語法字串&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">loads&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">14&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">48&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">data&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;!--adsense-->
&lt;h2 id="完整程式碼">完整程式碼&lt;/h2>
&lt;p>附上完整程式碼：&lt;a href="https://blog.jiatool.com/code/pchome_spider02.py" target="_blank" rel="noopener">
pchome_spider02.py
&lt;/a>&lt;br />
(對超連結右鍵 &amp;gt; 另存連結為)&lt;/p>
&lt;h2 id="延伸練習">延伸練習&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>有些商品的頁面會有「贈品」可以選取，試試看，你有辦法抓取贈品的資訊嗎？&lt;br />
範例商品：&lt;a href="https://24h.pchome.com.tw/prod/DCAN8J-A900AW0AQ">https://24h.pchome.com.tw/prod/DCAN8J-A900AW0AQ&lt;/a>&lt;br />
(小提示：可以使用贈品的名稱或 ID 在 開發人員工具 &amp;gt; Network 中搜尋 Ctrl + f)&lt;/p>
&lt;/li>
&lt;li>
&lt;p>在某些商品頁面會發現有「買此商品的人也買了&amp;hellip;」區塊，這部分的資訊我們也可以取得嗎？&lt;br />
範例商品：&lt;a href="https://24h.pchome.com.tw/prod/DCAN8J-A9009OS4V">https://24h.pchome.com.tw/prod/DCAN8J-A9009OS4V&lt;/a>&lt;br />
(小提示：這部分會先取得推薦的名單，再透過「取得商品資訊」章節的請求來取得詳細資訊)&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>在尋找 PChome 的請求網址、邏輯時，我還發現一個&amp;quot;prodjsv3-&amp;quot;開頭的 JavaScript 檔案，裡面可以找出許多不同請求的端倪，你們可以從中尋找還有哪些請求。&lt;br />
(迷之音：請求有夠多，全部要找要寫出來太花時間，叫網友自己去找好了，嗯~還可以順便說是給他們練習，不錯XD)&lt;/p>
&lt;p>之後還會陸續寫一些網站的&amp;quot;網路爬蟲實例&amp;quot;，如果此篇文章有幫助到你，歡迎在底下留言、留言，還有追蹤 FB 粉專『&lt;a href="https://www.facebook.com/jiatool" target="_blank" rel="noopener">
IT空間
&lt;/a>』~ 🔔&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;blockquote>
&lt;p>在這個世界上，沒有人能使你倒下。如果你自己的信念還站立的話。&lt;br />
In this world, no one can make you fall. If your faith is still standing.&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/pchome_spider02.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/pchome_spider02_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Python</category><category>PChome</category><category>網路爬蟲</category><category>Python網路爬蟲實例</category></item><item><title>[Python爬蟲實例] PChome 線上購物 (上篇)</title><link>https://blog.jiatool.com/posts/pchome_spider01/</link><pubDate>Sun, 25 Apr 2021 20:45:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sun, 25 Apr 2021 20:45:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/pchome_spider01/</guid><description>前言 在之前的 Python 網路爬蟲實例講解過蝦皮購物 ，而今日要來講解同樣在台灣非常多人使用的「PChome 線上購物 」。 實際操作後發現，PChome 在一個</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>在之前的 Python 網路爬蟲實例講解過&lt;a href="https://blog.jiatool.com/posts/shopee_spider/" target="_blank" rel="noopener">
蝦皮購物
&lt;/a>，而今日要來講解同樣在台灣非常多人使用的「&lt;a href="https://shopping.pchome.com.tw/" target="_blank" rel="noopener">
PChome 線上購物
&lt;/a>」。&lt;/p>
&lt;p>實際操作後發現，PChome 在一個頁面中針對不同部分的資料有送出不同的請求，整理成一篇會太長，因此我將分為上下篇來介紹。&lt;br />
上篇也就是你正在看的本篇，主要講解在 &lt;a href="https://ecshweb.pchome.com.tw/search/v3.3/?q=%E6%BB%91%E9%BC%A0" target="_blank" rel="noopener">
PChome 搜尋頁面
&lt;/a>的請求，而下篇是說明&lt;a href="https://24h.pchome.com.tw/prod/DCAN8J-A9008YONC" target="_blank" rel="noopener">
商品頁面
&lt;/a>的請求。&lt;/p>
&lt;ul>
&lt;li>PChome 線上購物 網路爬蟲實例 (上篇) =&amp;gt; 本篇&lt;/li>
&lt;li>&lt;a href="https://blog.jiatool.com/posts/pchome_spider02" target="_blank" rel="noopener">
PChome 線上購物 網路爬蟲實例 (下篇)
&lt;/a>&lt;/li>
&lt;/ul>
&lt;br/>
&lt;p>* 「&lt;a href="https://shopping.pchome.com.tw/" target="_blank" rel="noopener">
PChome 線上購物
&lt;/a>」與「&lt;a href="https://24h.pchome.com.tw/" target="_blank" rel="noopener">
PChome 24h購物
&lt;/a>」兩者的商品搜尋都是導到同樣的頁面，因此實際上是一樣的。&lt;/p>
&lt;p>備註：此文僅教育學習，切勿用作商業用途，個人實作皆屬個人行為，本作者不負任何法律責任&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider01/online_shopping.jpg" alt="線上購物 (來源：Pexels)" data-caption="線上購物 (來源：Pexels)" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
線上購物 (來源：Pexels)
&lt;/figcaption>
&lt;/figure>
&lt;h2 id="套件">套件&lt;/h2>
&lt;p>此次 Python 爬蟲主要使用到的套件：&lt;/p>
&lt;ul>
&lt;li>Requests [&lt;a href="https://requests.readthedocs.io/en/master/" target="_blank" rel="noopener">
Doc
&lt;/a>] [&lt;a href="https://github.com/psf/requests" target="_blank" rel="noopener">
GitHub
&lt;/a>]&lt;/li>
&lt;/ul>
&lt;p>安裝&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">pip install requests
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;!--adsense-->
&lt;h2 id="搜尋商品">搜尋商品&lt;/h2>
&lt;p>進入 &lt;a href="https://shopping.pchome.com.tw/" target="_blank" rel="noopener">
PChome 線上購物
&lt;/a> 網頁，先開啟瀏覽器的 &lt;strong>開發人員工具&lt;/strong> (F12 或 Ctrl + Shift + i)，回到網頁左上角輸入想要搜尋的關鍵字，點擊&amp;quot;找商品&amp;quot;。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider01/search_block.jpg" alt="首頁左上角搜尋欄位" data-caption="首頁左上角搜尋欄位" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
首頁左上角搜尋欄位
&lt;/figcaption>
&lt;/figure>
&lt;p>畫面跳轉到搜尋結果頁面後，開發人員工具切換到&amp;quot;Network&amp;quot; &amp;gt; &amp;quot;XHR&amp;quot;，會發現其中一個請求包含著搜尋結果，而 &lt;code>prods&lt;/code> 欄位內分別列出了每一項商品。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider01/xhr_results.png" alt="&amp;#34;Network&amp;#34; &amp;gt; &amp;#34;XHR&amp;#34; 頁面" data-caption="&amp;#34;Network&amp;#34; &amp;gt; &amp;#34;XHR&amp;#34; 頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;Network&amp;#34; &amp;gt; &amp;#34;XHR&amp;#34; 頁面
&lt;/figcaption>
&lt;/figure>
&lt;p>切換到&amp;quot;Headers&amp;quot;頁面可以查看請求的網址與方法。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider01/headers.png" alt="&amp;#34;Headers&amp;#34; 頁面" data-caption="&amp;#34;Headers&amp;#34; 頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;Headers&amp;#34; 頁面
&lt;/figcaption>
&lt;/figure>
&lt;p>我們可以開一個新分頁，將此請求網址貼上前往，查看回傳的資料是否正確、長什麼樣子。&lt;/p>
&lt;h3 id="請求路徑與參數">請求路徑與參數&lt;/h3>
&lt;div class="notices info" data-title="搜尋商品 請求">
請求網址：&lt;code>https://ecshweb.pchome.com.tw/search/v3.3/all/results?q=%E9%8D%B5%E7%9B%A4&amp;amp;page=1&amp;amp;sort=sale/dc&lt;/code>&lt;br />
請求方法：&lt;code>GET&lt;/code>
&lt;/div>
&lt;br/>
&lt;p>商品搜尋頁面有多項篩選條件，從下圖可以看到有關鍵字、商店類別、排序、取貨方式、價格範圍、依館別顯示等等。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider01/filter.jpg" alt="搜尋頁面 篩選功能" data-caption="搜尋頁面 篩選功能" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
搜尋頁面 篩選功能
&lt;/figcaption>
&lt;/figure>
&lt;p>而這些篩選條件正好對應網址後方帶的參數，我實際一個一個測試後，整理出來如下：&lt;/p>
&lt;p>&lt;strong>關鍵字&lt;/strong>&lt;br />
放在 &lt;code>q&lt;/code> 參數內。&lt;/p>
&lt;p>&lt;strong>商店類別&lt;/strong>&lt;br />
放在網址路徑內，可參考下方程式。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>數值&lt;/th>
&lt;th>意思&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>all&lt;/code>&lt;/td>
&lt;td>全部&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>24h&lt;/code>&lt;/td>
&lt;td>24h購物&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>24b&lt;/code>&lt;/td>
&lt;td>24h書店&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>vdr&lt;/code>&lt;/td>
&lt;td>廠商出貨&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>tour&lt;/code>&lt;/td>
&lt;td>PChome旅遊&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>排序&lt;/strong>&lt;br />
&lt;code>sort&lt;/code> 參數。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>數值&lt;/th>
&lt;th>意思&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>sale/dc&lt;/code>&lt;/td>
&lt;td>有貨優先&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>rnk/dc&lt;/code>&lt;/td>
&lt;td>精準度&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>prc/dc&lt;/code>&lt;/td>
&lt;td>價錢由高至低&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>prc/ac&lt;/code>&lt;/td>
&lt;td>價錢由低至高&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>new/dc&lt;/code>&lt;/td>
&lt;td>新上市&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>取貨方式&lt;/strong>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>數值&lt;/th>
&lt;th>意思&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>cvs=all&lt;/code>&lt;/td>
&lt;td>超商取貨&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>ipost=Y&lt;/code>&lt;/td>
&lt;td>i 郵箱取貨&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>價格範圍&lt;/strong>&lt;br />
&lt;code>price&lt;/code> 參數。&lt;br />
我測試的結果是兩者都要，也就是要包含最大金額與最小金額的限制。&lt;br />
&lt;code>{price_max}-{price_min}&lt;/code>&lt;/p>
&lt;p>&lt;strong>頁數&lt;/strong>&lt;br />
&lt;code>page&lt;/code> 參數。&lt;br />
回傳資料預設是 20 筆商品，如果要繼續往後抓取，需要帶入頁數參數。&lt;/p>
&lt;h3 id="回傳資料">回傳資料&lt;/h3>
&lt;p>它以 JSON 格式回傳，商品會在 prods 欄位內，每一個商品資料如下：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-JSON" data-lang="JSON">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;Id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DGCD1E-A900AIK2Q&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;cateId&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DGCA3Q&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;picS&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;/items/DGCD1EA900AIK2Q/000002_1582170821.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;picB&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;/items/DGCD1EA900AIK2Q/000001_1617156434.jpg&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;SanDisk USB Type-C™ 雙用隨身碟128GB (公司貨)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;describe&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;具備usb type-c與type-a旋轉式2合1金屬隨身碟。...&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;price&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">629&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;originPrice&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">629&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;author&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;brand&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;publishDate&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;sellerId&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isPChome&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isNC17&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;couponActid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[],&lt;/span>
&lt;span class="nt">&amp;#34;BU&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;ec&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>以上有許多欄位，這邊挑幾個已知道意思的來說明：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>欄位&lt;/th>
&lt;th>代表意思&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Id&lt;/td>
&lt;td>商品ID&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>cateId&lt;/td>
&lt;td>分類ID&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>picS&lt;/td>
&lt;td>商品圖片(縮圖)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>picB&lt;/td>
&lt;td>商品圖片(主圖)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>name&lt;/td>
&lt;td>商品名稱&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>describe&lt;/td>
&lt;td>商品描述&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>price&lt;/td>
&lt;td>商品價格&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>originPrice&lt;/td>
&lt;td>商品原始價格&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>author&lt;/td>
&lt;td>(書籍)作者&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>brand&lt;/td>
&lt;td>(書籍)出版社&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>publishDate&lt;/td>
&lt;td>(書籍)出版日期&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>isNC17&lt;/td>
&lt;td>是否限制級&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>商品圖片分為&amp;quot;picS&amp;quot;與&amp;quot;picB&amp;quot;，查看後我猜測&amp;quot;picS&amp;quot;是在搜尋頁面的圖片，而&amp;quot;picB&amp;quot;是位於商品本身頁面的。&lt;/p>
&lt;p>前方再加上 &lt;code>https://d.ecimg.tw&lt;/code> 即圖片完整網址。&lt;br />
如 &lt;code>https://d.ecimg.tw/items/DGCD1EA900AIK2Q/000002_1582170821.jpg&lt;/code>。&lt;/p>
&lt;p>&amp;quot;商品網址&amp;quot;是商品ID前方加上 &lt;code>https://24h.pchome.com.tw/prod/&lt;/code>，以上方為例就是：&lt;br />
&lt;code>https://24h.pchome.com.tw/prod/DGCD1E-A900AIK2Q&lt;/code>&lt;/p>
&lt;h3 id="範例程式">範例程式&lt;/h3>
&lt;p>&amp;quot;搜尋商品&amp;quot;部分範例程式如下，完整程式碼在文章最後會附上。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">search_products&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">keyword&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">max_page&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">shop&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;全部&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">sort&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;有貨優先&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">price_min&lt;/span>&lt;span class="o">=-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">price_max&lt;/span>&lt;span class="o">=-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">is_store_pickup&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">False&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">is_ipost_pickup&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">False&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;搜尋商品
&lt;/span>&lt;span class="s2">
&lt;/span>&lt;span class="s2"> :param keyword: 搜尋關鍵字
&lt;/span>&lt;span class="s2"> :param max_page: 抓取最大頁數
&lt;/span>&lt;span class="s2"> :param shop: 賣場類別 (全部、24h購物、24h書店、廠商出貨、PChome旅遊)
&lt;/span>&lt;span class="s2"> :param sort: 商品排序 (有貨優先、精準度、價錢由高至低、價錢由低至高、新上市)
&lt;/span>&lt;span class="s2"> :param price_min: 篩選&amp;#34;最低價&amp;#34; (需與 price_max 同時用)
&lt;/span>&lt;span class="s2"> :param price_max: 篩選&amp;#34;最高價&amp;#34; (需與 price_min 同時用)
&lt;/span>&lt;span class="s2"> :param is_store_pickup: 篩選&amp;#34;超商取貨&amp;#34;
&lt;/span>&lt;span class="s2"> :param is_ipost_pickup: 篩選&amp;#34;i 郵箱取貨&amp;#34;
&lt;/span>&lt;span class="s2"> :return products: 搜尋結果商品
&lt;/span>&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">products&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;span class="n">all_shop&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;全部&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;all&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;24h購物&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;24h&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;24h書店&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;24b&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;廠商出貨&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;vdr&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;PChome旅遊&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;tour&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">all_sort&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;有貨優先&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;sale/dc&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;精準度&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;rnk/dc&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;價錢由高至低&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;prc/dc&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;價錢由低至高&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;prc/ac&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;新上市&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;new/dc&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://ecshweb.pchome.com.tw/search/v3.3/{all_shop[shop]}/results&amp;#39;&lt;/span>
&lt;span class="n">params&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;q&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">keyword&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;sort&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">all_sort&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">sort&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="s1">&amp;#39;page&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">price_min&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="ow">and&lt;/span> &lt;span class="n">price_max&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">params&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;price&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;{price_min}-{price_max}&amp;#39;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">is_store_pickup&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">params&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;cvs&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;all&amp;#39;&lt;/span> &lt;span class="c1"># 超商取貨&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">is_ipost_pickup&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">params&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;ipost&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;Y&amp;#39;&lt;/span> &lt;span class="c1"># i 郵箱取貨&lt;/span>
&lt;span class="k">while&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;page&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">max_page&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">params&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;page&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">request_get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;請求發生錯誤：{url}{params}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">break&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;totalRows&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;找不到有關的產品&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">break&lt;/span>
&lt;span class="n">products&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extend&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;prods&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;totalPage&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;page&amp;#39;&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;span class="k">break&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">products&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="商品販售狀態">商品販售狀態&lt;/h2>
&lt;p>如果你還想要&amp;quot;商品販售狀態&amp;rdquo;，會發現此欄位不包含在上方&amp;quot;搜尋商品&amp;quot;請求的回傳資料中，我們要再從其他的地方找找。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider01/sale_status.jpg" alt="商品狀態按鈕" data-caption="商品狀態按鈕" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='200px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:200px;height:;"/>
&lt;figcaption style="text-align: center;">
商品狀態按鈕
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>試試用&amp;quot;立即訂購&amp;quot;之類的關鍵字在開發人員工具中搜尋，在某個搜尋到的 JavaScript 檔案發現到&amp;quot;orderNow&amp;quot;、&amp;quot;soldOut&amp;quot;等字眼。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider01/searchplus_js.jpg" alt="searchplus JS" data-caption="searchplus JS" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
searchplus JS
&lt;/figcaption>
&lt;/figure>
&lt;p>再進一步以&amp;quot;soldOut&amp;quot;搜尋，在另外一個 JavaScript 檔案發現到此資訊。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider01/button_js.png" alt="button JS" data-caption="button JS" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
button JS
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>雖然它是 JS 檔，但你只要把網址後方的 &lt;code>&amp;amp;_callback=jsonpcb_button&lt;/code> 刪掉，它就會以 JSON 格式回傳了。&lt;/p>
&lt;h3 id="請求路徑與參數-1">請求路徑與參數&lt;/h3>
&lt;p>請求網址路徑很大一串，經過我刪減、測試，其實最少只需要如下：&lt;/p>
&lt;div class="notices info" data-title="商品販售狀態 請求">
請求網址：&lt;code>https://ecapi.pchome.com.tw/ecshop/prodapi/v2/prod/button&amp;amp;id=DRAD1K-A900AWN96&lt;/code>&lt;br />
請求方法：&lt;code>GET&lt;/code>
&lt;/div>
&lt;p>如果需要，可以一次帶入多個商品一次請求，只需將商品 ID 以 &lt;code>,&lt;/code> 連接，例如：&lt;br />
&lt;code>https://ecapi.pchome.com.tw/ecshop/prodapi/v2/prod/button&amp;amp;id=DRAD1K-A900AWN96,DSAA6I-A900B3488&lt;/code>&lt;br />
就不需要分多次請求了。&lt;/p>
&lt;p>也可以透過 &lt;code>fields&lt;/code> 參數來指定你想要那些欄位，例如我只要商品ID、商品數量、商品狀態：&lt;br />
&lt;code>https://ecapi.pchome.com.tw/ecshop/prodapi/v2/prod/button&amp;amp;id=DRAD1K-A900AWN96&amp;amp;fields=Id,Qty,ButtonType&lt;/code>&lt;/p>
&lt;h3 id="回傳資料-1">回傳資料&lt;/h3>
&lt;p>它一樣以 JSON 格式回傳：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-JSON" data-lang="JSON">&lt;span class="p">[{&lt;/span>
&lt;span class="nt">&amp;#34;Seq&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">25977002&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DCAD6E-A900B1YM4-000&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Store&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DCAD6E&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Price&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="nt">&amp;#34;M&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nt">&amp;#34;P&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">550&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nt">&amp;#34;Prime&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;Qty&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">7&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;ButtonType&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;ForSale&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;SaleStatus&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Group&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DCAD6E-A900B1YM4&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isPrimeOnly&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;SpecialQty&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="p">}]&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>從 &lt;code>ButtonType&lt;/code> 的值可以看出此商品是否還有貨，像是 ForSale 代表此商品有出售、可以購買；SoldOut 代表此商品已售完等等。&lt;/p>
&lt;h3 id="範例程式-1">範例程式&lt;/h3>
&lt;p>&amp;quot;商品販售狀態&amp;quot;部分範例程式如下，完整程式碼在文章最後會附上。&lt;/p>
&lt;p>這邊我設計成傳入單個商品的字串(String)，或多個商品的字串陣列(List)都可以，比較彈性。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_products_sale_status&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">products_id&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;取得商品販售狀態
&lt;/span>&lt;span class="s2">
&lt;/span>&lt;span class="s2"> :param products_id: 商品 ID
&lt;/span>&lt;span class="s2"> :return data: 商品販售狀態資料
&lt;/span>&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="nb">type&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">products_id&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">products_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;,&amp;#39;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">products_id&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://ecapi.pchome.com.tw/ecshop/prodapi/v2/prod/button&amp;amp;id={products_id}&amp;#39;&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">request_get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;請求發生錯誤：{url}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">data&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="商品規格種類">商品規格種類&lt;/h2>
&lt;p>除了&amp;quot;商品狀態&amp;quot;不在原本的回傳資料中，還有某些商品有不同的規格，這部分也是要另外抓。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider01/product_specification.jpg" alt="商品規格種類" data-caption="商品規格種類" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
商品規格種類
&lt;/figcaption>
&lt;/figure>
&lt;p>一樣透過搜尋，找到了一個請求的路徑。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider01/spec_url.png" alt="查找&amp;#34;商品規格種類&amp;#34;路徑" data-caption="查找&amp;#34;商品規格種類&amp;#34;路徑" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
查找&amp;#34;商品規格種類&amp;#34;路徑
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="請求路徑與參數-2">請求路徑與參數&lt;/h3>
&lt;div class="notices info" data-title="商品規格種類 請求">
請求網址：&lt;code>https://ecapi.pchome.com.tw/ecshop/prodapi/v2/prod/spec&amp;amp;id=DYARL9-A900AZTJT&amp;amp;_callback=jsonpcb_spec&lt;/code>&lt;br />
請求方法：&lt;code>GET&lt;/code>
&lt;/div>
&lt;p>&lt;code>id&lt;/code> 就是給你要找的商品 ID。&lt;br />
跟上一節&amp;quot;商品販售狀態&amp;quot;一樣，如需一次請求多個商品，只需將商品 ID 以 &lt;code>,&lt;/code> 連接，例如：&lt;br />
&lt;code>https://ecapi.pchome.com.tw/ecshop/prodapi/v2/prod/spec&amp;amp;id=DYARL9-A900AZTJT,DYARLA-A900AZTJJ&amp;amp;_callback=jsonpcb_spec&lt;/code>&lt;/p>
&lt;h3 id="回傳資料-2">回傳資料&lt;/h3>
&lt;p>這邊有個小小麻煩的點，如果像&amp;quot;商品販售狀態&amp;quot;一樣把後方 &lt;code>_callback=json...&lt;/code> 去除，反而它就不回傳資料了，但加了這樣會使得回傳資料前後會有一段 JS 語法，所以我們要先將其字串移除後，才是正確的 JSON 格式。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-JavaScript" data-lang="JavaScript">&lt;span class="k">try&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nx">jsonpcb_spec&lt;/span>&lt;span class="p">({&lt;/span>
&lt;span class="s2">&amp;#34;DYARIO-A900B0P77&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[{&lt;/span>
&lt;span class="s2">&amp;#34;Seq&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="mi">25866719&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">...(&lt;/span>&lt;span class="nx">省略&lt;/span>&lt;span class="p">)...&lt;/span>
&lt;span class="s2">&amp;#34;PreOrdDate&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>
&lt;span class="p">}]&lt;/span>
&lt;span class="p">});&lt;/span>
&lt;span class="p">}&lt;/span> &lt;span class="k">catch&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nx">e&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">window&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">console&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nx">console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">log&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nx">e&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>* 題外話：我原本是想用 &lt;code>str.lstrip()&lt;/code>、&lt;code>str.rstrip()&lt;/code> 去移除，但遇到了點問題，所以後來改用字串切割的方式。&lt;/p>
&lt;br/>
&lt;p>去除前後 JS 語法後回傳資料範例：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-JSON" data-lang="JSON">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;DYARL9-A900AZTJT&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;Seq&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">25787942&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DYARL9-A900AZTJT-001&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;防摔！四角加厚空壓殼 iPhone 12 / i12 手機殼 保護殼 手機套 軟殼 保護套 防撞&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Spec&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;透藍&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Group&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DYARL9-A900AZTJT&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Pic&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;B&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;S&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;Qty&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isPreOrder24h&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;PreOrdDate&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;Seq&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">25787944&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DYARL9-A900AZTJT-003&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;防摔！四角加厚空壓殼 iPhone 12 / i12 手機殼 保護殼 手機套 軟殼 保護套 防撞&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Spec&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;透粉&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Group&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DYARL9-A900AZTJT&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Pic&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;B&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;S&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;Qty&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">6&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isPreOrder24h&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;PreOrdDate&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="範例程式-2">範例程式&lt;/h3>
&lt;p>&amp;quot;商品規格種類&amp;quot;部分範例程式如下，完整程式碼同樣在文章最後會附上。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_products_specification&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">products_id&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;取得商品規格種類
&lt;/span>&lt;span class="s2">
&lt;/span>&lt;span class="s2"> :param products_id: 商品 ID
&lt;/span>&lt;span class="s2"> :return data: 商品規格種類
&lt;/span>&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="nb">type&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">products_id&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">products_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;,&amp;#39;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">products_id&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://ecapi.pchome.com.tw/ecshop/prodapi/v2/prod/spec&amp;amp;id={products_id}&amp;amp;_callback=jsonpcb_spec&amp;#39;&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">request_get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">to_json&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">False&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 去除前後 JS 語法字串&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">loads&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">17&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">48&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">data&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="搜尋商品分類">搜尋商品分類&lt;/h2>
&lt;p>至於位於搜尋頁面的左側，這一大串的&amp;quot;分類&amp;quot;該從何而來？&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider01/search_category.jpg" alt="搜尋頁面的商品分類" data-caption="搜尋頁面的商品分類" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
搜尋頁面的商品分類
&lt;/figcaption>
&lt;/figure>
&lt;p>找到了一個請求的路徑。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider01/categories_url.png" alt="&amp;#34;搜尋商品分類&amp;#34;路徑" data-caption="&amp;#34;搜尋商品分類&amp;#34;路徑" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;搜尋商品分類&amp;#34;路徑
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="請求路徑與參數-3">請求路徑與參數&lt;/h3>
&lt;div class="notices info" data-title="搜尋商品分類 請求">
請求網址：&lt;code>https://ecshweb.pchome.com.tw/search/v3.3/all/categories?q=鍵盤&lt;/code>&lt;br />
請求方法：&lt;code>GET&lt;/code>
&lt;/div>
&lt;p>&lt;code>q&lt;/code> 後方就是接你是用什麼關鍵字搜尋商品的。&lt;/p>
&lt;h3 id="回傳資料-3">回傳資料&lt;/h3>
&lt;p>因為資料量比較大，我挑一小部分將解其結構：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-JSON" data-lang="JSON">&lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;Id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;D&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;24h購物&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;qty&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">12552&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;nodes&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;Id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DSAU&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DIY電腦&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;qty&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1418&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;nodes&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;Id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DSAUF4&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;qty&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">189&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;Id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DSAUF5&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;qty&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">176&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;Id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DSAUFA&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;qty&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">154&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>它是這樣由最大項分類一層一層下來，每一層會有 &lt;code>Id&lt;/code>、&lt;code>name&lt;/code>、&lt;code>qty&lt;/code> 等參數，代表此分類的&amp;quot;ID&amp;quot;、&amp;quot;名稱&amp;quot;、&amp;quot;商品數量&amp;quot;。&lt;/p>
&lt;p>但你可能會發現，怎麼到了最下面一層(第三層)卻沒了&amp;quot;名稱(&lt;code>name&lt;/code>)&amp;quot;？！&lt;br />
該不會&amp;hellip;對😅沒錯，它還要再透過另一個請求去取得，這部分會在下一章節介紹。&lt;/p>
&lt;h3 id="範例程式-3">範例程式&lt;/h3>
&lt;p>&amp;quot;搜尋商品分類&amp;quot;部分範例程式如下，很簡單，也沒什麼參數，完整程式碼同樣在文章最後會附上。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_search_category&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">keyword&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;取得搜尋商品分類(網頁左側)
&lt;/span>&lt;span class="s2">
&lt;/span>&lt;span class="s2"> :param keyword: 搜尋關鍵字
&lt;/span>&lt;span class="s2"> :return data: 分類資料
&lt;/span>&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://ecshweb.pchome.com.tw/search/v3.3/all/categories?q={keyword}&amp;#39;&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">request_get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">data&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>至於此分類該如何用來當搜尋商品的篩選條件，這部分就留給你們親自嘗試了，不會很複雜 (真的！)。&lt;/p>
&lt;h2 id="搜尋商品子分類名稱">搜尋商品子分類名稱&lt;/h2>
&lt;p>從上一章節，我們發現到商品分類的請求資料中，沒有包含最下面一層(第三層)的&amp;quot;name(名稱)&amp;quot;欄位。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/pchome_spider01/categories_name.jpg" alt="搜尋商品子分類名稱" data-caption="搜尋商品子分類名稱" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='200px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:200px;height:;"/>
&lt;figcaption style="text-align: center;">
搜尋商品子分類名稱
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="請求路徑與參數-4">請求路徑與參數&lt;/h3>
&lt;div class="notices info" data-title="搜尋商品子分類名稱 請求">
請求網址：&lt;code>https://ecapi-pchome.cdn.hinet.net/cdn/ecshop/cateapi/v1.5/store&amp;amp;id=DSAUF4&lt;/code>&lt;br />
請求方法：&lt;code>GET&lt;/code>
&lt;/div>
&lt;p>&lt;code>id&lt;/code> 後方接在上一章節&amp;quot;搜尋商品分類&amp;quot;中回傳的子分類。&lt;br />
一樣，如需一次請求多個商品，只需將子分類 ID 以 &lt;code>,&lt;/code> 連接，例如：&lt;br />
&lt;code>https://ecapi-pchome.cdn.hinet.net/cdn/ecshop/cateapi/v1.5/store&amp;amp;id=DSAUF4,DSAUF5,DSAUFA&amp;amp;fields=Id,Name&lt;/code>&lt;/p>
&lt;p>此請求路徑還有個 &lt;code>fields&lt;/code> 參數，可指定回傳欄位，例如我只要&amp;quot;ID&amp;quot;跟&amp;quot;名稱&amp;quot;：&lt;br />
&lt;code>https://ecapi-pchome.cdn.hinet.net/cdn/ecshop/cateapi/v1.5/store&amp;amp;id=DSAU&amp;amp;fields=Id,Name&lt;/code>&lt;/p>
&lt;h3 id="回傳資料-4">回傳資料&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-JSON" data-lang="JSON">&lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;Id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;DSAUF4&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;→10代Core i7八核&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;OriginId&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Sort&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">7&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is24h&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isVip&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isPick&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;isNC17&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Extra&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;Amount&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Fee&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;Intro&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;isNFC&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="範例程式-4">範例程式&lt;/h3>
&lt;p>&amp;quot;搜尋商品子分類名稱&amp;quot;部分範例程式如下，完整程式碼同樣在文章最後會附上。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_search_categories_name&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">categories_id&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;取得商品子分類的名稱(網頁左側)
&lt;/span>&lt;span class="s2">
&lt;/span>&lt;span class="s2"> :param categories_id: 分類 ID
&lt;/span>&lt;span class="s2"> :return data: 子分類名稱資料
&lt;/span>&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="nb">type&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">categories_id&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nb">list&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">categories_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;,&amp;#39;&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">categories_id&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://ecapi-pchome.cdn.hinet.net/cdn/ecshop/cateapi/v1.5/store&amp;amp;id={categories_id}&amp;amp;fields=Id,Name&amp;#39;&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">request_get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">data&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;!--adsense-->
&lt;h2 id="完整程式碼">完整程式碼&lt;/h2>
&lt;p>附上完整程式碼：&lt;a href="https://blog.jiatool.com/code/pchome_spider01.py" target="_blank" rel="noopener">
pchome_spider01.py
&lt;/a>&lt;br />
(對超連結右鍵 &amp;gt; 另存連結為)&lt;/p>
&lt;h2 id="延伸練習">延伸練習&lt;/h2>
&lt;ol>
&lt;li>在「&lt;a href="#%e6%90%9c%e5%b0%8b%e5%95%86%e5%93%81%e5%88%86%e9%a1%9e" target="_blank" rel="noopener">
搜尋頁面的商品分類
&lt;/a>」章節有介紹到商品所屬的分類，一般操作可以點擊分類來篩選商品，那在程式裡我們該如何送出指定分類的請求呢？&lt;br />
(小提示：注意觀察送出請求的路徑)&lt;/li>
&lt;/ol>
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>這篇文章主要是說明在&lt;a href="https://ecshweb.pchome.com.tw/search/v3.3/?q=%E6%BB%91%E9%BC%A0" target="_blank" rel="noopener">
搜尋頁面
&lt;/a>的請求，而之後會再寫一篇文章講解&lt;a href="https://24h.pchome.com.tw/prod/DCAN8J-A9008YONC" target="_blank" rel="noopener">
商品頁面
&lt;/a>，敬請其待。&lt;/p>
&lt;p>如果對文章有任何疑問或心得，歡迎在底下按讚、留言喔~😎&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;blockquote>
&lt;p>比別人多一點執著，你就會創造奇蹟。&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/pchome_spider01.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/pchome_spider01_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Python</category><category>PChome</category><category>網路爬蟲</category><category>Python網路爬蟲實例</category></item><item><title>[Python爬蟲實例] 教你輕鬆爬取"Yahoo奇摩知識+"的問題與解答</title><link>https://blog.jiatool.com/posts/yahoo_answers_spider/</link><pubDate>Sun, 21 Mar 2021 21:00:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sun, 21 Mar 2021 21:00:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/yahoo_answers_spider/</guid><description>前言 本次Python網路爬蟲實例 系列的「Yahoo奇摩知識+ 」，將帶領你來一步步爬取所有分類的問題與解答。 「Yahoo奇摩知識+」大約 10 年前</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>本次&lt;a href="https://blog.jiatool.com/series/Python%e7%b6%b2%e8%b7%af%e7%88%ac%e8%9f%b2%e5%af%a6%e4%be%8b/" target="_blank" rel="noopener">
Python網路爬蟲實例
&lt;/a>系列的「&lt;a href="https://tw.answers.yahoo.com/" target="_blank" rel="noopener">
Yahoo奇摩知識+
&lt;/a>」，將帶領你來一步步爬取所有分類的問題與解答。&lt;/p>
&lt;p>「Yahoo奇摩知識+」大約 10 年前左右在台灣還蠻多人用的，但現在會在Yahoo奇摩知識+上發問、回答的人已經少很多了。話說最近有人對Yahoo奇摩知識+有印象，會不會是從天氣之子呢(笑)，不過「Yahoo奇摩知識+」在日本是叫「Yahoo!知恵袋」哦~&lt;/p>
&lt;p>* 香港叫「Yahoo知識+」，但為什麼台灣的多出&amp;quot;奇摩&amp;quot;兩個字呢？較年輕的讀者可能不知道，「奇摩站」是以前台灣一家入口搜尋網站，但這又是另外一個故事了&amp;hellip;&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/yahoo_answers_spider/yahoo_answers.jpg" alt="Yahoo奇摩知識&amp;#43;" data-caption="Yahoo奇摩知識&amp;#43;" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
Yahoo奇摩知識&amp;#43;
&lt;/figcaption>
&lt;/figure>
&lt;p>備註：此文僅教育學習，切勿用作商業用途，個人實作皆屬個人行為，本作者不負任何法律責任&lt;/p>
&lt;h2 id="套件">套件&lt;/h2>
&lt;p>此次 Python 爬蟲主要使用到的套件：&lt;/p>
&lt;ul>
&lt;li>Requests [&lt;a href="https://requests.readthedocs.io/en/master/" target="_blank" rel="noopener">
Doc
&lt;/a>] [&lt;a href="https://github.com/psf/requests" target="_blank" rel="noopener">
GitHub
&lt;/a>]&lt;/li>
&lt;/ul>
&lt;p>安裝&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">pip install requests
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;!--adsense-->
&lt;h2 id="它資料是如何載入的呢">它資料是如何載入的呢？&lt;/h2>
&lt;p>進到&lt;a href="https://tw.answers.yahoo.com/" target="_blank" rel="noopener">
Yahoo奇摩知識+
&lt;/a>網站後，將網頁往下滾動，可以看到 Loading 的圖示，而且頁面也沒有跳轉，因此可以猜測它資料是透過 AJAX 的方式載入&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/yahoo_answers_spider/loading.jpg" alt="&amp;#34;問題資料&amp;#34;載入圖示" data-caption="&amp;#34;問題資料&amp;#34;載入圖示" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='400px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:400px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;問題資料&amp;#34;載入圖示
&lt;/figcaption>
&lt;/figure>
&lt;p>經過以前網路爬蟲實例的文章應該很熟悉了，打開瀏覽器的 &lt;strong>開發人員工具&lt;/strong> (F12 或 Ctrl + Shift + i)，切換到 &amp;quot;Network&amp;quot; &amp;gt; &amp;quot;XHR&amp;quot;，再將網頁往下滾動，讓我們抓到它送出的請求。點擊 &amp;quot;_reservice_/&amp;quot; 的請求後切換到 &amp;quot;Preview&amp;quot; 頁面，可以發現它返回的資料都在這裡。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/yahoo_answers_spider/network_xhr_preview.jpg" alt="&amp;#34;Network&amp;#34; &amp;gt; &amp;#34;XHR&amp;#34; &amp;gt; &amp;#34;_reservice_/&amp;#34; &amp;gt; &amp;#34;Preview&amp;#34;" data-caption="&amp;#34;Network&amp;#34; &amp;gt; &amp;#34;XHR&amp;#34; &amp;gt; &amp;#34;_reservice_/&amp;#34; &amp;gt; &amp;#34;Preview&amp;#34;" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;Network&amp;#34; &amp;gt; &amp;#34;XHR&amp;#34; &amp;gt; &amp;#34;_reservice_/&amp;#34; &amp;gt; &amp;#34;Preview&amp;#34;
&lt;/figcaption>
&lt;/figure>
&lt;p>開發人員工具切回到&amp;quot;Headers&amp;quot;頁面查看請求的網址與方法。&lt;br />
跟我們一般常用的 HTTP 請求方法(GET、POST)不同，在這裡它是使用 PUT 方法。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/yahoo_answers_spider/network_xhr_headers.png" alt="&amp;#34;Network&amp;#34; &amp;gt; &amp;#34;XHR&amp;#34; &amp;gt; &amp;#34;_reservice_/&amp;#34; &amp;gt; &amp;#34;Headers&amp;#34;" data-caption="&amp;#34;Network&amp;#34; &amp;gt; &amp;#34;XHR&amp;#34; &amp;gt; &amp;#34;_reservice_/&amp;#34; &amp;gt; &amp;#34;Headers&amp;#34;" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;Network&amp;#34; &amp;gt; &amp;#34;XHR&amp;#34; &amp;gt; &amp;#34;_reservice_/&amp;#34; &amp;gt; &amp;#34;Headers&amp;#34;
&lt;/figcaption>
&lt;/figure>
&lt;p>往下還有請求夾帶的參數 Request Payload，可以點擊 view source 方便我們複製參數。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/yahoo_answers_spider/request_payload.png" alt="Request Payload" data-caption="Request Payload" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
Request Payload
&lt;/figcaption>
&lt;/figure>
&lt;p>請求網址：&lt;code>https://tw.answers.yahoo.com/_reservice_/&lt;/code>&lt;br />
請求方法：&lt;code>PUT&lt;/code>&lt;br />
Request Payload：&lt;br />
&lt;code>{&amp;quot;type&amp;quot;:&amp;quot;CALL_RESERVICE&amp;quot;,&amp;quot;payload&amp;quot;:{&amp;quot;categoryId&amp;quot;:&amp;quot;0&amp;quot;,&amp;quot;lang&amp;quot;:&amp;quot;zh-Hant-TW&amp;quot;,&amp;quot;count&amp;quot;:20,&amp;quot;offset&amp;quot;:&amp;quot;pv61~p:0&amp;quot;},&amp;quot;reservice&amp;quot;:{&amp;quot;name&amp;quot;:&amp;quot;FETCH_DISCOVER_STREAMS_END&amp;quot;,&amp;quot;start&amp;quot;:&amp;quot;FETCH_DISCOVER_STREAMS_START&amp;quot;,&amp;quot;state&amp;quot;:&amp;quot;CREATED&amp;quot;}}&lt;/code>&lt;/p>
&lt;br/>
&lt;p>這邊有個之前文章沒遇過的地方，以前請求夾帶的參數常遇到的是 key-value (鍵值對)的形式，但這邊是採用 JSON 格式，因此 Headers 內要加入 &lt;code>content-type(HTTP 內容類型)&lt;/code> 來表明用 JSON 格式來傳遞參數資料。&lt;br />
&lt;code>'content-type': 'application/json'&lt;/code>&lt;/p>
&lt;p>同時要注意請求的 data 中資料是 JSON 格式的字串，在 Python 程式裡記得要使用 &lt;code>json.dumps()&lt;/code> 將其轉換為字串，大致如下程式碼所示。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">json&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://tw.answers.yahoo.com/_reservice_/&amp;#39;&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;user-agent&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;content-type&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;application/json&amp;#39;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">payload&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;CALL_RESERVICE&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;payload&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;categoryId&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;0&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;lang&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;zh-Hant-TW&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;count&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">20&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;offset&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="s2">&amp;#34;reservice&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;FETCH_DISCOVER_STREAMS_END&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;start&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;FETCH_DISCOVER_STREAMS_START&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;state&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;CREATED&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">put&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dumps&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">payload&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;p>好！！那這樣都知道&amp;quot;Yahoo奇摩知識+&amp;quot;資料的請求方法了，我們來看看其參數有哪些值~&lt;/p>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="問題列表">問題列表&lt;/h2>
&lt;p>首先從網站一進入就會看到的問題列表(文章列表)說起，左方有各式各樣的分類，中間的問題列表還有分為&amp;quot;探索&amp;quot;與&amp;quot;解答&amp;quot;，綠色方框即是我們想要獲取的部分。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/yahoo_answers_spider/question_list.jpg" alt="問題列表(文章列表) 頁面" data-caption="問題列表(文章列表) 頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
問題列表(文章列表) 頁面
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="請求方法">請求方法&lt;/h3>
&lt;p>先從&amp;quot;探索&amp;quot;開始找起，同上章節步驟，從&lt;strong>開發人員工具&lt;/strong>知道請求的路徑、參數如下：&lt;/p>
&lt;p>請求網址：&lt;code>https://tw.answers.yahoo.com/_reservice_/&lt;/code>&lt;br />
請求方法：&lt;code>PUT&lt;/code>&lt;br />
Request Payload：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-JSON" data-lang="JSON">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;CALL_RESERVICE&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;payload&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;categoryId&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;0&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;lang&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;zh-Hant-TW&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;count&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">20&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;offset&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;pv61~p:0&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;reservice&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;FETCH_DISCOVER_STREAMS_END&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;start&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;FETCH_DISCOVER_STREAMS_START&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;state&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;CREATED&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>其中幾個參數代表意思：&lt;/p>
&lt;ul>
&lt;li>&lt;code>categoryId&lt;/code>：分類 ID。分類 ID 在各分類網頁的網址後方可找到，目前共有 24 個大分類，子分類也是採用同樣的方式。&lt;/li>
&lt;/ul>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/yahoo_answers_spider/category_url.jpg" alt="分類 ID 在網址後方可以取得" data-caption="分類 ID 在網址後方可以取得" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
分類 ID 在網址後方可以取得
&lt;/figcaption>
&lt;/figure>
&lt;p>而如果給 0，則代表&amp;quot;所有分類&amp;quot;，以下是各大分類所對應的 &lt;code>categoryId&lt;/code>：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>分類名稱&lt;/th>
&lt;th>分類 ID&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>所有分類&lt;/td>
&lt;td>0&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>健康&lt;/td>
&lt;td>396545018&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>商業與財經&lt;/td>
&lt;td>396545013&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>娛樂與音樂&lt;/td>
&lt;td>396545016&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>家居與園藝&lt;/td>
&lt;td>396545394&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>家庭與人際關係&lt;/td>
&lt;td>396545433&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>寵物&lt;/td>
&lt;td>396545443&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>懷孕與育兒&lt;/td>
&lt;td>396546046&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>政治與政府&lt;/td>
&lt;td>396545444&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>教育與參考&lt;/td>
&lt;td>396545015&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>新聞與活動&lt;/td>
&lt;td>396545439&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>旅遊&lt;/td>
&lt;td>396545469&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>汽車與交通&lt;/td>
&lt;td>396545311&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>消費電子產品&lt;/td>
&lt;td>396545014&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>環境&lt;/td>
&lt;td>396545451&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>社會科學&lt;/td>
&lt;td>396545301&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>社會與文化&lt;/td>
&lt;td>396545454&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>科學&lt;/td>
&lt;td>396545122&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>美容與造型&lt;/td>
&lt;td>396545144&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>藝術與人文&lt;/td>
&lt;td>396545012&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>遊戲與休閒活動&lt;/td>
&lt;td>396545019&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>運動&lt;/td>
&lt;td>396545213&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>電腦與網際網路&lt;/td>
&lt;td>396545660&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>食品與飲料&lt;/td>
&lt;td>396545367&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>餐廳與小吃&lt;/td>
&lt;td>396545327&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;ul>
&lt;li>
&lt;p>&lt;code>count&lt;/code>：一次回傳&amp;quot;問題(文章)&amp;quot;數量。但實測發現有時得到的數量會較少。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>offset&lt;/code>：偏移值。帶入前一頁回傳資料中 &lt;code>offset&lt;/code> 的值。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;br/>
&lt;p>而 &amp;quot;解答&amp;quot; 部分的問題列表(文章列表)其參數幾乎一樣，只要把 &lt;code>FETCH_DISCOVER_STREAMS_END&lt;/code> 改成 &lt;code>FETCH_ANSWER_STREAMS_END&lt;/code>、&lt;code>FETCH_DISCOVER_STREAMS_START&lt;/code> 改成 &lt;code>FETCH_ANSWER_STREAMS_START&lt;/code> 即可。&lt;/p>
&lt;p>請求網址：&lt;code>https://tw.answers.yahoo.com/_reservice_/&lt;/code>&lt;br />
請求方法：&lt;code>PUT&lt;/code>&lt;br />
Request Payload：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-JSON" data-lang="JSON">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;CALL_RESERVICE&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;payload&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;categoryId&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;0&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;lang&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;zh-Hant-TW&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;count&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">20&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;offset&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;pv61~p:0&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;reservice&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;FETCH_ANSWER_STREAMS_END&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;start&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;FETCH_ANSWER_STREAMS_START&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;state&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;CREATED&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="回傳資料">回傳資料&lt;/h3>
&lt;p>它以 JSON 格式回傳，&lt;code>error&lt;/code> 會顯示此次請求是否發生錯誤，主要的資料都在 &lt;code>payload&lt;/code> 裏頭。&lt;/p>
&lt;ul>
&lt;li>&lt;code>canLoadMore&lt;/code>：是否還有下一頁。&lt;/li>
&lt;li>&lt;code>offset&lt;/code>：請求下一頁的偏移值。&lt;/li>
&lt;li>&lt;code>questions&lt;/code>：問題列表(文章列表)。&lt;/li>
&lt;/ul>
&lt;p>而每一則問題又有幾個數值：&lt;/p>
&lt;ul>
&lt;li>&lt;code>qid&lt;/code>：問題 ID。也代表問題網址後方帶的參數，例如 &lt;code>https://tw.answers.yahoo.com/question/index?qid=20210318093121AAnaQXT&lt;/code>。&lt;/li>
&lt;li>&lt;code>title&lt;/code>：問題標題。&lt;/li>
&lt;li>&lt;code>detail&lt;/code>：問題內容。&lt;/li>
&lt;li>&lt;code>category&lt;/code>：問題分類。&lt;/li>
&lt;li>&lt;code>createdTime&lt;/code>：創建日期時間。&lt;/li>
&lt;li>&lt;code>answersCount&lt;/code>：解答總數。&lt;/li>
&lt;li>&lt;code>thumbUpsCount&lt;/code>：按讚總數。&lt;/li>
&lt;li>&lt;code>bestAnswerDetail&lt;/code>：最佳解答內容。&lt;/li>
&lt;/ul>
&lt;br/>
&lt;p>範例：問題列表 JSON 資料 &lt;a href="https://blog.jiatool.com/code/question_list_data.json" target="_blank" rel="noopener">
question_list_data.json
&lt;/a>&lt;/p>
&lt;h2 id="問題詳細資料">問題詳細資料&lt;/h2>
&lt;p>在問題列表(文章列表)點擊問題後會跳轉到問題詳細頁面，有完整的問題資訊與網友的解答。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/yahoo_answers_spider/question.jpg" alt="問題詳細資料 頁面" data-caption="問題詳細資料 頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
問題詳細資料 頁面
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="請求方法-1">請求方法&lt;/h3>
&lt;p>可以發現請求路徑和方法都是一樣的，它是透過 Request Payload 來判斷需要哪些資料(條件)。&lt;/p>
&lt;p>請求網址：&lt;code>https://tw.answers.yahoo.com/_reservice_/&lt;/code>&lt;br />
請求方法：&lt;code>PUT&lt;/code>&lt;br />
Request Payload：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-JSON" data-lang="JSON">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;CALL_RESERVICE&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;payload&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;qid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;20210310121058AAxKYlh&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;reservice&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;FETCH_QUESTION_END&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;start&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;FETCH_QUESTION_START&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;state&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;CREATED&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;kvPayload&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;key&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;20210310121058AAxKYlh&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;kvActionPrefix&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;KV/question/&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>其中 &lt;code>payload&lt;/code> &amp;gt; &lt;code>qid&lt;/code> 與 &lt;code>kvPayload&lt;/code> &amp;gt; &lt;code>key&lt;/code> 參數帶上問題 ID。&lt;/p>
&lt;h3 id="回傳資料-1">回傳資料&lt;/h3>
&lt;p>它以 JSON 格式回傳，&lt;code>error&lt;/code> 會顯示此次請求是否發生錯誤，主要的資料都在 &lt;code>payload&lt;/code> 裏頭，幾個比較重要的參數：&lt;/p>
&lt;ul>
&lt;li>&lt;code>qid&lt;/code>：問題 ID。也代表問題網址後方帶的參數，例如 &lt;code>https://tw.answers.yahoo.com/question/index?qid=20210318093121AAnaQXT&lt;/code>。&lt;/li>
&lt;li>&lt;code>lang&lt;/code>：語言。&lt;/li>
&lt;li>&lt;code>category&lt;/code>：問題分類。&lt;/li>
&lt;li>&lt;code>createdTime&lt;/code>：創建日期時間。&lt;/li>
&lt;li>&lt;code>title&lt;/code>：問題標題。&lt;/li>
&lt;li>&lt;code>content&lt;/code>：問題內容。&lt;/li>
&lt;li>&lt;code>updatedDetails&lt;/code>：問題更新詳情。&lt;/li>
&lt;li>&lt;code>attachedImageUrl&lt;/code>：附加圖片網址。&lt;/li>
&lt;li>&lt;code>bestAnswer&lt;/code>：最佳解答。&lt;/li>
&lt;li>&lt;code>answerCount&lt;/code>：解答總數。&lt;/li>
&lt;li>&lt;code>saveCount&lt;/code>：被收藏總數。&lt;/li>
&lt;li>&lt;code>isAnonymous&lt;/code>：是否匿名。&lt;/li>
&lt;/ul>
&lt;br/>
&lt;p>範例：問題 JSON 資料 &lt;a href="https://blog.jiatool.com/code/question_data.json" target="_blank" rel="noopener">
question_data.json
&lt;/a>&lt;/p>
&lt;h2 id="解答列表">解答列表&lt;/h2>
&lt;p>位於每篇問題(文章)底下會有各網友回覆的解答(留言)。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/yahoo_answers_spider/answer_list.jpg" alt="解答列表 頁面" data-caption="解答列表 頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
解答列表 頁面
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="請求方法-2">請求方法&lt;/h3>
&lt;p>一樣只有 Request Payload 有差異，&lt;/p>
&lt;p>請求網址：&lt;code>https://tw.answers.yahoo.com/_reservice_/&lt;/code>&lt;br />
請求方法：&lt;code>PUT&lt;/code>&lt;br />
Request Payload：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-JSON" data-lang="JSON">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;CALL_RESERVICE&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;payload&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;qid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;20210310121058AAxKYlh&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;count&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;start&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;lang&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;zh-Hant-TW&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;sortType&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;NEWEST&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;reservice&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;FETCH_QUESTION_ANSWERS_END&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;start&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;FETCH_QUESTION_ANSWERS_START&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;state&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;CREATED&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;kvPayload&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;key&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;20210310121058AAxKYlh&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;kvActionPrefix&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;KV/questionAnswers/&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>其中 &lt;code>payload&lt;/code> &amp;gt; &lt;code>qid&lt;/code> 與 &lt;code>kvPayload&lt;/code> &amp;gt; &lt;code>key&lt;/code> 參數帶上問題 ID。&lt;br />
&lt;code>count&lt;/code> 代表一次回傳&amp;quot;解答(留言)&amp;quot;數量，&lt;code>start&lt;/code> 代表起始值，例如這次解答取到 10 則，下一次要從第 11 則開始抓，那 &lt;code>start&lt;/code> 就要帶 11。&lt;br />
&lt;code>sortType&lt;/code> 代表解答排序依據(RATING:評分、NEWEST:最新、OLDEST:最舊)。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/yahoo_answers_spider/sort_type.jpg" alt="解答排序依據" data-caption="解答排序依據" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
解答排序依據
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="回傳資料-2">回傳資料&lt;/h3>
&lt;p>它以 JSON 格式回傳，&lt;code>error&lt;/code> 會顯示此次請求是否發生錯誤，主要的資料都在 &lt;code>payload&lt;/code> 裏頭，幾個比較重要的參數：&lt;/p>
&lt;ul>
&lt;li>&lt;code>qid&lt;/code>：問題 ID。&lt;/li>
&lt;li>&lt;code>lang&lt;/code>：語言。&lt;/li>
&lt;li>&lt;code>answerCount&lt;/code>：解答總數。&lt;/li>
&lt;li>&lt;code>start&lt;/code>：本次解答起始值。&lt;/li>
&lt;li>&lt;code>count&lt;/code>：本次解答數量。&lt;/li>
&lt;li>&lt;code>sortType&lt;/code>：解答排序依據(RATING:評分、NEWEST:最新、OLDEST:最舊)。&lt;/li>
&lt;li>&lt;code>answers&lt;/code>：解答列表(留言列表)。&lt;/li>
&lt;/ul>
&lt;p>而每一則解答又有幾個數值：&lt;/p>
&lt;ul>
&lt;li>&lt;code>qid&lt;/code>：問題 ID。&lt;/li>
&lt;li>&lt;code>id&lt;/code>：解答 ID。&lt;/li>
&lt;li>&lt;code>text&lt;/code>：解答內容。&lt;/li>
&lt;li>&lt;code>attachedImageUrl&lt;/code>：附加圖片網址。&lt;/li>
&lt;li>&lt;code>reference&lt;/code>：解答參考來源。&lt;/li>
&lt;li>&lt;code>answerer&lt;/code>：解答網友。&lt;/li>
&lt;li>&lt;code>answerer&lt;/code> &amp;gt; &lt;code>kid&lt;/code>：網友 ID。&lt;/li>
&lt;li>&lt;code>answerer&lt;/code> &amp;gt; &lt;code>nickname&lt;/code>：網友暱稱。&lt;/li>
&lt;li>&lt;code>answerer&lt;/code> &amp;gt; &lt;code>imageUrl&lt;/code>：網友圖片網址。&lt;/li>
&lt;li>&lt;code>answerer&lt;/code> &amp;gt; &lt;code>level&lt;/code>：網友等級。&lt;/li>
&lt;li>&lt;code>isBestAnswer&lt;/code>：是否為最佳解答。&lt;/li>
&lt;li>&lt;code>thumbsDown&lt;/code>：倒讚數。&lt;/li>
&lt;li>&lt;code>thumbsUp&lt;/code>：按讚數。&lt;/li>
&lt;li>&lt;code>isAnonymous&lt;/code>：是否匿名。&lt;/li>
&lt;li>&lt;code>commentCount&lt;/code>：此解答底下回覆數量(目前此功能好像被移除了)。&lt;/li>
&lt;li>&lt;code>createdTime&lt;/code>：創建日期時間。&lt;/li>
&lt;/ul>
&lt;br/>
&lt;p>* 抓取解答(留言)時要注意，如果此問題有&amp;quot;最佳解答&amp;quot;，則此解答並不會出現在&amp;quot;解答列表&amp;quot;的回應裡，而是會在&amp;quot;問題詳細資料&amp;quot;回應資料裡的 &lt;code>bestAnswer&lt;/code> 參數中，因此要注意不要遺漏掉了。&lt;/p>
&lt;br/>
&lt;p>範例：解答列表 JSON 資料 &lt;a href="https://blog.jiatool.com/code/answer_list_data.json" target="_blank" rel="noopener">
answer_list_data.json
&lt;/a>&lt;/p>
&lt;h2 id="範例程式碼">範例程式碼&lt;/h2>
&lt;p>附上範例程式碼：&lt;a href="https://blog.jiatool.com/code/yahoo_answers_spider.py" target="_blank" rel="noopener">
yahoo_answers_spider.py
&lt;/a>&lt;br />
(對超連結右鍵 &amp;gt; 另存連結為&amp;hellip;)&lt;/p>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="延伸練習">延伸練習&lt;/h2>
&lt;ol>
&lt;li>試著爬取一篇問題，並將問題以及各解答挑出想要的幾個欄位，並儲存成適合的檔案(TXT文字檔、JSON)。&lt;/li>
&lt;/ol>
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>一開始我在測試抓取&amp;quot;Yahoo奇摩知識+&amp;quot;時，不知道為何 Header 都給一樣了，還是一直無法成功請求到資料。後來改使用 Postman 這項工具測試，才發覺 &lt;code>content-type&lt;/code> 要帶 &lt;code>'application/json'&lt;/code>，也學到了一個😙。&lt;/p>
&lt;br/>
&lt;p>如果你對於 Python、爬蟲、網頁感興趣的話，我後續還會繼續寫相關的文章，歡迎來追蹤 FB 粉專『&lt;a href="https://www.facebook.com/jiatool" target="_blank" rel="noopener">
IT空間
&lt;/a>』~&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;blockquote>
&lt;p>人生就像天空一樣，有季節更迭，時刻在變；&lt;br />
它雖然不會一直晴空萬里，但也不會總是大雪紛飛。&lt;/p>
&lt;p align="right">—— 《鬼滅之刃》&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/yahoo_answers_spider.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/yahoo_answers_spider_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Python</category><category>網路爬蟲</category><category>Python網路爬蟲實例</category></item><item><title>[Python爬蟲實例] 如何爬取"蝦皮購物"的商品、評價資料？</title><link>https://blog.jiatool.com/posts/shopee_spider/</link><pubDate>Sun, 28 Feb 2021 21:00:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sun, 17 Sep 2023 21:55:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/shopee_spider/</guid><description>前言 蝦皮購物網頁後來有加入更多反爬蟲機制，以下文章說明的內容已過時，可以當作參考資料來學習。 大家都喜歡買東西，而現代人購物很大一部份會從線上</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;div class="notices warning" data-title="以下作法已過時">
蝦皮購物網頁後來有加入更多反爬蟲機制，以下文章說明的內容已過時，可以當作參考資料來學習。
&lt;/div>
&lt;br/>
&lt;p>大家都喜歡買東西，而現代人購物很大一部份會從線上的購物平台來尋找，像是台灣前幾大的 PChome24h購物、momo購物網、蝦皮購物、露天拍賣等等。&lt;/p>
&lt;p>這次的&lt;a href="https://blog.jiatool.com/series/Python%e7%b6%b2%e8%b7%af%e7%88%ac%e8%9f%b2%e5%af%a6%e4%be%8b/" target="_blank" rel="noopener">
Python網路爬蟲實例
&lt;/a>系列要來挖掘&lt;a href="https://shopee.tw/" target="_blank" rel="noopener">
&amp;quot;蝦皮購物&amp;quot;
&lt;/a>，試著說明如何抓取各項商品資訊、評價資料，跟著文章體驗爬蟲的樂趣吧~&lt;/p>
&lt;p>備註：此文僅教育學習，切勿用作商業用途，個人實作皆屬個人行為，本作者不負任何法律責任&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/shopee_spider/online_shopping.jpg" alt="線上購物 (來源：Unsplash)" data-caption="線上購物 (來源：Unsplash)" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
線上購物 (來源：Unsplash)
&lt;/figcaption>
&lt;/figure>
&lt;h2 id="套件">套件&lt;/h2>
&lt;p>此次 Python 爬蟲主要使用到的套件：&lt;/p>
&lt;ul>
&lt;li>Requests [&lt;a href="https://requests.readthedocs.io/en/master/" target="_blank" rel="noopener">
Doc
&lt;/a>] [&lt;a href="https://github.com/psf/requests" target="_blank" rel="noopener">
GitHub
&lt;/a>]&lt;/li>
&lt;/ul>
&lt;p>安裝&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">pip install requests
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;!--adsense-->
&lt;h2 id="尋找抓取資料的方法">尋找抓取資料的方法&lt;/h2>
&lt;p>我們想要爬取&amp;quot;搜尋商品結果&amp;quot;頁面的商品資訊，以下以搜尋&lt;a href="https://shopee.tw/search?keyword=%E6%89%8B%E6%A9%9F%E4%BF%9D%E8%AD%B7%E6%AE%BC" target="_blank" rel="noopener">
&amp;quot;手機保護殼&amp;quot;
&lt;/a>來示範。&lt;/p>
&lt;p>前往蝦皮購物網站，一開始當然是打開我們熟悉的 &lt;strong>開發人員工具&lt;/strong> (F12 或 Ctrl + Shift + i)，切換到&amp;quot;Network&amp;quot; &amp;gt; &amp;quot;XHR&amp;quot;，並在網頁上方搜尋欄打入關鍵字、點擊搜尋。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/shopee_spider/search1.jpg" alt="搜尋商品結果" data-caption="搜尋商品結果" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
搜尋商品結果
&lt;/figcaption>
&lt;/figure>
&lt;p>接著在開發人員工具頁面中，它會記錄著每個請求，從中尋找蝦皮購物是否採用動態載入的方式載入資料，可以一個一個查看，或使用搜尋(Ctrl+f)來找商品名稱。&lt;/p>
&lt;p>在其中一條 &lt;code>?by=relevancy&amp;amp;keyword=...&lt;/code> 開頭的請求中發現了搜尋結果商品資訊。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/shopee_spider/network_xhr.png" alt="&amp;#34;Network&amp;#34; &amp;gt; &amp;#34;XHR&amp;#34; 動態載入" data-caption="&amp;#34;Network&amp;#34; &amp;gt; &amp;#34;XHR&amp;#34; 動態載入" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;Network&amp;#34; &amp;gt; &amp;#34;XHR&amp;#34; 動態載入
&lt;/figcaption>
&lt;/figure>
&lt;p>開發人員工具切換到&amp;quot;Headers&amp;quot;頁面查看請求的網址與方法。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/shopee_spider/headers.png" alt="&amp;#34;Headers&amp;#34;頁面" data-caption="&amp;#34;Headers&amp;#34;頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;Headers&amp;#34;頁面
&lt;/figcaption>
&lt;/figure>
&lt;p>請求網址：&lt;code>https://shopee.tw/api/v2/search_items/?by=relevancy&amp;amp;keyword=手機保護殼&amp;amp;limit=50&amp;amp;newest=0&amp;amp;order=desc&amp;amp;page_type=search&amp;amp;version=2&lt;/code>&lt;br />
請求方法：&lt;code>GET&lt;/code>&lt;/p>
&lt;br/>
&lt;p>但如果你直接拿此網址去用 Python &lt;code>requests.get(url)&lt;/code>，會發現回傳資料會不完整、裡面的多項數據也是錯誤的，只在 Headers 加上 &lt;code>user-agent&lt;/code> 顯然是不夠的。&lt;br />
經過我的測試，將 &lt;code>referer&lt;/code> 加入 Headers 後資料就完整了。&lt;br />
(放到 &lt;code>referer&lt;/code> 前記得要將 url 編碼才不會噴錯)&lt;/p>
&lt;p>但又遇到一個問題，仔細看會發現，怎麼取得的資料和網頁上看到的順序不一樣？！&lt;br />
首先猜測 Headers 是否還缺少哪個參數導致，經過多次嘗試後，發覺是 x-api-source 與 cookie。&lt;/p>
&lt;p>x-api-source 帶入 &lt;code>pc&lt;/code> 即可，很簡單。&lt;br />
但 cookie 則需要當中的 SPC_SI 值，這個值該從何而來。&lt;/p>
&lt;p>我將 SPC_SI 的值貼到搜尋(Ctrl+f)，來找找這個值是從哪邊來的。&lt;br />
發現其中一個是在請求 &lt;code>https://shopee.tw/api/v4/search/product_labels&lt;/code> 後，返回的結果 set-cookie 中有設定 SPC_SI。&lt;/p>
&lt;p>因此這部分我就先嘗試使用 requests 的 Session，他會把每次請求都算在同一個 session 裡，像是 cookie 之類的都會保持，這樣我就不用還要將 cookie 讀出來，下一次請求再設定了。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">urllib&lt;/span>
&lt;span class="n">keyword&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;手機保護殼&amp;#39;&lt;/span>
&lt;span class="n">headers&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;user-agent&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.68&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;x-api-source&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;pc&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;referer&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://shopee.tw/search?keyword={urllib.parse.quote(keyword)}&amp;#39;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">s&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Session&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://shopee.tw/api/v4/search/product_labels&amp;#39;&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">s&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">base_url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://shopee.tw/api/v2/search_items/&amp;#39;&lt;/span>
&lt;span class="n">query&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;by=relevancy&amp;amp;keyword={keyword}&amp;amp;limit=50&amp;amp;newest=0&amp;amp;order=desc&amp;amp;page_type=search&amp;amp;version=2&amp;#34;&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">base_url&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="s1">&amp;#39;?&amp;#39;&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">query&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">s&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">headers&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="c1"># with open(&amp;#39;shopee.json&amp;#39;, &amp;#39;w&amp;#39;, encoding=&amp;#39;utf-8&amp;#39;) as f:&lt;/span>
&lt;span class="c1"># f.write(r.text)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>回傳資料是 JSON 格式，可以使用 requests 提供的 &lt;code>r.json()&lt;/code> 轉換。&lt;/p>
&lt;br/>
&lt;p>其他兩個&amp;quot;商品資訊&amp;quot;與&amp;quot;評價資訊&amp;quot;都是採用同樣的方法來尋找請求網址，這邊就不再重複說明。&lt;/p>
&lt;p>下面我將&amp;quot;搜尋商品&amp;quot;、&amp;quot;商品資訊&amp;quot;、&amp;quot;評分資訊&amp;quot;所找出來的請求路徑、參數內容及回傳資料整理出來說明。&lt;/p>
&lt;h2 id="搜尋商品">搜尋商品&lt;/h2>
&lt;p>搜尋商品的頁面大致上能分為三個部分，藍色方框為商品結果、綠色方框為篩選功能(雖然應該算排序)、紫色方框為條件篩選。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/shopee_spider/search2.jpg" alt="搜尋商品結果 板塊" data-caption="搜尋商品結果 板塊" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
搜尋商品結果 板塊
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="請求路徑">請求路徑&lt;/h3>
&lt;p>GET &lt;code>https://shopee.tw/api/v2/search_items/?by=relevancy&amp;amp;keyword={關鍵字}&amp;amp;limit=50&amp;amp;newest=0&amp;amp;order=desc&amp;amp;page_type=search&amp;amp;version=2&lt;/code>&lt;/p>
&lt;p>範例：&lt;code>https://shopee.tw/api/v2/search_items/?by=relevancy&amp;amp;keyword=手機保護殼&amp;amp;limit=50&amp;amp;newest=0&amp;amp;order=desc&amp;amp;page_type=search&amp;amp;version=2&lt;/code>&lt;/p>
&lt;p>&lt;code>referer&lt;/code>：&lt;code>https://shopee.tw/search?keyword={關鍵字}&lt;/code>&lt;br />
(也就是搜尋頁面網址，記得將 url 編碼)&lt;/p>
&lt;h3 id="請求參數">請求參數&lt;/h3>
&lt;p>來看一下請求網址帶的參數有哪些：&lt;/p>
&lt;ul>
&lt;li>&lt;code>by&lt;/code> 和 &lt;code>order&lt;/code> 排序用，也就是網頁上面這欄(雖然它這邊是寫篩選，但其功能是排序)：&lt;/li>
&lt;/ul>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/shopee_spider/sort.jpg" alt="排序用欄位" data-caption="排序用欄位" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
排序用欄位
&lt;/figcaption>
&lt;/figure>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>篩選&lt;/th>
&lt;th>by&lt;/th>
&lt;th>order&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>綜合排名&lt;/td>
&lt;td>relevancy&lt;/td>
&lt;td>desc&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>最新&lt;/td>
&lt;td>ctime&lt;/td>
&lt;td>desc&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>熱銷&lt;/td>
&lt;td>sales&lt;/td>
&lt;td>desc&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>價格(高到低)&lt;/td>
&lt;td>price&lt;/td>
&lt;td>desc&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>價格(低到高)&lt;/td>
&lt;td>price&lt;/td>
&lt;td>asc&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;ul>
&lt;li>
&lt;p>&lt;code>keyword&lt;/code>：很明顯就是想要搜尋的關鍵字。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>limit&lt;/code>：一次請求最大回傳的結果數量，預設20個、最多100個，但如果給超過100個，會回傳10個。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>newest&lt;/code>：偏移量的概念，如果limit設50、newest設100，就如同取得第三頁(第101~150個)。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>page_type&lt;/code>：設定search代表我們使用搜尋。還有像是shop，則用在查看某一賣場內商品。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;code>version&lt;/code>：可能是指 API 的版本。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>條件篩選&lt;br />
在網頁左邊的位置，有許多類別可以選擇，底下會一一介紹，至於參數的值，某些數量較多就不全部列出了(像是&amp;quot;用送方式&amp;quot;、&amp;quot;分類&amp;quot;、&amp;quot;品牌&amp;quot;)。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/shopee_spider/condition_screening.jpg" alt="條件篩選" data-caption="條件篩選" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='750px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:750px;height:;"/>
&lt;figcaption style="text-align: center;">
條件篩選
&lt;/figcaption>
&lt;/figure>
&lt;p>如果有使用&amp;quot;條件篩選&amp;quot;，請求會再多加上 skip_autocorrect=1 (跳過自動修正)，這個參數不確定會產生怎樣的影響。&lt;/p>
&lt;p>某些參數可以給多個值，其中就使用&lt;code>,&lt;/code>隔開，例如運送方式要&amp;quot;全家、7-11&amp;quot;，參數就設定為&lt;code>shippings=1,2&lt;/code>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>條件&lt;/th>
&lt;th>參數&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>運送方式&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>全家&lt;/td>
&lt;td>shippings=1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>7-11&lt;/td>
&lt;td>shippings=2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>賣家宅配&lt;/td>
&lt;td>shippings=8&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>出貨地點&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>台灣&lt;/td>
&lt;td>locations=-1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>海外&lt;/td>
&lt;td>locations=-2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>分類&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ASUS保護殼&lt;/td>
&lt;td>categoryids=7964&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>卡通殼&lt;/td>
&lt;td>categoryids=17360&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>品牌&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>NOKIA&lt;/td>
&lt;td>brandids=137374&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ASUS&lt;/td>
&lt;td>brandids=4747&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>價格&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>最小 100 元&lt;/td>
&lt;td>price_min=100&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>最大 500 元&lt;/td>
&lt;td>price_max=500&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>評價&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>5星&lt;/td>
&lt;td>rating_filter=5&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>4星或以上&lt;/td>
&lt;td>rating_filter=4&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>賣場類型&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>蝦皮商城&lt;/td>
&lt;td>official_mall=1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>蝦皮優選&lt;/td>
&lt;td>shopee_verified=1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>商品保存狀況&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>新商品&lt;/td>
&lt;td>conditions=new&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>二手商品&lt;/td>
&lt;td>conditions=used&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>付款方式&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>信用卡&lt;/td>
&lt;td>pay_credit_card=1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>服務與促銷&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>目前有折扣&lt;/td>
&lt;td>with_discount=true&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>運費補助&lt;/td>
&lt;td>shipping_fee_included=true&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>商城最低價&lt;/td>
&lt;td>filter_lowest_price_guarantee=1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>多件優惠&lt;/td>
&lt;td>wholesale=1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>影音介紹&lt;/td>
&lt;td>filter_video=1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>快速出貨&lt;/td>
&lt;td>label_ids=1000028&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>蝦幣回饋&lt;/td>
&lt;td>label_ids=1000040&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>* &amp;quot;商品保存狀況&amp;quot;裡如果你兩個都勾，會等於兩個都不勾。&lt;/p>
&lt;p>* 舉例來說：&lt;br />
我查詢&amp;quot;手機保護殼&amp;quot;，並以&amp;quot;最熱銷&amp;quot;排序，&lt;br />
條件篩選有&amp;quot;運送方式 7-11&amp;quot;、&amp;quot;價格最高 600 元&amp;quot;、&amp;quot;評價四星或以上&amp;quot;、&amp;quot;新商品&amp;quot;，&lt;br />
一次最多 100 筆商品&lt;br />
&lt;code>https://shopee.tw/api/v2/search_items/?by=sales&amp;amp;conditions=new&amp;amp;keyword=手機保護殼&amp;amp;limit=100&amp;amp;newest=0&amp;amp;order=desc&amp;amp;page_type=search&amp;amp;price_max=600&amp;amp;rating_filter=4&amp;amp;shippings=2&amp;amp;skip_autocorrect=1&amp;amp;version=2&lt;/code>&lt;/p>
&lt;h3 id="回傳資料">回傳資料&lt;/h3>
&lt;p>它以 JSON 格式回傳，商品會在 items 欄位內，每一個商品有許多欄位，這邊挑幾個來說明。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>欄位&lt;/th>
&lt;th>代表意思&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>itemid&lt;/td>
&lt;td>商品ID&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>shopid&lt;/td>
&lt;td>賣場ID&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>name&lt;/td>
&lt;td>商品名稱&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>brand&lt;/td>
&lt;td>品牌&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>shop_location&lt;/td>
&lt;td>賣場位置(出貨地)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ctime&lt;/td>
&lt;td>上架時間(時間戳)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>can_use_wholesale&lt;/td>
&lt;td>是否有多件優惠&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>show_free_shipping&lt;/td>
&lt;td>是否顯示免運&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>shopee_verified&lt;/td>
&lt;td>是否為蝦皮優選&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>show_shopee_verified_label&lt;/td>
&lt;td>是否顯示蝦皮優選標籤&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>is_official_shop&lt;/td>
&lt;td>是否為官方商店&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>show_official_shop_label&lt;/td>
&lt;td>是否顯示官方商店標籤&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>show_official_shop_label_in_title&lt;/td>
&lt;td>是否在標題中顯示官方商店標籤&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>is_adult&lt;/td>
&lt;td>是否為成人商品&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>historical_sold&lt;/td>
&lt;td>已售出數量&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>stock&lt;/td>
&lt;td>庫存&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>liked_count&lt;/td>
&lt;td>喜歡數&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>view_count&lt;/td>
&lt;td>瀏覽數&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>currency&lt;/td>
&lt;td>貨幣&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>has_lowest_price_guarantee&lt;/td>
&lt;td>最低價格保證&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>discount&lt;/td>
&lt;td>折扣&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>price&lt;/td>
&lt;td>價格(要再除100000)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>price_before_discount&lt;/td>
&lt;td>折扣前價格&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>price_min&lt;/td>
&lt;td>價格範圍(最低)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>price_max&lt;/td>
&lt;td>價格範圍(最高)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>price_min_before_discount&lt;/td>
&lt;td>折扣前價格範圍(最低)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>price_max_before_discount&lt;/td>
&lt;td>折扣前價格範圍(最高)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>cmt_count&lt;/td>
&lt;td>評價數量&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>item_rating&lt;/td>
&lt;td>評價&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>image&lt;/td>
&lt;td>商品圖片(封面)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>images&lt;/td>
&lt;td>商品圖片&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>video_info_list&lt;/td>
&lt;td>影片&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>tier_variations&lt;/td>
&lt;td>規格&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>voucher_info&lt;/td>
&lt;td>優惠券資訊&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>* 回傳資料裡面並無&amp;quot;商品網址&amp;quot;，要自己串，如下所示：&lt;br />
&lt;code>https://shopee.tw/{商品名稱}-i.{賣場ID}.{商品ID}&lt;/code>&lt;br />
&lt;code>https://shopee.tw/犀牛盾-iPhone12-11-Pro-Mini-Se-XR-7-8-Xs-Max-手機-防摔殼-防摔邊框-台灣公司貨-i.9060351.1558498138&lt;/code>&lt;/p>
&lt;p>商品名稱中間加如有 &amp;quot; &amp;quot;(空白) 或 &amp;quot;/&amp;quot; 要轉換成 &amp;quot;-&amp;quot;，而且如有連續多個也要合併成一個。&lt;br />
但&amp;hellip;我發現商品網址其實不一定需要&amp;quot;商品網址&amp;quot;，就算這部分隨便給也都可以(但不能不給)，像是上方範例改成這樣也可😆。&lt;br />
&lt;code>https://shopee.tw/一代一代-i.9060351.1558498138&lt;/code>&lt;/p>
&lt;p>&lt;strong>[更新 2021/04/04]&lt;/strong> &amp;quot;商品網址&amp;quot;還有另一種樣式，就不需要包含商品名稱了，如下：&lt;br />
&lt;code>https://shopee.tw/product/{賣場ID}/{商品ID}&lt;/code>&lt;br />
&lt;code>https://shopee.tw/product/6453718/103810019&lt;/code>&lt;/p>
&lt;br/>
&lt;p>* 商品圖片是一串碼，要取得圖片網址需再如下自行補上，如要取得其縮圖(解析度較低、檔案較小)則再加上 &lt;code>_tn&lt;/code> 即可：&lt;br />
圖片網址：https://cf.shopee.tw/file/a8b82098b055a69c3b63b73fe1978caf&lt;br />
縮圖網址：https://cf.shopee.tw/file/a8b82098b055a69c3b63b73fe1978caf_tn&lt;/p>
&lt;p>* 影片網址則是先從 video_info_list 讀到 video_id，再如下組成網址：&lt;br />
影片網址：https://cv.shopee.tw/video/JmkCD3CvRP50uxb-&lt;/p>
&lt;p>* 可以從 &lt;code>adsid&lt;/code> 是否有值來判斷這間商品是否為廣告。&lt;/p>
&lt;h2 id="商品資訊">商品資訊&lt;/h2>
&lt;p>在商品頁面取得，相比上方&amp;quot;搜尋商品&amp;quot;得到的資訊來說，這邊會有更多的資訊，例如商品詳情、各規格較詳細資訊等等。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/shopee_spider/item_page.jpg" alt="商品頁面" data-caption="商品頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
商品頁面
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="請求路徑-1">請求路徑&lt;/h3>
&lt;p>GET &lt;code>https://shopee.tw/api/v2/item/get?itemid={商品ID}&amp;amp;shopid={賣場ID}&lt;/code>&lt;/p>
&lt;p>範例：&lt;code>https://shopee.tw/api/v2/item/get?itemid=1558498138&amp;amp;shopid=9060351&lt;/code>&lt;/p>
&lt;p>&lt;code>referer&lt;/code>：&lt;code>https://shopee.tw/{商品名稱}-i.{賣場ID}.{商品ID}&lt;/code>&lt;br />
(也就是此商品網址，還有記得將 url 編碼)&lt;br />
&lt;strong>[更新 2021/04/04]&lt;/strong> 或是 &lt;code>https://shopee.tw/product/{賣場ID}/{商品ID}&lt;/code>&lt;/p>
&lt;h3 id="請求參數-1">請求參數&lt;/h3>
&lt;p>參數很簡單，就只有 &lt;code>itemid&lt;/code> 和 &lt;code>shopid&lt;/code> 兩項：&lt;/p>
&lt;ul>
&lt;li>&lt;code>itemid&lt;/code>：商品ID。&lt;/li>
&lt;li>&lt;code>shopid&lt;/code>：賣場ID。&lt;/li>
&lt;/ul>
&lt;h3 id="回傳資料-1">回傳資料&lt;/h3>
&lt;p>同樣是以 JSON 格式回傳，資料內欄位很多，但大部分欄位都跟上面&amp;quot;搜尋商品&amp;quot;一樣，這邊列出幾個上面沒有但較重要的欄位：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>欄位&lt;/th>
&lt;th>代表意思&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>description&lt;/td>
&lt;td>商品詳情&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>estimated_days&lt;/td>
&lt;td>估計出貨天數&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>models&lt;/td>
&lt;td>各規格較詳細資訊&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;div class="expand">
&lt;button type="button" class="expand__button" aria-label="Expand Button">
&lt;span class="expand-icon expand-icon__right">
&lt;svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">&lt;path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/>&lt;/svg>
&lt;/span>
附上回傳資料範例：
&lt;/button>
&lt;div class="expand__content">
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt"> 10
&lt;/span>&lt;span class="lnt"> 11
&lt;/span>&lt;span class="lnt"> 12
&lt;/span>&lt;span class="lnt"> 13
&lt;/span>&lt;span class="lnt"> 14
&lt;/span>&lt;span class="lnt"> 15
&lt;/span>&lt;span class="lnt"> 16
&lt;/span>&lt;span class="lnt"> 17
&lt;/span>&lt;span class="lnt"> 18
&lt;/span>&lt;span class="lnt"> 19
&lt;/span>&lt;span class="lnt"> 20
&lt;/span>&lt;span class="lnt"> 21
&lt;/span>&lt;span class="lnt"> 22
&lt;/span>&lt;span class="lnt"> 23
&lt;/span>&lt;span class="lnt"> 24
&lt;/span>&lt;span class="lnt"> 25
&lt;/span>&lt;span class="lnt"> 26
&lt;/span>&lt;span class="lnt"> 27
&lt;/span>&lt;span class="lnt"> 28
&lt;/span>&lt;span class="lnt"> 29
&lt;/span>&lt;span class="lnt"> 30
&lt;/span>&lt;span class="lnt"> 31
&lt;/span>&lt;span class="lnt"> 32
&lt;/span>&lt;span class="lnt"> 33
&lt;/span>&lt;span class="lnt"> 34
&lt;/span>&lt;span class="lnt"> 35
&lt;/span>&lt;span class="lnt"> 36
&lt;/span>&lt;span class="lnt"> 37
&lt;/span>&lt;span class="lnt"> 38
&lt;/span>&lt;span class="lnt"> 39
&lt;/span>&lt;span class="lnt"> 40
&lt;/span>&lt;span class="lnt"> 41
&lt;/span>&lt;span class="lnt"> 42
&lt;/span>&lt;span class="lnt"> 43
&lt;/span>&lt;span class="lnt"> 44
&lt;/span>&lt;span class="lnt"> 45
&lt;/span>&lt;span class="lnt"> 46
&lt;/span>&lt;span class="lnt"> 47
&lt;/span>&lt;span class="lnt"> 48
&lt;/span>&lt;span class="lnt"> 49
&lt;/span>&lt;span class="lnt"> 50
&lt;/span>&lt;span class="lnt"> 51
&lt;/span>&lt;span class="lnt"> 52
&lt;/span>&lt;span class="lnt"> 53
&lt;/span>&lt;span class="lnt"> 54
&lt;/span>&lt;span class="lnt"> 55
&lt;/span>&lt;span class="lnt"> 56
&lt;/span>&lt;span class="lnt"> 57
&lt;/span>&lt;span class="lnt"> 58
&lt;/span>&lt;span class="lnt"> 59
&lt;/span>&lt;span class="lnt"> 60
&lt;/span>&lt;span class="lnt"> 61
&lt;/span>&lt;span class="lnt"> 62
&lt;/span>&lt;span class="lnt"> 63
&lt;/span>&lt;span class="lnt"> 64
&lt;/span>&lt;span class="lnt"> 65
&lt;/span>&lt;span class="lnt"> 66
&lt;/span>&lt;span class="lnt"> 67
&lt;/span>&lt;span class="lnt"> 68
&lt;/span>&lt;span class="lnt"> 69
&lt;/span>&lt;span class="lnt"> 70
&lt;/span>&lt;span class="lnt"> 71
&lt;/span>&lt;span class="lnt"> 72
&lt;/span>&lt;span class="lnt"> 73
&lt;/span>&lt;span class="lnt"> 74
&lt;/span>&lt;span class="lnt"> 75
&lt;/span>&lt;span class="lnt"> 76
&lt;/span>&lt;span class="lnt"> 77
&lt;/span>&lt;span class="lnt"> 78
&lt;/span>&lt;span class="lnt"> 79
&lt;/span>&lt;span class="lnt"> 80
&lt;/span>&lt;span class="lnt"> 81
&lt;/span>&lt;span class="lnt"> 82
&lt;/span>&lt;span class="lnt"> 83
&lt;/span>&lt;span class="lnt"> 84
&lt;/span>&lt;span class="lnt"> 85
&lt;/span>&lt;span class="lnt"> 86
&lt;/span>&lt;span class="lnt"> 87
&lt;/span>&lt;span class="lnt"> 88
&lt;/span>&lt;span class="lnt"> 89
&lt;/span>&lt;span class="lnt"> 90
&lt;/span>&lt;span class="lnt"> 91
&lt;/span>&lt;span class="lnt"> 92
&lt;/span>&lt;span class="lnt"> 93
&lt;/span>&lt;span class="lnt"> 94
&lt;/span>&lt;span class="lnt"> 95
&lt;/span>&lt;span class="lnt"> 96
&lt;/span>&lt;span class="lnt"> 97
&lt;/span>&lt;span class="lnt"> 98
&lt;/span>&lt;span class="lnt"> 99
&lt;/span>&lt;span class="lnt">100
&lt;/span>&lt;span class="lnt">101
&lt;/span>&lt;span class="lnt">102
&lt;/span>&lt;span class="lnt">103
&lt;/span>&lt;span class="lnt">104
&lt;/span>&lt;span class="lnt">105
&lt;/span>&lt;span class="lnt">106
&lt;/span>&lt;span class="lnt">107
&lt;/span>&lt;span class="lnt">108
&lt;/span>&lt;span class="lnt">109
&lt;/span>&lt;span class="lnt">110
&lt;/span>&lt;span class="lnt">111
&lt;/span>&lt;span class="lnt">112
&lt;/span>&lt;span class="lnt">113
&lt;/span>&lt;span class="lnt">114
&lt;/span>&lt;span class="lnt">115
&lt;/span>&lt;span class="lnt">116
&lt;/span>&lt;span class="lnt">117
&lt;/span>&lt;span class="lnt">118
&lt;/span>&lt;span class="lnt">119
&lt;/span>&lt;span class="lnt">120
&lt;/span>&lt;span class="lnt">121
&lt;/span>&lt;span class="lnt">122
&lt;/span>&lt;span class="lnt">123
&lt;/span>&lt;span class="lnt">124
&lt;/span>&lt;span class="lnt">125
&lt;/span>&lt;span class="lnt">126
&lt;/span>&lt;span class="lnt">127
&lt;/span>&lt;span class="lnt">128
&lt;/span>&lt;span class="lnt">129
&lt;/span>&lt;span class="lnt">130
&lt;/span>&lt;span class="lnt">131
&lt;/span>&lt;span class="lnt">132
&lt;/span>&lt;span class="lnt">133
&lt;/span>&lt;span class="lnt">134
&lt;/span>&lt;span class="lnt">135
&lt;/span>&lt;span class="lnt">136
&lt;/span>&lt;span class="lnt">137
&lt;/span>&lt;span class="lnt">138
&lt;/span>&lt;span class="lnt">139
&lt;/span>&lt;span class="lnt">140
&lt;/span>&lt;span class="lnt">141
&lt;/span>&lt;span class="lnt">142
&lt;/span>&lt;span class="lnt">143
&lt;/span>&lt;span class="lnt">144
&lt;/span>&lt;span class="lnt">145
&lt;/span>&lt;span class="lnt">146
&lt;/span>&lt;span class="lnt">147
&lt;/span>&lt;span class="lnt">148
&lt;/span>&lt;span class="lnt">149
&lt;/span>&lt;span class="lnt">150
&lt;/span>&lt;span class="lnt">151
&lt;/span>&lt;span class="lnt">152
&lt;/span>&lt;span class="lnt">153
&lt;/span>&lt;span class="lnt">154
&lt;/span>&lt;span class="lnt">155
&lt;/span>&lt;span class="lnt">156
&lt;/span>&lt;span class="lnt">157
&lt;/span>&lt;span class="lnt">158
&lt;/span>&lt;span class="lnt">159
&lt;/span>&lt;span class="lnt">160
&lt;/span>&lt;span class="lnt">161
&lt;/span>&lt;span class="lnt">162
&lt;/span>&lt;span class="lnt">163
&lt;/span>&lt;span class="lnt">164
&lt;/span>&lt;span class="lnt">165
&lt;/span>&lt;span class="lnt">166
&lt;/span>&lt;span class="lnt">167
&lt;/span>&lt;span class="lnt">168
&lt;/span>&lt;span class="lnt">169
&lt;/span>&lt;span class="lnt">170
&lt;/span>&lt;span class="lnt">171
&lt;/span>&lt;span class="lnt">172
&lt;/span>&lt;span class="lnt">173
&lt;/span>&lt;span class="lnt">174
&lt;/span>&lt;span class="lnt">175
&lt;/span>&lt;span class="lnt">176
&lt;/span>&lt;span class="lnt">177
&lt;/span>&lt;span class="lnt">178
&lt;/span>&lt;span class="lnt">179
&lt;/span>&lt;span class="lnt">180
&lt;/span>&lt;span class="lnt">181
&lt;/span>&lt;span class="lnt">182
&lt;/span>&lt;span class="lnt">183
&lt;/span>&lt;span class="lnt">184
&lt;/span>&lt;span class="lnt">185
&lt;/span>&lt;span class="lnt">186
&lt;/span>&lt;span class="lnt">187
&lt;/span>&lt;span class="lnt">188
&lt;/span>&lt;span class="lnt">189
&lt;/span>&lt;span class="lnt">190
&lt;/span>&lt;span class="lnt">191
&lt;/span>&lt;span class="lnt">192
&lt;/span>&lt;span class="lnt">193
&lt;/span>&lt;span class="lnt">194
&lt;/span>&lt;span class="lnt">195
&lt;/span>&lt;span class="lnt">196
&lt;/span>&lt;span class="lnt">197
&lt;/span>&lt;span class="lnt">198
&lt;/span>&lt;span class="lnt">199
&lt;/span>&lt;span class="lnt">200
&lt;/span>&lt;span class="lnt">201
&lt;/span>&lt;span class="lnt">202
&lt;/span>&lt;span class="lnt">203
&lt;/span>&lt;span class="lnt">204
&lt;/span>&lt;span class="lnt">205
&lt;/span>&lt;span class="lnt">206
&lt;/span>&lt;span class="lnt">207
&lt;/span>&lt;span class="lnt">208
&lt;/span>&lt;span class="lnt">209
&lt;/span>&lt;span class="lnt">210
&lt;/span>&lt;span class="lnt">211
&lt;/span>&lt;span class="lnt">212
&lt;/span>&lt;span class="lnt">213
&lt;/span>&lt;span class="lnt">214
&lt;/span>&lt;span class="lnt">215
&lt;/span>&lt;span class="lnt">216
&lt;/span>&lt;span class="lnt">217
&lt;/span>&lt;span class="lnt">218
&lt;/span>&lt;span class="lnt">219
&lt;/span>&lt;span class="lnt">220
&lt;/span>&lt;span class="lnt">221
&lt;/span>&lt;span class="lnt">222
&lt;/span>&lt;span class="lnt">223
&lt;/span>&lt;span class="lnt">224
&lt;/span>&lt;span class="lnt">225
&lt;/span>&lt;span class="lnt">226
&lt;/span>&lt;span class="lnt">227
&lt;/span>&lt;span class="lnt">228
&lt;/span>&lt;span class="lnt">229
&lt;/span>&lt;span class="lnt">230
&lt;/span>&lt;span class="lnt">231
&lt;/span>&lt;span class="lnt">232
&lt;/span>&lt;span class="lnt">233
&lt;/span>&lt;span class="lnt">234
&lt;/span>&lt;span class="lnt">235
&lt;/span>&lt;span class="lnt">236
&lt;/span>&lt;span class="lnt">237
&lt;/span>&lt;span class="lnt">238
&lt;/span>&lt;span class="lnt">239
&lt;/span>&lt;span class="lnt">240
&lt;/span>&lt;span class="lnt">241
&lt;/span>&lt;span class="lnt">242
&lt;/span>&lt;span class="lnt">243
&lt;/span>&lt;span class="lnt">244
&lt;/span>&lt;span class="lnt">245
&lt;/span>&lt;span class="lnt">246
&lt;/span>&lt;span class="lnt">247
&lt;/span>&lt;span class="lnt">248
&lt;/span>&lt;span class="lnt">249
&lt;/span>&lt;span class="lnt">250
&lt;/span>&lt;span class="lnt">251
&lt;/span>&lt;span class="lnt">252
&lt;/span>&lt;span class="lnt">253
&lt;/span>&lt;span class="lnt">254
&lt;/span>&lt;span class="lnt">255
&lt;/span>&lt;span class="lnt">256
&lt;/span>&lt;span class="lnt">257
&lt;/span>&lt;span class="lnt">258
&lt;/span>&lt;span class="lnt">259
&lt;/span>&lt;span class="lnt">260
&lt;/span>&lt;span class="lnt">261
&lt;/span>&lt;span class="lnt">262
&lt;/span>&lt;span class="lnt">263
&lt;/span>&lt;span class="lnt">264
&lt;/span>&lt;span class="lnt">265
&lt;/span>&lt;span class="lnt">266
&lt;/span>&lt;span class="lnt">267
&lt;/span>&lt;span class="lnt">268
&lt;/span>&lt;span class="lnt">269
&lt;/span>&lt;span class="lnt">270
&lt;/span>&lt;span class="lnt">271
&lt;/span>&lt;span class="lnt">272
&lt;/span>&lt;span class="lnt">273
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-JSON" data-lang="JSON">&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;item&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;itemid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">6155409258&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;price_max_before_discount&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">-1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;item_status&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;normal&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;can_use_wholesale&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;show_free_shipping&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;estimated_days&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">20&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_hot_sales&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_slash_price_item&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;upcoming_flash_sale&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;slash_lowest_price&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_partial_fulfilled&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;condition&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;show_original_guarantee&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;add_on_deal_info&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_non_cc_installment_payment_eligible&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;categories&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;display_name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;手機平板與周邊&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;catid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">70&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;image&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;no_sub&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_default_subcat&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;block_buyer_platform&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;display_name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;手機周邊配件&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;catid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1579&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;image&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;no_sub&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_default_subcat&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;block_buyer_platform&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;display_name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;轉接電視棒、線&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;catid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">16762&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;image&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;no_sub&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">true&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_default_subcat&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;block_buyer_platform&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;ctime&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1601691912&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;【WoW世界代購】2020 Google Chromecast with Google TV 4k HDMI媒體串流播放&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;show_shopee_verified_label&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;size_chart&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_pre_order&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">true&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;service_by_shopee_flag&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;historical_sold&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1428&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;reference_item_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;recommendation_info&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;bundle_deal_info&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;price_max&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">210000000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;has_lowest_price_guarantee&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;shipping_icon_type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;images&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="s2">&amp;#34;82ddad81bd0cc6b03d797acbdf51c7cd&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;bb192fb5989cef4358a5377100965fd8&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;1ee7c425fedb0b5f0cfef7dddf475ec1&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;f0df75429124a11407597908abf76f7f&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;46d282f0742b2ea5fe9a21fafacf6c03&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;044f715ffd1e982989aa50fd35370bcc&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;6a8bf7deb89df6cc49edd27612cc8604&amp;#34;&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;price_before_discount&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;cod_flag&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;catid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">70&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_official_shop&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;coin_earn_label&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;hashtag_list&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;sold&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">210&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;makeup&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;item_rating&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;rating_star&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">4.96895&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;rating_count&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="mi">1096&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="mi">21&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="mi">1069&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;rcount_with_image&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">150&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;rcount_with_context&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">305&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;show_official_shop_label_in_title&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;discount&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;reason&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;label_ids&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="mi">1001276&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="mi">1000575&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="mi">1000630&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="mi">1002199&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="mi">1002826&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;has_group_buy_stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;other_stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">35&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;deep_discount&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;attributes&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;is_pending_qc&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;idx&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;value&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Google&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">7958&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_timestamp&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;品牌&amp;#34;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;badge_icon_type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;liked&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;cmt_count&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1096&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;image&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;82ddad81bd0cc6b03d797acbdf51c7cd&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;recommendation_algorithm&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_cc_installment_payment_eligible&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">true&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;shopid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">3149132&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;normal_stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">35&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;video_info_list&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[],&lt;/span>
&lt;span class="nt">&amp;#34;installment_plans&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;view_count&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">15059&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;voucher_info&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;current_promotion_has_reserve_stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;liked_count&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">934&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;show_official_shop_label&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;price_min_before_discount&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">-1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;show_discount&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;preview_info&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;flag&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">720896&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;exclusive_price_info&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;current_promotion_reserved_stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;wholesale_tier_list&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[],&lt;/span>
&lt;span class="nt">&amp;#34;group_buy_info&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;shopee_verified&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;item_has_post&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;hidden_price_display&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;transparent_background_image&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;welcome_package_info&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;discount_stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;coin_info&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;spend_cash_unit&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">100000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;coin_earn_items&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;is_adult&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;currency&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;TWD&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;raw_discount&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_preferred_plus_seller&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_category_failed&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;price_min&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">210000000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;can_use_bundle_deal&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;cb_option&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;brand&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">35&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;status&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;bundle_deal_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;is_group_buy_item&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;description&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;原廠保固一年，我們免費代送保固哦！\n\n下單後才代購，預計3/9左右抵台灣出貨，出貨時會通知，......&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;flash_sale&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;models&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;itemid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">6155409258&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;status&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;current_promotion_reserved_stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;粉紅（缺貨）&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;promotionid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;price&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">220000000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;price_stocks&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;model_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">23792748542&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;stockout_time&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1609939591&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;region&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;TW&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;rebate&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;price&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">220000000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;promotion_type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;allocated_stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;shop_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">3149132&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;end_time&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;stock_breakdown_by_location&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[],&lt;/span>
&lt;span class="nt">&amp;#34;item_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">6155409258&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;promotion_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;purchase_limit&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;start_time&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;current_promotion_has_reserve_stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;currency&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;TWD&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;normal_stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;extinfo&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;seller_promotion_limit&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;has_shopee_promo&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;group_buy_info&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;holiday_mode_old_stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;tier_index&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="mi">2&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;seller_promotion_refresh_time&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;price_before_discount&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;modelid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">23792748542&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;sold&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;itemid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">6155409258&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;status&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;current_promotion_reserved_stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;白色snow(3/9出貨)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;promotionid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;price&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">210000000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;price_stocks&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;model_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">51236728441&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;stockout_time&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;region&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;TW&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;rebate&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;price&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">210000000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;promotion_type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;allocated_stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;shop_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">3149132&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;end_time&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;stock_breakdown_by_location&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[],&lt;/span>
&lt;span class="nt">&amp;#34;item_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">6155409258&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;promotion_id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;purchase_limit&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;start_time&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">35&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;current_promotion_has_reserve_stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;currency&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;TWD&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;normal_stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">35&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;extinfo&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;seller_promotion_limit&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;has_shopee_promo&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;group_buy_info&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;holiday_mode_old_stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;tier_index&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="mi">0&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;seller_promotion_refresh_time&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;price_before_discount&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;modelid&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">51236728441&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;sold&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">1329&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;stock&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">35&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;has_low_fulfillment_rate&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;price&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">210000000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;shop_location&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;高雄市苓雅區&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;tier_variations&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="nt">&amp;#34;images&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[],&lt;/span>
&lt;span class="nt">&amp;#34;properties&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[],&lt;/span>
&lt;span class="nt">&amp;#34;type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;顏色&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;options&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;span class="s2">&amp;#34;白色snow(3/9出貨)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s2">&amp;#34;粉紅（缺貨）&amp;#34;&lt;/span>
&lt;span class="p">]&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">],&lt;/span>
&lt;span class="nt">&amp;#34;can_use_cod&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;makeups&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;welcome_package_type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;show_official_shop_label_in_normal_position&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;item_type&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="nt">&amp;#34;version&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;3ce549a98de8723d3e24613cc448f7f8&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;data&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;error_msg&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="nt">&amp;#34;error&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">null&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;h2 id="評價資訊">評價資訊&lt;/h2>
&lt;p>評價資訊指的是商品頁面底下，買家對於此商品的評分、評論、照片、影片等資料。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/shopee_spider/ratings.jpg" alt="評價資訊" data-caption="評價資訊" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
評價資訊
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="請求路徑-2">請求路徑&lt;/h3>
&lt;p>GET &lt;code>https://shopee.tw/api/v2/item/get_ratings?filter=0&amp;amp;flag=1&amp;amp;itemid={商品ID}&amp;amp;limit=6&amp;amp;offset=0&amp;amp;shopid={賣場ID}&amp;amp;type=0&lt;/code>&lt;/p>
&lt;p>範例：&lt;code>https://shopee.tw/api/v2/item/get_ratings?filter=0&amp;amp;flag=1&amp;amp;itemid=1558498138&amp;amp;limit=6&amp;amp;offset=0&amp;amp;shopid=9060351&amp;amp;type=0&lt;/code>&lt;/p>
&lt;p>&lt;code>referer&lt;/code>：&lt;code>https://shopee.tw/{商品名稱}-i.{賣場ID}.{商品ID}&lt;/code>&lt;br />
(同樣是此商品網址，一樣記得將 url 編碼)&lt;/p>
&lt;h3 id="請求參數-2">請求參數&lt;/h3>
&lt;p>來看一下評價資訊的請求網址帶哪些參數：&lt;/p>
&lt;ul>
&lt;li>&lt;code>shopid&lt;/code>：賣場ID。&lt;/li>
&lt;li>&lt;code>itemid&lt;/code>：商品ID。&lt;/li>
&lt;li>&lt;code>flag&lt;/code> 和 &lt;code>type&lt;/code>：篩選條件。&lt;/li>
&lt;/ul>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>篩選&lt;/th>
&lt;th>filter&lt;/th>
&lt;th>type&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>全部留言&lt;/td>
&lt;td>0&lt;/td>
&lt;td>0&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>五星留言&lt;/td>
&lt;td>0&lt;/td>
&lt;td>5&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>四星留言&lt;/td>
&lt;td>0&lt;/td>
&lt;td>4&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>三星留言&lt;/td>
&lt;td>0&lt;/td>
&lt;td>3&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>二星留言&lt;/td>
&lt;td>0&lt;/td>
&lt;td>2&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>一星留言&lt;/td>
&lt;td>0&lt;/td>
&lt;td>1&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>附上評論&lt;/td>
&lt;td>1&lt;/td>
&lt;td>0&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>附上照片/影片&lt;/td>
&lt;td>3&lt;/td>
&lt;td>0&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>* 經過嘗試，發現兩者貌似無法混用，例如無法篩選&amp;quot;附上評論的三星留言&amp;quot;這樣。&lt;/p>
&lt;ul>
&lt;li>&lt;code>limit&lt;/code>：一次請求最大回傳的結果數量，預設 15 個、最多 59 個，但如果給超過 59 個，反而會回傳 0 個。&lt;/li>
&lt;li>&lt;code>offset&lt;/code>：偏移值。&lt;/li>
&lt;li>&lt;code>flag&lt;/code>：未知。&lt;/li>
&lt;/ul>
&lt;h3 id="回傳資料-2">回傳資料&lt;/h3>
&lt;p>它也是以 JSON 格式回傳，&lt;code>data&lt;/code> 底下有 &lt;code>item_rating_summary&lt;/code> 與 &lt;code>ratings&lt;/code> 兩個欄位。&lt;br />
&lt;code>item_rating_summary&lt;/code> 是總評價的統計，像是總評分為幾分、有幾個五星評價、有幾個加上照片/影片的評價；&lt;code>ratings&lt;/code> 裡面就是各評價的詳細資料。&lt;/p>
&lt;p>以下我列出一些各評價中比較重要的欄位，如與上方有重複的就不再寫出來：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>欄位&lt;/th>
&lt;th>代表意思&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>rating_star&lt;/td>
&lt;td>評分(星等)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>author_portrait&lt;/td>
&lt;td>作者大頭照&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>cmtid&lt;/td>
&lt;td>評價ID&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>author_username&lt;/td>
&lt;td>評分者帳號&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>author_shopid&lt;/td>
&lt;td>評分者賣場ID&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>comment&lt;/td>
&lt;td>評論&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>anonymous&lt;/td>
&lt;td>是否匿名&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ctime&lt;/td>
&lt;td>創建評分時間(時間戳)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>mtime&lt;/td>
&lt;td>修改評分時間(時間戳)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>product_items &amp;gt; model_name&lt;/td>
&lt;td>評分者購買商品的規格&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ItemRatingReply&lt;/td>
&lt;td>賣家回應&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>* 作者大頭照與之前圖片一樣，網址 &lt;code>https://cf.shopee.tw/file/&lt;/code> 再加上圖片ID即可。&lt;/p>
&lt;p>* 這邊影片網址不需要再像上面那樣串，它直接給影片網址了。&lt;/p>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="延伸練習">延伸練習&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>試著將&amp;quot;搜尋商品&amp;quot;、&amp;quot;商品資訊&amp;quot;、&amp;quot;評分資訊&amp;quot;的抓取資料挑選、整理之後，儲存到檔案(txt、csv、json)中。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>以上文章說明抓取&amp;quot;搜尋商品&amp;quot;、&amp;quot;商品資訊&amp;quot;、&amp;quot;評分資訊&amp;quot;，請試著自己寫寫看&amp;quot;如何取得指定賣場內商品&amp;quot;？&lt;br />
例如：&lt;a href="https://shopee.tw/shop/48032592/search" target="_blank" rel="noopener">
Logitech羅技官方旗艦館
&lt;/a> 裡頭所販售的所有商品。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="注意事項">注意事項&lt;/h2>
&lt;p>後來發現如果短時間太頻繁的送出請求，會被伺服器阻擋，貌似正常獲得資料，但其實仔細看會發現資料有誤，例如價格很明顯不正確等等。&lt;/p>
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>在尋找、爬取&amp;quot;蝦皮購物&amp;quot;的相關資料時會覺得很有趣，因為它是使用 API 的方式去請求資料，也不用自己寫 BeautifulSoup 來解析網頁，一步步尋找個參數代表什麼意思，我想這也是在寫爬蟲程式過程的樂趣吧。&lt;/p>
&lt;p>之後會繼續陸續寫一些網站的&lt;a href="https://blog.jiatool.com/series/Python%e7%b6%b2%e8%b7%af%e7%88%ac%e8%9f%b2%e5%af%a6%e4%be%8b/" target="_blank" rel="noopener">
Python網路爬蟲實例
&lt;/a>，如果你正好是剛開始想學爬蟲的新手、想知道某網站如何爬取資料，又或遇到其他問題，歡迎參考與在底下留言喔~🔖&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;blockquote>
&lt;p>逆風的方向，更適合飛翔，我不怕千萬人阻擋，只怕自己投降。&lt;/p>
&lt;p align="right">—— 五月天《倔強》&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/shopee_spider.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/shopee_spider_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Python</category><category>網路爬蟲</category><category>Python網路爬蟲實例</category></item><item><title>《PUI PUI 天竺鼠車車》簡單趨勢分析，同場加映：Python 爬取 Google 每日搜尋趨勢</title><link>https://blog.jiatool.com/posts/puipui_trend/</link><pubDate>Sun, 07 Feb 2021 20:30:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sun, 07 Feb 2021 20:30:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/puipui_trend/</guid><description>前言 小孩才看鬼滅之刃，大人都看天竺鼠車車！！ 最近《PUI PUI 天竺鼠車車》超紅🔥🔥🔥，算是繼鬼滅之刃後下一個爆紅的動畫作品，不曉得你上車了嗎？ 本</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>小孩才看鬼滅之刃，大人都看天竺鼠車車！！&lt;br />
最近《PUI PUI 天竺鼠車車》超紅🔥🔥🔥，算是繼鬼滅之刃後下一個爆紅的動畫作品，不曉得你上車了嗎？&lt;/p>
&lt;p>本篇文章第一部分會介紹這部爆紅的作品《PUI PUI 天竺鼠車車》，接下來將簡單帶大家來看天竺鼠車車在台灣的趨勢，最後還會有 Python 爬取 &amp;quot;Google 每日搜尋趨勢&amp;quot; 的講解與教學，千萬不要錯過！！&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/puipui_trend/puipui01.jpg" alt="《PUI PUI 天竺鼠車車》 圖片來源：PUI PUI 天竺鼠車車 官方網站" data-caption="《PUI PUI 天竺鼠車車》 圖片來源：PUI PUI 天竺鼠車車 官方網站" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
《PUI PUI 天竺鼠車車》 圖片來源：PUI PUI 天竺鼠車車 官方網站
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="天竺鼠車車介紹">🐹《天竺鼠車車》介紹&lt;/h2>
&lt;p>天竺鼠車車全名《PUI PUI 天竺鼠車車》，為日本原創採用羊毛氈製作的電視定格動畫，&amp;quot;PUI PUI&amp;quot;是代表天竺鼠真實的叫聲，每話片長非常短只有 2 分 40 秒，而且是沒有對話或旁白的。&lt;br />
(原本是做給兒童看的，沒想到在大人間爆紅🤣)&lt;/p>
&lt;p>引用 &lt;a href="https://www.youtube.com/playlist?list=PL12UaAf_xzfq1Qw3hO43WvcgAo_Sju6Ix" target="_blank" rel="noopener">
Muse木棉花-TW
&lt;/a> 內簡介&lt;/p>
&lt;blockquote>
&lt;p>故事舞臺發生在一個天竺鼠變成車子的世界。 療癒系的車“天竺鼠車車”。圓滾滾的眼睛和又大又圓的屁股，短短的手腳。常常一臉傻乎乎地四處奔波的天竺鼠車車。&lt;br />
即使塞車了，只要看著前面的天竺鼠車車的屁股就能被療癒，就算製造了一些麻煩，因為毛茸茸太可愛了也能原諒吧？！&lt;br />
以汽車各式各樣的情境為中心的療癒、友情、冒險、亂七八糟的動作戲以及超多天竺鼠的動畫！&lt;/p>
&lt;/blockquote>
&lt;p>引用 &lt;a href="https://ani.gamer.com.tw/animeVideo.php?sn=20454" target="_blank" rel="noopener">
巴哈姆特動畫瘋
&lt;/a> 內簡介&lt;/p>
&lt;blockquote>
&lt;p>《PUI PUI 天竺鼠車車》是以羊毛氈天竺鼠來創作的偶動畫，如果將車子通通「擬豬化」，這個世界會變得如何呢？&lt;br />
以天竺鼠作為交通工具的世界觀，發展出一連串療癒、友情與冒險的故事。變成車子的天竺鼠，還是保有豬豬的個性，會排隊行動，容易驚嚇，又因為貪吃而爭先恐後引發大騷動，只差沒有黑豆噴射攻擊了！而且用羊毛氈表現的天竺鼠表情，實在是很寫實逗趣啊！&lt;br />
動畫監督見里朝希，以偶動畫創作獲得多項國際大獎，劇名裡的「PUI PUI」就是天竺鼠的叫聲。&lt;/p>
&lt;/blockquote>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/puipui_trend/puipui02.jpg" alt="《PUI PUI 天竺鼠車車》 圖片來源：Muse木棉花 FB粉專" data-caption="《PUI PUI 天竺鼠車車》 圖片來源：Muse木棉花 FB粉專" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
《PUI PUI 天竺鼠車車》 圖片來源：Muse木棉花 FB粉專
&lt;/figcaption>
&lt;/figure>
&lt;p>如還你沒看過、想要觀看，歡迎至以下正版平台收看。&lt;br />
(1/5(二) 起，每週二 07:35 與日同步更新)&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://www.youtube.com/playlist?list=PL12UaAf_xzfq1Qw3hO43WvcgAo_Sju6Ix" target="_blank" rel="noopener">
Muse木棉花 YouTube 官方頻道
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://ani.gamer.com.tw/animeVideo.php?sn=20454" target="_blank" rel="noopener">
巴哈姆特動畫瘋
&lt;/a>&lt;/li>
&lt;li>&lt;a href="http://mod.cht.com.tw/video/movie-details.php?id=729229" target="_blank" rel="noopener">
中華電信MOD
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://hamivideo.hinet.net/product/140209.do" target="_blank" rel="noopener">
Hami Video
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.myvideo.net.tw/details/3/14701" target="_blank" rel="noopener">
MyVideo影音隨看
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://video.friday.tw/anime/detail/1734" target="_blank" rel="noopener">
遠傳FriDay影音
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.litv.tv/vod/kids/content.do?content_id=VOD00201158" target="_blank" rel="noopener">
LiTV線上影視
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.kktv.me/titles/06000841" target="_blank" rel="noopener">
KKTV
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.linetv.tw/drama/11849/eps/1" target="_blank" rel="noopener">
LINE TV
&lt;/a>&lt;/li>
&lt;li>中嘉bb寬頻.bbTV&lt;/li>
&lt;li>&lt;a href="https://tw.tv.yahoo.com/puipui-molcar/%E5%A4%A9%E7%AB%BA%E9%BC%A0%E8%BB%8A%E8%BB%8A-ep01-%E5%AE%8C%E6%95%B4%E7%89%88-065204788.html" target="_blank" rel="noopener">
YAHOO TV
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.catchplay.com/tw/video/cbca2c35-5eb9-11eb-9cf7-026834468022" target="_blank" rel="noopener">
台灣CatchPlay
&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.ttv.com.tw/taiwan/ttvinfo/view/7243/651" target="_blank" rel="noopener">
CH08台視
&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>題外話，之前看到一篇文章訪問、講解為何木棉花代理動畫卻免費放送，因盜版猖獗，有許多非常途徑可以看到動畫，因此木棉花轉變觀念，希望由動漫帶動後面周邊商品開發、授權聯名等營業項目。&lt;br />
有興趣的朋友可以過去看看：&lt;a href="https://www.managertoday.com.tw/articles/view/62364" target="_blank" rel="noopener">
《鬼滅》《天竺鼠車車》幕後推手！代理動畫卻免費放送，木棉花在想什麼？
&lt;/a>&lt;/p>
&lt;h2 id="天竺鼠車車在台灣的-google-搜尋趨勢">🐹《天竺鼠車車》在台灣的 Google 搜尋趨勢&lt;/h2>
&lt;p>在 &lt;a href="https://trends.google.com.tw/trends/explore" target="_blank" rel="noopener">
Google 趨勢探索
&lt;/a>頁面，我將 &amp;quot;天竺鼠&amp;quot; 與 &amp;quot;天竺鼠車車&amp;quot; 關鍵字輸入，一同觀看《天竺鼠車車》從 2021 年 1 月 5 日開播以來的搜尋趨勢變化，這邊關鍵字我輸入 &amp;quot;天竺鼠&amp;quot; 和 &amp;quot;天竺鼠車車&amp;quot; 兩個，因為可能很多人搜尋不會將全名打出來。&lt;br />
並且我將前五話的播出時間點標記出來，方便對照觀察。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/puipui_trend/puipui_explore.jpg" alt="&amp;#34;天竺鼠&amp;#34; 搜尋趨勢 2021/01/01~2021/02/05" data-caption="&amp;#34;天竺鼠&amp;#34; 搜尋趨勢 2021/01/01~2021/02/05" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;天竺鼠&amp;#34; 搜尋趨勢 2021/01/01~2021/02/05
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>明顯看出一開始並沒有造成話題，但在 1/20 達到顛峰，也就是在星期二(1/19) 第 03 話播出後的隔天最多人搜尋，仔細想想大部分的人聽到、知道這部動畫應該也是差不多那個時候，而且如果去搜尋天竺鼠車車相關文章與影片(討論、分析)，會發現許多都是在第 03 話附近的時間點發文的。&lt;br />
然後在後續第 04 話、第 05 話播出當天，搜尋量也有小幅提升。&lt;/p>
&lt;br/>
&lt;br/>
&lt;p>接下來看看 &lt;a href="https://trends.google.com.tw/trends/trendingsearches/daily" target="_blank" rel="noopener">
Google 每日搜尋趨勢
&lt;/a>，尋找 &amp;quot;天竺鼠車車&amp;quot; 是否有登上哪一天的台灣搜尋排行榜。&lt;/p>
&lt;p>我簡單使用 Python 來爬取每一天的 Google 每日搜尋趨勢(後面會再說明該如何做到)，發現到從開播以來只有 1/19 當天上榜，直接衝上第二名，在台灣的搜尋量達到 10 萬多筆。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/puipui_trend/trending_searches.jpg" alt="&amp;#34;天竺鼠車車&amp;#34; Google 每日搜尋趨勢" data-caption="&amp;#34;天竺鼠車車&amp;#34; Google 每日搜尋趨勢" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;天竺鼠車車&amp;#34; Google 每日搜尋趨勢
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>我來稍微說明一下，可能看到&amp;quot;探索&amp;quot;圖表我輸入的關鍵字有人會感到疑惑，為何是輸入&amp;quot;天竺鼠 車 車&amp;quot;而不是&amp;quot;天竺鼠車車&amp;quot;，中間幹嘛要加入空格呢？&lt;br />
這邊是經過嘗試並參考以下文章內提到 Google Trends 中文分詞的 bug，所以修正關鍵字的。&lt;br />
&lt;a href="https://frankchiu.io/seo-how-to-use-google-trends/" target="_blank" rel="noopener">
揭密 Google Trends 正確使用方式：為何 90% 人都用錯 Google Trends？｜Google Trends 教學
&lt;/a>&lt;/p>
&lt;h2 id="爬取-google-每日搜尋趨勢">🐹爬取 &amp;quot;Google 每日搜尋趨勢&amp;quot;&lt;/h2>
&lt;p>這邊要注意，底下的教學是爬取 &lt;a href="https://trends.google.com.tw/trends/trendingsearches/daily" target="_blank" rel="noopener">
&amp;quot;每日搜尋趨勢&amp;quot;
&lt;/a>，而不是可以自行輸入關鍵字的 &lt;a href="https://trends.google.com.tw/trends/explore" target="_blank" rel="noopener">
&amp;quot;探索&amp;quot;
&lt;/a>。&lt;br />
&amp;quot;探索&amp;quot; 功能之後有機會會再寫一篇文章來介紹，想看的麻煩在本文章底下、&lt;a href="https://home.gamer.com.tw/creation.php?owner=g919233" target="_blank" rel="noopener">
巴哈姆特
&lt;/a>或&lt;a href="https://www.facebook.com/jiatool" target="_blank" rel="noopener">
FB粉專
&lt;/a>留言讓我知道~&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/puipui_trend/daily_explore.jpg" alt="Google &amp;#34;每日搜尋趨勢&amp;#34; 與 &amp;#34;探索&amp;#34;" data-caption="Google &amp;#34;每日搜尋趨勢&amp;#34; 與 &amp;#34;探索&amp;#34;" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
Google &amp;#34;每日搜尋趨勢&amp;#34; 與 &amp;#34;探索&amp;#34;
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;h3 id="尋找爬取方法">尋找爬取方法&lt;/h3>
&lt;p>首先進到 &lt;a href="https://trends.google.com.tw/trends/trendingsearches/daily" target="_blank" rel="noopener">
&amp;quot;Google 每日搜尋趨勢&amp;quot;
&lt;/a> 網頁，上方可以選擇國家，底下是依照每天使用者在 Google 搜尋量來排名。&lt;/p>
&lt;p>當我們把網頁滾到最下面，發現到有 &amp;quot;載入更多&amp;quot; 的按鈕，我們可以猜測網頁是否使用 JavaScript 來動態載入更多資料。&lt;br />
打開瀏覽器的&amp;quot;開發人員工具(F12)&amp;quot;，並切換到 &amp;quot;Network&amp;quot; &amp;gt; &amp;quot;XHR&amp;quot; 頁面，滑鼠點擊&amp;quot;載入更多&amp;quot;按鈕。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/puipui_trend/network_xhr01.jpg" alt="&amp;#34;開發人員工具(F12)&amp;#34; &amp;gt; &amp;#34;Network&amp;#34; &amp;gt; &amp;#34;XHR&amp;#34;" data-caption="&amp;#34;開發人員工具(F12)&amp;#34; &amp;gt; &amp;#34;Network&amp;#34; &amp;gt; &amp;#34;XHR&amp;#34;" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;開發人員工具(F12)&amp;#34; &amp;gt; &amp;#34;Network&amp;#34; &amp;gt; &amp;#34;XHR&amp;#34;
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>可以發現確實網頁有新資料顯示，&amp;quot;XHR&amp;quot; 頁面也有一個 GET 請求。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/puipui_trend/network_xhr02.jpg" alt="點擊&amp;#34;載入更多&amp;#34;後會載入更多資料" data-caption="點擊&amp;#34;載入更多&amp;#34;後會載入更多資料" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
點擊&amp;#34;載入更多&amp;#34;後會載入更多資料
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>滑鼠對它點擊，切到 &amp;quot;Preview&amp;quot; 稍微觀察一下資料。&lt;br />
沒錯！！這就是我們想要抓取的資料。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/puipui_trend/preview.png" alt="&amp;#34;Preview&amp;#34; 頁面" data-caption="&amp;#34;Preview&amp;#34; 頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;Preview&amp;#34; 頁面
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>在 &amp;quot;Headers&amp;quot; 的地方可以找到請求的網址與方法：&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/puipui_trend/headers.png" alt="&amp;#34;Headers&amp;#34; 有請求的網址與方法" data-caption="&amp;#34;Headers&amp;#34; 有請求的網址與方法" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;Headers&amp;#34; 有請求的網址與方法
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;pre>&lt;code>Request URL: https://trends.google.com.tw/trends/api/dailytrends?hl=zh-TW&amp;amp;tz=-480&amp;amp;ed=20210203&amp;amp;geo=TW&amp;amp;ns=15
Request Method: GET
&lt;/code>&lt;/pre>&lt;br/>
&lt;p>從請求網址後方可以發現它有帶五個傳遞參數(網址&lt;code>?&lt;/code>後方)，分別如下：&lt;/p>
&lt;pre>&lt;code>hl: zh-TW
tz: -480
ed: 20210206
geo: TW
ns: 15
&lt;/code>&lt;/pre>&lt;ul>
&lt;li>&lt;code>hl&lt;/code> 代表語言，台灣的繁體中文是&lt;code>zh-TW&lt;/code>。其他語言可以藉由切換網頁上的語言來查看送出的請求他帶什麼數值，或參考&lt;a href="https://sites.google.com/site/tomihasa/google-language-codes" target="_blank" rel="noopener">
此網頁列表
&lt;/a>。&lt;/li>
&lt;li>&lt;code>tz&lt;/code> 代表時區偏移量，單位是分鐘，因此台灣時區是 +8 也就是 8*60=480，然後負的代表我們時間要減 480 分鐘才會等於格林威治標準時間。&lt;/li>
&lt;li>&lt;code>geo&lt;/code> 代表國家縮寫，例如台灣是&lt;code>TW&lt;/code>、美國是&lt;code>US&lt;/code>。&lt;/li>
&lt;li>&lt;code>ed&lt;/code> 代表查詢的日期，採&amp;quot;年年年年月月日日&amp;quot;的方式排列，像是 &amp;quot;20200520&amp;quot;、&amp;quot;20210207&amp;quot;。&lt;/li>
&lt;li>&lt;code>ns&lt;/code> 目前尚未查到它代表什麼意思。&lt;/li>
&lt;/ul>
&lt;br/>
&lt;p>而收到的資料中，最前方第一行有段干擾的文字「&lt;code>)]}',\n&lt;/code>」，後方才是正確的 json 格式資料。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/puipui_trend/response_data.png" alt="&amp;#34;Response&amp;#34; 頁面可察看回應資料" data-caption="&amp;#34;Response&amp;#34; 頁面可察看回應資料" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
&amp;#34;Response&amp;#34; 頁面可察看回應資料
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>裡頭的資料跟你在網頁會看到的差不多，關鍵字、搜尋量、相關新聞、相關查詢、圖片連結、關鍵字探索連結等等。&lt;/p>
&lt;h3 id="python-範例程式">Python 範例程式&lt;/h3>
&lt;p>接下來，我們將以上流程寫成 Python 程式，以下示範請求 2021/02/01 當天台灣的 Google 每日搜尋趨勢：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">json&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;span class="n">HEADERS&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;User-Agent&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36&amp;#39;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;span class="n">date_str&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;20210201&amp;#39;&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://trends.google.com.tw/trends/api/dailytrends?hl=zh-TW&amp;amp;geo=TW&amp;amp;tz=-480&amp;amp;ns=15&amp;amp;ed={date_str}&amp;#39;&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">HEADERS&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">lstrip&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;)]}&amp;#39;,&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">data_json&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">json&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">loads&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">trends&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data_json&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;default&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;trendingSearchesDays&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">trends&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;請求失敗：{r.status_code}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>而經過測試，Google 每日搜尋趨勢最多提供最近 30 天的資料，每天最多前 20 個熱門關鍵字，好像當天關鍵字搜尋量不到 2000+ 就不會排出來，所以有些天數的熱門關鍵字不到 20 個。&lt;/p>
&lt;br/>
&lt;p>如果你想使用迴圈來一次爬取好幾個日期，可以參考以下方式來取得一段日期列表，再執行迴圈來請求：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="kn">from&lt;/span> &lt;span class="nn">datetime&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">date&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timedelta&lt;/span>
&lt;span class="n">base_date&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">date&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">today&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">days_num&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">3&lt;/span>
&lt;span class="n">date_list&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">base_date&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">timedelta&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">days&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">x&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">days_num&lt;/span>&lt;span class="p">)]&lt;/span>
&lt;span class="c1"># [&amp;#39;20210206&amp;#39;, &amp;#39;20210205&amp;#39;, &amp;#39;20210204&amp;#39;]&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">date_&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">date_list&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">date_str&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">date_&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strftime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;%Y%m&lt;/span>&lt;span class="si">%d&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># ...&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>* 記得多次請求之間要加入一點延遲，才不會被擋ㄛ~&lt;/p>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>如果你還沒看過《PUI PUI 天竺鼠車車》的話，趕緊去各正版平台觀看，反正每話也才不到 3 分鐘，一下子就看完了🤣&lt;/p>
&lt;p>最後提醒，在飼養動物都要了解其習性，並評估自身及經濟狀況，不要因為一時熱潮而衝動購買，要尊重生命。&lt;/p>
&lt;br/>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://molcar-anime.com/" target="_blank" rel="noopener">
PUI PUI 天竺鼠車車 官方網站
&lt;/a>&lt;br />
&lt;a href="https://www.youtube.com/channel/UCgdwtyqBunlRb-i-7PnCssQ" target="_blank" rel="noopener">
Muse木棉花 YouTube 官方頻道
&lt;/a>&lt;br />
&lt;a href="https://ani.gamer.com.tw/" target="_blank" rel="noopener">
巴哈姆特動畫瘋
&lt;/a>&lt;/p>
&lt;br/>
&lt;blockquote>
&lt;p>PUI~PUI~PUI~PUI~PUI~PUI~PUI~PUI~PUI~&lt;/p>
&lt;p align="right">—— 天竺鼠&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/puipui_trend.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/puipui_trend_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Python</category><category>Google趨勢</category><category>網路爬蟲</category></item><item><title>Google 搜尋結果 API — Aves API 完整教學</title><link>https://blog.jiatool.com/posts/aves_api/</link><pubDate>Sat, 30 Jan 2021 20:55:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sat, 18 Nov 2023 21:50:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/aves_api/</guid><description>(先澄清，以下非業配，純粹依個人使用過程描述。) 前言 因為某原因，需要爬取&amp;quot;Google 搜尋&amp;quot;頁面上的資料，沒多久前舊有的</description><content:encoded>&lt;p>(先澄清，以下非業配，純粹依個人使用過程描述。)&lt;/p>
&lt;h2 id="前言">前言&lt;/h2>
&lt;p>因為某原因，需要爬取&amp;quot;Google 搜尋&amp;quot;頁面上的資料，沒多久前舊有的網頁爬蟲請求失敗了!! (不妙啊&amp;hellip;&lt;/p>
&lt;p>後來多次嘗試，也改用手機網路分享(不同IP)測試，也是遇到同樣的問題&amp;quot;HTTP Error 429: Too Many Requests&amp;quot;，並需要通過 &lt;a href="https://zh.wikipedia.org/wiki/ReCAPTCHA" target="_blank" rel="noopener">
reCAPTCHA 驗證
&lt;/a>。&lt;br />
📢 白話翻譯：你短時間送出太多請求了，一般人不可能這麼頻繁，我嚴重懷疑你是機器人，先出個題目讓你回答(&lt;a href="https://technews.tw/2018/12/17/keying-recaptcha-working-for-google/" target="_blank" rel="noopener">
順便賺個免費勞工幫我們訓練機器學習
&lt;/a>)，等確定你是真人再給你資料。&lt;/p>
&lt;p>後來想說為了穩定及時間因素，不要我們自己手動爬取、絞盡腦汁突破了，請求外援看看XD&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/aves_api/coffee.jpg" alt="Photo by Harry Brewer on Unsplash" data-caption="Photo by Harry Brewer on Unsplash" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
Photo by Harry Brewer on Unsplash
&lt;/figcaption>
&lt;/figure>
&lt;h2 id="尋找-google-搜尋-api">尋找 Google 搜尋 API&lt;/h2>
&lt;p>先去 Google 官網看看是否提供對應功能的 API，結果是有 &lt;a href="https://developers.google.com/custom-search/v1/overview" target="_blank" rel="noopener">
Custom Search JSON API
&lt;/a>，但每天只免費提供 100 次搜尋，額外請求的費用為每 1000 個搜尋 5 美元，每天最多 1 萬次搜尋。&lt;br />
這對我來說免費額度遠遠不夠，加購的價格又超貴 QAQ&lt;/p>
&lt;br/>
&lt;p>官方提供的不行，不然找找看網路上，有沒有別人提供免費或付費的 Google 搜尋 API 服務可以使用呢？因為感覺某些資訊公司也會有這種需求。&lt;/p>
&lt;p>後來找到「&lt;a href="https://avesapi.com" target="_blank" rel="noopener">
Aves API
&lt;/a>」，其他有提供類似的服務還有「&lt;a href="https://serpapi.com/" target="_blank" rel="noopener">
SerpApi
&lt;/a>」、「&lt;a href="https://rapidapi.com/apigeek/api/google-search3/endpoints" target="_blank" rel="noopener">
Rapid API
&lt;/a>」、「&lt;a href="https://zenserp.com/" target="_blank" rel="noopener">
zenserp
&lt;/a>」、「&lt;a href="https://scraperbox.com/google-search-scraper" target="_blank" rel="noopener">
ScraperBox
&lt;/a>」、「&lt;a href="https://dataforseo.com/apis/serp-api" target="_blank" rel="noopener">
DataForSEO
&lt;/a>」&amp;hellip;&amp;hellip;等可以參考，多方去比較，找到最符合自己需求的服務。&lt;/p>
&lt;p>最後我選擇 Aves API，會選擇這個最主要的因素 &amp;ndash; 便宜😅，這是我目前找到最便宜的，而且它計費的方式與其他有些不同，它是類似儲值的概念，你用多少就扣多少，沒有時間上的限制，而其他比較常見的是按月付款。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/aves_api/aves_web.jpg" alt="Aves API 官網" data-caption="Aves API 官網" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
Aves API 官網
&lt;/figcaption>
&lt;/figure>
&lt;h2 id="測試頁面">測試頁面&lt;/h2>
&lt;p>在 Aves API 官網首頁上有個可以實際輸入關鍵字，查看它回傳的資料是那些、長怎麼樣的 &lt;a href="https://avesapi.com/#try-serpapi" target="_blank" rel="noopener">
即時測試頁面(Live Demo)
&lt;/a>，能在此先測試是否有符合自己的需求。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/aves_api/live_demo.jpg" alt="即時測試頁面(Live Demo)" data-caption="即時測試頁面(Live Demo)" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
即時測試頁面(Live Demo)
&lt;/figcaption>
&lt;/figure>
&lt;h2 id="api-相關文檔">API 相關文檔&lt;/h2>
&lt;p>&lt;a href="https://docs.avesapi.com/" target="_blank" rel="noopener">
官方網站 API 文檔
&lt;/a>&lt;/p>
&lt;h3 id="錯誤狀態代碼">錯誤狀態代碼&lt;/h3>
&lt;p>如果請求收到錯誤狀態代碼，可以在&lt;a href="https://docs.avesapi.com/#common-api-error-codes" target="_blank" rel="noopener">
這邊
&lt;/a>查看是什麼原因，例如：API 金鑰無效、缺少查詢參數、帳戶額度不足。&lt;/p>
&lt;h3 id="api-參數">API 參數&lt;/h3>
&lt;p>註冊後會取得唯一的 API Key(金鑰)，送出請求時要代入。&lt;br />
API 網址如下：&lt;/p>
&lt;pre>&lt;code>https://api.avesapi.com/search?apikey=YOUR_API_KEY
&lt;/code>&lt;/pre>&lt;p>(使用 GET 方式送出請求，等同於你在瀏覽器直接輸入網址啦！)&lt;/p>
&lt;br/>
&lt;p>而此 API 目前可帶參數有以下這些：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>參數&lt;/th>
&lt;th>代表意思&lt;/th>
&lt;th>預設&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>&lt;code>apikey&lt;/code>&lt;/td>
&lt;td>[必要] 你的 API Key(金鑰)。&lt;/td>
&lt;td>[無]&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>query&lt;/code>&lt;/td>
&lt;td>[必要] 要搜尋的關鍵字。&lt;/td>
&lt;td>[無]&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>device&lt;/code>&lt;/td>
&lt;td>指定搜尋裝置平台：&lt;code>desktop&lt;/code> 或 &lt;code>mobile&lt;/code>。&lt;/td>
&lt;td>&lt;code>desktop&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>location&lt;/code>&lt;/td>
&lt;td>指定位置參數，有助於取得基於位置的搜索結果。提供的位置在 &lt;a href="https://avesapi.com/places.json" target="_blank" rel="noopener">
places.json
&lt;/a> 此檔案內所列出來的，需要的話就帶入&lt;code>place_slug&lt;/code>中的值。台灣可以使用&lt;code>&amp;quot;tw&amp;quot;&lt;/code>在檔案內搜尋，例如有&lt;code>taipei&lt;/code>、&lt;code>taichung&lt;/code>、&lt;code>tainan&lt;/code>、&lt;code>kaohsiung&lt;/code>等地點。&lt;/td>
&lt;td>[無]&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>google_domain&lt;/code>&lt;/td>
&lt;td>指定 Google 網域，支援的列表 &lt;a href="https://avesapi.com/google-domains.json" target="_blank" rel="noopener">
google-domains.json
&lt;/a>。台灣是 &lt;code>google.com.tw&lt;/code>。&lt;/td>
&lt;td>&lt;code>google.com&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>gl&lt;/code>&lt;/td>
&lt;td>指定查詢的國家代碼(預設美國)，支援的列表 &lt;a href="https://avesapi.com/countries.json" target="_blank" rel="noopener">
countries.json
&lt;/a>。台灣是 &lt;code>tw&lt;/code>。&lt;/td>
&lt;td>&lt;code>us&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>hl&lt;/code>&lt;/td>
&lt;td>指定查詢的語言(預設美語)，支援的列表 &lt;a href="https://avesapi.com/languages.json" target="_blank" rel="noopener">
languages.json
&lt;/a>。繁體中文是 &lt;code>Chinese (Traditional)&lt;/code>。&lt;/td>
&lt;td>&lt;code>en&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>num&lt;/code>&lt;/td>
&lt;td>指定每頁顯示的結果數，測試最多到&lt;code>100&lt;/code>。&lt;/td>
&lt;td>&lt;code>10&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>page&lt;/code>&lt;/td>
&lt;td>指定頁數(1~10頁)。&lt;/td>
&lt;td>&lt;code>1&lt;/code>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>uule&lt;/code>&lt;/td>
&lt;td>Returns the location based search results. (好像可以設定精確位置，但我不了解。)&lt;/td>
&lt;td>[無]&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;code>output&lt;/code>&lt;/td>
&lt;td>API 回應資料的格式：&lt;code>json&lt;/code> 或 &lt;code>html&lt;/code>。&lt;/td>
&lt;td>&lt;code>json&lt;/code>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>* 還有我發現在它 API Playground 頁面，還有一個的參數是&lt;code>type&lt;/code>，代表搜尋種類，有 &lt;code>web&lt;/code>(預設)、&lt;code>image&lt;/code>、&lt;code>news&lt;/code> 可選，但這個參數我還沒實際試過。&lt;/p>
&lt;h3 id="使用範例">使用範例&lt;/h3>
&lt;p>舉例來說，我想要在 google.com.tw 網域上搜尋&amp;quot;手機&amp;quot;，國家設定台灣、語言當然是繁體中文，想要看前 100 個搜尋結果，就如下代入參數請求：&lt;/p>
&lt;pre>&lt;code>https://api.avesapi.com/search?apikey={your-api-key}&amp;amp;query=手機&amp;amp;google_domain=google.com.tw&amp;amp;gl=tw&amp;amp;hl=zh-tw&amp;amp;num=100
&lt;/code>&lt;/pre>&lt;p>或者參數也可以以字典(Dictionary)的方式呈現。&lt;br />
在此使用 Python 程式來示範。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">your_api_key&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;XXXXXXXXXX&amp;#39;&lt;/span>
&lt;span class="n">keyword&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;手機&amp;#39;&lt;/span>
&lt;span class="n">api_url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://api.avesapi.com/search&amp;#39;&lt;/span>
&lt;span class="n">params&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;apikey&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">your_api_key&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;type&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;web&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;query&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">keyword&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;device&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;desktop&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;google_domain&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;google.com.tw&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;gl&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;tw&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;hl&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;zh-tw&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;output&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;json&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;num&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">100&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">api_url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">params&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">params&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timeout&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">35&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>回應資料如此：&lt;a href="https://blog.jiatool.com/code/avesapi_data.json" target="_blank" rel="noopener">
avesapi_data.json
&lt;/a>&lt;/p>
&lt;p>除了一般的搜尋結果與排名，如果搜尋結果內還有&amp;quot;圖片&amp;quot;、&amp;quot;影片&amp;quot;、&amp;quot;地圖&amp;quot;、&amp;quot;相關搜尋關鍵字&amp;quot;，它一樣也可以取得。&lt;/p>
&lt;p>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/aves_api/photo.jpg" alt="圖片 範例" data-caption="圖片 範例" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
圖片 範例
&lt;/figcaption>
&lt;/figure>&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/aves_api/video.jpg" alt="影片 範例" data-caption="影片 範例" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
影片 範例
&lt;/figcaption>
&lt;/figure>&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/aves_api/map.jpg" alt="地圖 範例" data-caption="地圖 範例" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
地圖 範例
&lt;/figcaption>
&lt;/figure>&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/aves_api/related_searches.jpg" alt="相關搜尋關鍵字 範例" data-caption="相關搜尋關鍵字 範例" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='400px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:400px;height:;"/>
&lt;figcaption style="text-align: center;">
相關搜尋關鍵字 範例
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;h2 id="網站後台">網站後台&lt;/h2>
&lt;p>當你註冊後登入，即可進入&lt;a href="https://app.avesapi.com/" target="_blank" rel="noopener">
後台頁面
&lt;/a>去查看更多相關資訊。&lt;/p>
&lt;p>其中有幾個重要的頁面：&lt;/p>
&lt;h3 id="儀錶板dashboard">儀錶板(Dashboard)&lt;/h3>
&lt;p>像是你還剩多少額度、最近請求的紀錄、每天使用量等等，以圖表來呈現。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/aves_api/dashboard.jpg" alt="Dashboard 頁面" data-caption="Dashboard 頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
Dashboard 頁面
&lt;/figcaption>
&lt;/figure>
&lt;h3 id="api-playground">API Playground&lt;/h3>
&lt;p>API Playground 以圖形化的操作頁面，讓你可以實際選擇參數、送出請求，並查看回傳的資料。如果你發現使用自己寫的程式，都沒有成功的話，也可以在此頁面測試，藉此排除是否是 API 的問題。&lt;br />
但要注意，這邊請求會帶上自己的 API Key，因此每一次請求也是會扣積分的哦！&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/aves_api/api_playground.jpg" alt="API Playground 頁面" data-caption="API Playground 頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
API Playground 頁面
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>剩下的是一些購買頁面、購買紀錄、個人資料等等，這邊我就不展示了。&lt;/p>
&lt;h2 id="注意事項">注意事項&lt;/h2>
&lt;ol>
&lt;li>有時因他們伺服器問題，會發生請求回應失敗，無法取得資料的情況，這時再重新送出請求一次即可，這個不會扣除積分。&lt;/li>
&lt;li>使用發現有時請求會發生 timeout 逾時，沒有成功取得資料，但卻還是被扣了一個積分額度。&lt;br />
與客服聯繫後得知，此 API 請求最大 timeout 為 30 秒，也就是說如果我requests.get(url, timeout=20) 設定 20 秒，但伺服器在 25 秒時才回覆資料，那我程式這邊雖然是 timeout，但他們是有送出資料(一樣算成功請求，會被扣積分)。所以建議 requests 中 timeout 要設定大於 30 秒。&lt;/li>
&lt;li>API 文檔有列出一些&lt;a href="https://docs.avesapi.com/#prohibited-keywords" target="_blank" rel="noopener">
禁止的關鍵字
&lt;/a>，例如：&lt;code>site:&lt;/code>、&lt;code>domain:&lt;/code>、&lt;code>title:&lt;/code>、&lt;code>before:&lt;/code>&amp;hellip;&amp;hellip;，可能因為這些進階查詢讓他們系統比較容易被檔吧(?)，如果使用這類關鍵字查詢的話，每個成功請求會被扣 25 個積分。&lt;/li>
&lt;/ol>
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>因為 Google 搜尋結果相關的 API 我也只使用過這一款，所以沒辦法跟你說是不是這個就是最好，但其實這類的服務大同小異，需要的話可以自行比較看看，官網文檔是否完整詳細、客服回應速度如何、是否提供台灣中文搜尋參數、計費方式、網路上別人的評價推薦。&lt;br />
最好也註冊一個帳號，用免費的額度嘗試，是否有達到自己的需求。&lt;/p>
&lt;p>* 要注意某些網站可能沒有提供免費額度&lt;/p>
&lt;br/>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://developers.google.com/custom-search" target="_blank" rel="noopener">
Google Custom Search JSON API 官網
&lt;/a>&lt;br />
&lt;a href="https://avesapi.com" target="_blank" rel="noopener">
Aves API 官網
&lt;/a>&lt;/p>
&lt;br/>
&lt;blockquote>
&lt;p>又一天過去了。今天覺得如何呢？&lt;br />
夢想是不是又更遠了？&lt;/p>
&lt;p align="right">—— &lt;a href="https://www.facebook.com/NeEnergy">每天來點負能量&lt;/a>&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/aves_api.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/aves_api_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Google搜尋</category><category>SEO</category><category>API</category><category>Python</category><category>分享</category></item><item><title>Requests 套件發生 requests.exceptions.SSLError: certificate verify failed 錯誤，無法請求網頁</title><link>https://blog.jiatool.com/posts/requests_ssl_error/</link><pubDate>Sun, 17 Jan 2021 20:30:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sun, 17 Jan 2021 20:30:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/requests_ssl_error/</guid><description>問題 在使用 Requests 套件送出請求抓取網頁時，有時候可能會遇到以下錯誤： requests.exceptions.SSLError: HTTPSConnectionPool(host='www.xxx.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:852)'),)) 原因是 HTTPS 的 SSL 憑證過期、不合格或有其他問題，</description><content:encoded>&lt;h2 id="問題">問題&lt;/h2>
&lt;p>在使用 Requests 套件送出請求抓取網頁時，有時候可能會遇到以下錯誤：&lt;/p>
&lt;pre>&lt;code>requests.exceptions.SSLError: HTTPSConnectionPool(host='www.xxx.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:852)'),))
&lt;/code>&lt;/pre>&lt;p>原因是 HTTPS 的 SSL 憑證過期、不合格或有其他問題，造成 Requests 在請求時證書驗證失敗，就會出現 requests.exceptions.SSLError 這樣的錯誤。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/requests_ssl_error/invalid_certificate.png" alt="憑證無效" data-caption="憑證無效" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
憑證無效
&lt;/figcaption>
&lt;/figure>
&lt;h2 id="解決辦法">解決辦法&lt;/h2>
&lt;p>&lt;a href="https://requests.readthedocs.io/en/master/user/advanced/#ssl-cert-verification" target="_blank" rel="noopener">
Requests 套件
&lt;/a>在默認的情況下，預設是啟用 SSL 驗證，其中一個解決的方式是透過加上 &lt;code>verify=False&lt;/code> 參數來關閉 Requests 的 SSL 憑證檢查功能。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;https://www.xxx.com&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">verify&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">False&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;br/>
&lt;hr />
&lt;p>關閉 Requests 套件的 SSL 憑證檢查功能，就能正常取得網頁資料，但會跳出以下警告：&lt;/p>
&lt;pre>&lt;code>InsecureRequestWarning: Unverified HTTPS request is being made to host 'www.xxx.com'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
&lt;/code>&lt;/pre>&lt;p>雖然不影響結果，但如果覺得很礙眼想隱藏此警告消息，&lt;br />
參考它給的網址(&lt;a href="https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings" target="_blank" rel="noopener">
https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
&lt;/a>)，裡頭寫到&amp;quot;如果您了解風險並希望禁用這些警告，則可以使用 &lt;code>disable_warnings()&lt;/code>&amp;quot;：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">urllib3&lt;/span>
&lt;span class="n">urllib3&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">disable_warnings&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>或者也可以只針對不安全的請求警告隱藏：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">urllib3&lt;/span>
&lt;span class="n">urllib3&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">disable_warnings&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">urllib3&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exceptions&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">InsecureRequestWarning&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://requests.readthedocs.io/en/master/user/advanced/#ssl-cert-verification" target="_blank" rel="noopener">
Requests 套件 SSL Cert Verification
&lt;/a>&lt;br />
&lt;a href="https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings" target="_blank" rel="noopener">
urllib3 套件 TLS Warnings
&lt;/a>&lt;br />
&lt;a href="https://stackoverflow.com/questions/27981545/suppress-insecurerequestwarning-unverified-https-request-is-being-made-in-pytho" target="_blank" rel="noopener">
stackoverflow
&lt;/a>&lt;/p>
&lt;br/>
&lt;blockquote>
&lt;p>真正能讓你倒下的，不是對手，而是你絕望的內心。&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/requests_ssl_error.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/requests_ssl_error_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>Python</category><category>Requests</category><category>SSL</category><category>網路爬蟲</category></item><item><title>Python try/except：一道看似簡單，卻隱藏著陷阱</title><link>https://blog.jiatool.com/posts/try_except_trap/</link><pubDate>Sat, 09 Jan 2021 20:10:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sat, 09 Jan 2021 20:10:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/try_except_trap/</guid><description>一個非常簡單的函式： 1 2 3 4 5 6 def func(): x = 1 return x print(func()) 我們都知道最後會輸出1 再來回答看看底下這段程式會輸出什麼呢？ 1 2 3 4 5 6 7 8 9 10 11 12 13 def func(): try:</description><content:encoded>&lt;p>一個非常簡單的函式：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">func&lt;/span>&lt;span class="p">():&lt;/span>
&lt;span class="n">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">x&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">func&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>我們都知道最後會輸出&lt;code>1&lt;/code>&lt;/p>
&lt;br>
&lt;hr />
&lt;p>再來回答看看底下這段程式會輸出什麼呢？&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">func&lt;/span>&lt;span class="p">():&lt;/span>
&lt;span class="k">try&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">x&lt;/span>
&lt;span class="k">except&lt;/span> &lt;span class="ne">Exception&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">2&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">x&lt;/span>
&lt;span class="k">finally&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">3&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">x&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">func&lt;/span>&lt;span class="p">())&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>(a) 1&lt;br />
(b) 2&lt;br />
(c) 3&lt;/p>
&lt;br>
&lt;br>
&lt;br>
&lt;br>
&lt;br>
&lt;br>
&lt;p>答案竟然是 (c) 3 ?!&lt;br />
如何？跟你想像的一樣嗎？&lt;/p>
&lt;p>照理來講，&lt;br />
在函式內執行 &lt;code>x = 1&lt;/code> 之後就遇到了 &lt;code>return x&lt;/code> 就該跳出迴圈了。&lt;/p>
&lt;p>But 🤨&lt;br />
這段程式是放在 &lt;code>try/except&lt;/code> 異常處理中，&lt;br />
而當中如果有 &lt;code>finally&lt;/code>，那 &lt;code>finally&lt;/code> 是無論例外有沒有發生都會執行的。&lt;/p>
&lt;p>上面那道題目，如果使用IDE的單步執行來偵錯的話，會發現 &lt;code>try&lt;/code> 內的 &lt;code>return x&lt;/code> 執行完後，會跳到 &lt;code>finally&lt;/code> 內執行 &lt;code>x = 3&lt;/code> 和 &lt;code>return x&lt;/code>，所以最後函式會返回&lt;code>3&lt;/code>。&lt;/p>
&lt;br/>
&lt;p>因此在撰寫程式時，避免把 &lt;code>return&lt;/code> 寫在 &lt;code>try/except&lt;/code> 異常處理中，以免發生這種較不直觀的流程。&lt;br />
畢竟發生異常也要把異常處理好再離開嘛~&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;blockquote>
&lt;p>我想打起精神來，卻不小心把它打死了&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/try_except_trap.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><category>Python</category><category>例外處理</category><category>其他</category></item><item><title>[Python爬蟲實例] NOWnews今日新聞-動態載入</title><link>https://blog.jiatool.com/posts/nownews_spider/</link><pubDate>Sun, 27 Dec 2020 20:30:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sun, 27 Dec 2020 20:30:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/nownews_spider/</guid><description>前言 Python網路爬蟲實例系列 已經進入第六篇了，我們要試著來抓取「NOWnews今日新聞」的即時新聞列表 ，而透過底下說明可以發現它有使用 Ajax</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>&lt;a href="https://blog.jiatool.com/series/Python%e7%b6%b2%e8%b7%af%e7%88%ac%e8%9f%b2%e5%af%a6%e4%be%8b/" target="_blank" rel="noopener">
Python網路爬蟲實例系列
&lt;/a>已經進入第六篇了，我們要試著來抓取「NOWnews今日新聞」的&lt;a href="https://www.nownews.com/cat/breaking/" target="_blank" rel="noopener">
即時新聞列表
&lt;/a>，而透過底下說明可以發現它有使用 Ajax 動態載入，我們也可以更容易地取得資料。文末有附上完整程式碼供參考。&lt;/p>
&lt;p>備註：此文僅教育學習，切勿用作商業用途，個人實作皆屬個人行為，本作者不負任何法律責任&lt;/p>
&lt;h2 id="套件">套件&lt;/h2>
&lt;p>此次 Python 爬蟲主要使用到的套件：&lt;/p>
&lt;ul>
&lt;li>Requests [&lt;a href="https://requests.readthedocs.io/en/master/" target="_blank" rel="noopener">
Doc
&lt;/a>] [&lt;a href="https://github.com/psf/requests" target="_blank" rel="noopener">
GitHub
&lt;/a>]&lt;/li>
&lt;/ul>
&lt;p>安裝&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">pip install requests
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="流程">流程&lt;/h2>
&lt;p>首先進入 NOWnews 今日新聞的&lt;a href="https://www.nownews.com/cat/breaking/" target="_blank" rel="noopener">
即時新聞列表
&lt;/a> 網頁，來觀察看看其新聞列表載入方式。&lt;/p>
&lt;p>打開瀏覽器的 &lt;strong>開發人員工具&lt;/strong> (F12 或 Ctrl + Shift + i)，可能一開始會先透過&amp;quot;Elements&amp;quot;找網頁節點元素，馬上就開始寫爬蟲程式了。&lt;br />
但是等等，這樣除了要解析網頁，他頁面上有三種版型，還要各自分開解析，或許我們可以再花點時間觀察觀察。&lt;/p>
&lt;p>&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/nownews_spider/nownews_page.jpg" alt="即時新聞列表網頁" data-caption="即時新聞列表網頁" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
即時新聞列表網頁
&lt;/figcaption>
&lt;/figure>&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/nownews_spider/three_template.jpg" alt="新聞列表三種版型" data-caption="新聞列表三種版型" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
新聞列表三種版型
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>開發人員工具切換到&amp;quot;Network&amp;quot; &amp;gt; &amp;quot;XHR&amp;quot;，當我們點擊「看更多新聞」按鈕時，會發現有送出一個請求，單點選它打開之後，右邊選擇 &lt;code>Preview&lt;/code> 分頁看一下其中的資料。&lt;br />
水啦~~~就是我們希望取得的新聞列表。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/nownews_spider/more_news_btn.jpg" alt="「看更多新聞」按鈕" data-caption="「看更多新聞」按鈕" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
「看更多新聞」按鈕
&lt;/figcaption>
&lt;/figure>&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/nownews_spider/more_news_ajax.jpg" alt="「看更多新聞」Ajax" data-caption="「看更多新聞」Ajax" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
「看更多新聞」Ajax
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>切換回 &lt;code>Headers&lt;/code> 分頁，看一下此資料請求方式與網址。&lt;br />
使用&amp;quot;GET&amp;quot;的方式，網址為 &lt;code>https://www.nownews.com/nn-client/api/v1/cat/breaking/&lt;/code>。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/nownews_spider/ajax_request.png" alt="Ajax請求方式" data-caption="Ajax請求方式" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
Ajax請求方式
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>ㄟ？！ 那網址後方的參數 &lt;code>pid=5148899&lt;/code> 代表什麼呢？&lt;br />
打開開發人員工具內的搜尋(Ctrl+F)，觀察一下發現，原來是代表前一次資料中的最後一篇新聞ID啊~&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/nownews_spider/pid.jpg" alt="pid 參數代表什麼？" data-caption="pid 參數代表什麼？" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
pid 參數代表什麼？
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>可以將網址貼到瀏覽器的網址欄位中，查看回傳的資料。&lt;/p>
&lt;p>OK&lt;br />
大致上原理與流程我們知道了，來開始將其轉換成 Python 程式碼吧！&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/nownews_spider/go.jpg" alt="來源：吉卜力工作室 www.ghibli.jp" data-caption="來源：吉卜力工作室 www.ghibli.jp" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
來源：吉卜力工作室 www.ghibli.jp
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;h2 id="爬蟲程式">爬蟲程式&lt;/h2>
&lt;p>先設定兩個變數，&lt;code>all_news&lt;/code> 之後要裝抓取的新聞資料；&lt;code>pid&lt;/code> 是記錄每頁最後一筆新聞的ID (為了請求下一頁)。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_news&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">num&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="n">all_news&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;span class="n">pid&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>這邊使用 &lt;code>while&lt;/code> 迴圈，&lt;code>num&lt;/code> 代表我們想爬取的新聞數量，當數量還不到時，就繼續抓取。&lt;br />
請求的網址 &lt;code>url&lt;/code> 後方記得帶上 &lt;code>pid&lt;/code> 參數。第一頁只要空著就行，之後開始才需要給值。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python"> &lt;span class="k">while&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">all_news&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">num&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;https://www.nownews.com/nn-client/api/v1/cat/breaking/?pid={pid}&amp;#39;&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">HEADERS&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;Requests Error: {r.status_code}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">break&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>我們先觀察之前取得的回傳資料：&lt;br />
* 為了方便觀察，我這邊使用 &lt;a href="http://jsoneditoronline.org/" target="_blank" rel="noopener">
JSON Editor Online
&lt;/a> 線上工具來輔助演示。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/nownews_spider/data.png" alt="回傳資料內容" data-caption="回傳資料內容" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
回傳資料內容
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>參數&lt;/th>
&lt;th>代表意思&lt;/th>
&lt;th>格式&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>id&lt;/td>
&lt;td>ID&lt;/td>
&lt;td>&lt;em>文字&lt;/em>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>postTitle&lt;/td>
&lt;td>標題&lt;/td>
&lt;td>&lt;em>文字&lt;/em>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>postUrl&lt;/td>
&lt;td>網址(包含請求分類)&lt;/td>
&lt;td>&lt;em>文字&lt;/em>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>postOnlyUrl&lt;/td>
&lt;td>網址(不包含請求分類)&lt;/td>
&lt;td>&lt;em>文字&lt;/em>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>sort&lt;/td>
&lt;td>排序&lt;/td>
&lt;td>&lt;em>數字&lt;/em>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>postContent&lt;/td>
&lt;td>內容摘要&lt;/td>
&lt;td>&lt;em>文字&lt;/em>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>imageUrl&lt;/td>
&lt;td>圖片網址&lt;/td>
&lt;td>&lt;em>數字&lt;/em>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>newsDate&lt;/td>
&lt;td>發布日期&lt;/td>
&lt;td>&lt;em>數字&lt;/em>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>回傳資料是 JSON 格式，直接使用 requests 提供的 &lt;code>r.json()&lt;/code> 轉換。&lt;br />
新聞列表資料是放在 &lt;code>data&lt;/code> &amp;gt; &lt;code>newsList&lt;/code> 中，並取得我們想要的欄位。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python"> &lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">news_list&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;data&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;newsList&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">news&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">news_list&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">news_data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;id&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">news&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;id&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="s1">&amp;#39;url&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;https://www.nownews.com&amp;#39;&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">news&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;postOnlyUrl&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="s1">&amp;#39;title&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">news&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;postTitle&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="s1">&amp;#39;content&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">news&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;postContent&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="s1">&amp;#39;date&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">news&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;newsDate&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">all_news&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">news_data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>下一頁網址後方參數 &lt;code>pid&lt;/code>，就是這次的最後一筆新聞ID。&lt;br />
每次請求之間加入一小段延遲，避免太頻繁爬取，造成對方伺服器負擔。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python"> &lt;span class="n">pid&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">all_news&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;id&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">uniform&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="完整程式碼">完整程式碼&lt;/h2>
&lt;p>附上完整程式碼：&lt;a href="https://blog.jiatool.com/code/nownews_spider.py" target="_blank" rel="noopener">
nownews_spider.py
&lt;/a>&lt;br />
(對超連結右鍵 &amp;gt; 另存連結為)&lt;/p>
&lt;h2 id="延伸練習">延伸練習&lt;/h2>
&lt;ol>
&lt;li>試著抓取不同分類裡的新聞列表，例如：&lt;a href="https://game.nownews.com/" target="_blank" rel="noopener">
NOW電玩裡的最新新聞
&lt;/a>。&lt;br />
提示：雖然它看似採用&amp;quot;下一頁&amp;quot;的方式，但你實際點擊不同頁數時，發現到網址並無任何變化，或許它也是使用 Ajax 動態載入資料的方式呢~&lt;/li>
&lt;/ol>
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>整體來說，NOWnews今日新聞的爬取方法與聯合新聞網蠻類似的，可以前往我之前寫的&lt;a href="https://blog.jiatool.com/posts/udn_spider/" target="_blank" rel="noopener">
教學文
&lt;/a>參考。&lt;/p>
&lt;p>我會陸續慢慢寫一些網站的&lt;a href="https://blog.jiatool.com/series/Python%e7%b6%b2%e8%b7%af%e7%88%ac%e8%9f%b2%e5%af%a6%e4%be%8b/" target="_blank" rel="noopener">
Python網路爬蟲實例
&lt;/a>，如果你正好是剛開始想學爬蟲的新手、想知道某個網站如何爬取資料，又或遇到其他問題，歡迎參考與在底下留言喔~🔖&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;blockquote>
&lt;p>人生沒有最好的決定，只有在決定之後做到最好。&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/nownews_spider.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><category>Python</category><category>網路爬蟲</category><category>Python網路爬蟲實例</category></item><item><title>[Python爬蟲實例] YouTube-使用 youtube_dl 套件</title><link>https://blog.jiatool.com/posts/youtube_spider_dl/</link><pubDate>Sun, 13 Dec 2020 20:20:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sun, 13 Dec 2020 20:20:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/youtube_spider_dl/</guid><description>前言 在之前 [Python爬蟲實例] YouTube-使用 YouTube Data API 教學是使用 YouTube Data API 來取得影片相關資訊，不過如果你只是想抓取影片基本訊息，但不想麻煩</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>在之前 &lt;a href="https://blog.jiatool.com/posts/youtube_spider_api/" target="_blank" rel="noopener">
[Python爬蟲實例] YouTube-使用 YouTube Data API
&lt;/a> 教學是使用 YouTube Data API 來取得影片相關資訊，不過如果你只是想抓取影片基本訊息，但不想麻煩去申請 API Key，或許可以改使用一個非常有名的套件 — youtube_dl。&lt;/p>
&lt;p>備註：此文僅教育學習，切勿用作商業用途，個人實作皆屬個人行為，本作者不負任何法律責任&lt;/p>
&lt;h2 id="套件">套件&lt;/h2>
&lt;p>本次主要使用到的套件：&lt;/p>
&lt;ul>
&lt;li>youtube-dl [&lt;a href="http://ytdl-org.github.io/youtube-dl/" target="_blank" rel="noopener">
官網
&lt;/a>] [&lt;a href="https://github.com/ytdl-org/youtube-dl" target="_blank" rel="noopener">
GitHub
&lt;/a>]&lt;/li>
&lt;/ul>
&lt;h2 id="-爬蟲程式">📘 爬蟲程式&lt;/h2>
&lt;p>youtube_dl 主要提供從 YouTube 及其他多個網站下載影片，使用方法非常簡單：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">with&lt;/span> &lt;span class="n">youtube_dl&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">YoutubeDL&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">ydl&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ydl&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extract_info&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;影片網址&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">download&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">False&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>因為我們只是想取得影片資訊，並沒有要下載影片，因此 download 帶入 False。&lt;/p>
&lt;p>函式回傳的資料即是 dict (字典) 資料型別，我們可以只挑選需要的內容。&lt;br />
程式碼如下：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="kn">from&lt;/span> &lt;span class="nn">pprint&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">pprint&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">youtube_dl&lt;/span>
&lt;span class="k">def&lt;/span> &lt;span class="nf">get_video_info&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">youtube_url&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="n">video_info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;span class="k">with&lt;/span> &lt;span class="n">youtube_dl&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">YoutubeDL&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">ydl&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ydl&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extract_info&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">youtube_url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">download&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">False&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># pprint(info)&lt;/span>
&lt;span class="n">video_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;ID&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;id&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">video_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;標題&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;title&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">video_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;影片縮圖&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;thumbnail&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">video_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;上傳者&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;uploader&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">video_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;上傳者網址&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;uploader_url&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">video_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;影片長度(秒)&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;duration&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">video_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;觀看次數&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;view_count&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">video_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;留言數&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;comment_count&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># -&lt;/span>
&lt;span class="n">video_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;喜歡數&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;like_count&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">video_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;不喜歡數&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;dislike_count&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">video_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;平均評分&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;average_rating&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">video_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;描述&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;description&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">video_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;標籤&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;tags&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">video_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;網頁網址&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;webpage_url&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">video_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;上傳日期&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">info&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;upload_date&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">video_info&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;__main__&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">video_info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_video_info&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;https://www.youtube.com/watch?v=YculJhe_iPk&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">pprint&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">video_info&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>回傳影片相關資訊結果：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;ID&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;YculJhe_iPk&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;上傳日期&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;20201206&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;上傳者&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;Onion Man&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;上傳者網址&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;http://www.youtube.com/channel/UCzxN4G3s9uR9ao5_O5DoXmA&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;不喜歡數&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">230&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;喜歡數&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">13735&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;平均評分&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">4.9341211&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;影片縮圖&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;https://i.ytimg.com/vi_webp/YculJhe_iPk/maxresdefault.webp?v=5fccb8d3&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;影片長度(秒)&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">299&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;描述&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;你的請客值有多少?&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;span class="s1">&amp;#39;【訂閱】及觀看洋蔥更多影片: https://goo.gl/ijP3Eb&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;span class="s1">&amp;#39;工作合作：service@weido.biz&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;span class="s1">&amp;#39;Onion Man 百萬追蹤粉絲團:goo.gl/Z5CSvw&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;span class="s1">&amp;#39;最新阿文貼圖:https://reurl.cc/GxYjA&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;span class="s1">&amp;#39;第一代阿文line貼圖:https://reurl.cc/Wroxx&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;span class="s1">&amp;#39;洋蔥私生活IG:https://www.instagram.com/onionman__/&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;span class="s1">&amp;#39;運動漫畫裡的中二老梗劇情&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;span class="s1">&amp;#39;►第一集:https://youtu.be/cMoV1rPH35k&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;span class="s1">&amp;#39;►第二集:https://youtu.be/iW7LM00lny0&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;span class="s1">&amp;#39;►第三集:https://youtu.be/2G5wu61uCM0&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;span class="s1">&amp;#39;►第四集:https://youtu.be/-rP1abYv8n4&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;span class="s1">&amp;#39;Onion Man 關鍵字:&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>
&lt;span class="s1">&amp;#39;中二 肥宅 單身漢 單身 魯蛇 屌絲 肥宅&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;標籤&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;onion&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;man&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;阿文&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;黑鳳梨&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;插畫&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;爆笑&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;搞笑&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;玩笑&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="o">...&lt;/span>&lt;span class="s1">&amp;#39;綜藝大熱門&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;de&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;jun&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;上班不要看&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="s1">&amp;#39;標題&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;Onion Man | 我不想出錢 但要裝闊&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;留言數&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="bp">None&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;網頁網址&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;https://www.youtube.com/watch?v=YculJhe_iPk&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;觀看次數&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">555986&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>* 我發現它 YouTube 好像無法取得留言數。🤔&lt;/p>
&lt;p>但它是需要透過影片網址來取得影片相關資訊，如果我們想要像&lt;a href="https://blog.jiatool.com/posts/youtube_spider_api/" target="_blank" rel="noopener">
上次
&lt;/a>一樣，針對某個頻道抓取最近的五部影片，可能就要先透過網路爬蟲取得網頁的方式來獲取影片網址，才可以使用了 youtube_dl 套件。&lt;/p>
&lt;h2 id="完整程式碼">完整程式碼&lt;/h2>
&lt;p>附上完整程式碼：&lt;a href="https://blog.jiatool.com/code/youtube_spider_dl.py" target="_blank" rel="noopener">
youtube_dl.py
&lt;/a>&lt;br />
(對超連結右鍵 &amp;gt; 另存連結為)&lt;/p>
&lt;h2 id="延伸練習">延伸練習&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>在上方教學中，我們是透過影片網址取得影片資訊。&lt;br />
那你可以寫支程式自動抓取&lt;a href="https://www.youtube.com/feed/trending" target="_blank" rel="noopener">
發燒影片
&lt;/a>的前10名影片資訊嗎？&lt;/p>
&lt;/li>
&lt;li>
&lt;p>youtube_dl 套件最主要是用來從 YouTube 及其他多個網站下載影片，你何不來嘗試看看呢？&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>如果你只是想取得影片的基本資訊，使用 youtube_dl 套件會比較容易哦~&lt;/p>
&lt;p>我有陸續寫一些網站的&lt;a href="https://blog.jiatool.com/series/Python%e7%b6%b2%e8%b7%af%e7%88%ac%e8%9f%b2%e5%af%a6%e4%be%8b/" target="_blank" rel="noopener">
Python網路爬蟲實例
&lt;/a>，如果你正好是剛開始想學爬蟲的新手、想知道某個網站如何爬取資料，或者遇到其他問題，歡迎過來參考和在底下留言~👇&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://github.com/ytdl-org/youtube-dl" target="_blank" rel="noopener">
youtube-dl GitHub
&lt;/a>&lt;/p>
&lt;br/>
&lt;blockquote>
&lt;p>有夢就去追啊，愣在原地做什麽。&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/youtube_spider_dl.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><category>Python</category><category>YouTube</category><category>網路爬蟲</category><category>Python網路爬蟲實例</category></item><item><title>Python 使用 Faker 套件來生成假資料</title><link>https://blog.jiatool.com/posts/faker/</link><pubDate>Mon, 09 Nov 2020 21:00:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Mon, 09 Nov 2020 21:00:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/faker/</guid><description>前言 有時候可能因為某些原因需要生成一些假資料，例如做網頁時，先填入一些假資料方便排版。 在 Python 中就有一個 Faker 套件來產生假資料，包括人名、電話、地址</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>有時候可能因為某些原因需要生成一些假資料，例如做網頁時，先填入一些假資料方便排版。&lt;/p>
&lt;p>在 Python 中就有一個 Faker 套件來產生假資料，包括人名、電話、地址、工作、公司、信用卡、IP&amp;hellip;&amp;hellip;非常多樣。&lt;/p>
&lt;h2 id="安裝">安裝&lt;/h2>
&lt;p>安裝也很簡單，可以透過 pip 安裝：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">pip install faker
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>這邊要注意的是從版本 v4.0.0 開始，Faker 只支援 Python 3.5 及更新版本，並不支援 Python 2。&lt;/p>
&lt;p>以下以撰寫文章時最新的版本 v4.14.2 為範例。&lt;br />
&lt;a href="https://github.com/joke2k/faker" target="_blank" rel="noopener">
Faker 官方GitHub
&lt;/a>&lt;br />
&lt;a href="https://faker.readthedocs.io/en/master/" target="_blank" rel="noopener">
Faker 官方文件
&lt;/a>&lt;/p>
&lt;h2 id="簡易範例">簡易範例&lt;/h2>
&lt;p>使用 faker.Faker() 來創建並初始化產生器，調用方法來產生資料，例如以下名字、地址。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="kn">from&lt;/span> &lt;span class="nn">faker&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Faker&lt;/span>
&lt;span class="n">fake&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Faker&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="c1"># Carla Parker&lt;/span>
&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">address&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="c1"># 1882 Erika Glens\nRoblesbury, MO 28877&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="語言包">語言包&lt;/h2>
&lt;p>看到這裡，可能有人覺得都是生成英文數據，我想要繁體中文那怎麼辦🤔&lt;br />
別擔心，Faker 有內建語言包的機制，在一開始創建 Faker 時帶入語言參數即可。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">fake&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Faker&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;zh_TW&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">_&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">address&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;--------&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 許哲瑋&lt;/span>
&lt;span class="c1"># 45851 臺東市復興路11號之9&lt;/span>
&lt;span class="c1"># --------&lt;/span>
&lt;span class="c1"># 林雅慧&lt;/span>
&lt;span class="c1"># 67491 台北縣學府巷468號之1&lt;/span>
&lt;span class="c1"># --------&lt;/span>
&lt;span class="c1"># 陳宇軒&lt;/span>
&lt;span class="c1"># 20610 新竹民治巷862號之2&lt;/span>
&lt;span class="c1"># --------&lt;/span>
&lt;span class="c1"># 殷沖&lt;/span>
&lt;span class="c1"># 80604 橫山中興路5段595號5樓&lt;/span>
&lt;span class="c1"># --------&lt;/span>
&lt;span class="c1"># 李信宏&lt;/span>
&lt;span class="c1"># 51142 台北大同路172號之2&lt;/span>
&lt;span class="c1"># --------&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>你如果想要多個語言混合，當然也行🤣&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">fake&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Faker&lt;/span>&lt;span class="p">([&lt;/span>&lt;span class="s1">&amp;#39;zh_TW&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;ja_JP&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;ko_KR&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">_&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">6&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 佐々木 明美&lt;/span>
&lt;span class="c1"># 高橋 直子&lt;/span>
&lt;span class="c1"># 宋惠如&lt;/span>
&lt;span class="c1"># 이영일&lt;/span>
&lt;span class="c1"># 佐々木 桃子&lt;/span>
&lt;span class="c1"># 김미영&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>一些常見的語言代碼如下：&lt;/p>
&lt;ul>
&lt;li>繁體中文：zh_TW&lt;/li>
&lt;li>簡體中文：zh_CN&lt;/li>
&lt;li>美國英文：en_US&lt;/li>
&lt;li>英國英文：en_GB&lt;/li>
&lt;li>日文：ja_JP&lt;/li>
&lt;li>韓文：ko_KR&lt;/li>
&lt;li>完整的語言包列表，請參考官方文件：&lt;a href="https://faker.readthedocs.io/en/master/locales.html" target="_blank" rel="noopener">
https://faker.readthedocs.io/en/master/locales.html
&lt;/a>&lt;/li>
&lt;/ul>
&lt;p>* 題外話：我發現它的繁體中文有些地方不是很好，感覺是從簡體直接轉過來的。&lt;/p>
&lt;h2 id="方法介紹">方法介紹&lt;/h2>
&lt;h4 id="人名">人名&lt;/h4>
&lt;p>與人名相關數據，例如：姓氏、名字、羅馬拼音等等。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 袁家銘&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">name_female&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="c1"># 女生人名&lt;/span>
&lt;span class="c1"># 莫怡萱&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">name_male&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="c1"># 男生人名&lt;/span>
&lt;span class="c1"># 孫威廷&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">romanized_name&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="c1"># 羅馬拼音&lt;/span>
&lt;span class="c1"># Ping Long&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">last_name&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 楊&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">last_name_female&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 李&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">last_name_male&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 黃&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">last_romanized_name&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># Lin&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">first_name&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 家豪&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">first_name_female&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 惠雯&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">first_name_male&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 冠霖&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">first_romanized_name&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># Jing&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="個人資料">個人資料&lt;/h4>
&lt;p>像是：語言、手機號碼、身分證、工作職稱。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">language_name&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># Turkmen&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">country_calling_code&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># +290 8&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">phone_number&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 0977-739186&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ssn&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># D169226625&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">job&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 工業設計&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">simple_profile&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># {&amp;#39;username&amp;#39;: &amp;#39;sfang&amp;#39;, &amp;#39;name&amp;#39;: &amp;#39;李雅文&amp;#39;, &amp;#39;sex&amp;#39;: &amp;#39;M&amp;#39;, &amp;#39;address&amp;#39;: &amp;#39;42346 板橋縣民有路310號之3&amp;#39;, &amp;#39;mail&amp;#39;: &amp;#39;xiuyingxue@gmail.com&amp;#39;, &amp;#39;birthdate&amp;#39;: datetime.date(1936, 2, 13)}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="地址">地址&lt;/h4>
&lt;p>與地址相關數據，例如：完整地址、城市、鄉鎮、路名&amp;hellip;&amp;hellip;。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">address&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 30751 基隆市仁愛街93號6樓&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">building_number&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 4號&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">city&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 卑南縣&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">city_name&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 草屯&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">city_name_suffix&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 縣&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">country&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 俄羅斯&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">country_code&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># LT&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">postcode&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 824&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">secondary_address&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 之2&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">street_address&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 自由街759號&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">street_name&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 信義&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">street_name_suffix&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 路&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="公司">公司&lt;/h4>
&lt;p>與公司相關數據，例如：公司名稱、公司前綴、公司後綴等等。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">bs&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># synergize enterprise relationships&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">catch_phrase&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># Object-based zero administration secured line&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">company&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 台北眾大捷運股份有限公司&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">company_prefix&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 品誠&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">company_suffix&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 有限公司&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="句子">句子&lt;/h4>
&lt;p>與句子、單詞相關數據。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sentence&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 發生服務選擇人民游戲然后一下法律.&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sentences&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># [&amp;#39;發現密碼地區那個精華制作.&amp;#39;, &amp;#39;擁有地方手機所有.&amp;#39;, &amp;#39;業務決定地址經濟投資方式.&amp;#39;]&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">max_nb_chars&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">15&lt;/span>&lt;span class="p">))&lt;/span>
&lt;span class="c1"># 基本主要研究根據一種當然各種.&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">word&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 關於&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">words&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># [&amp;#39;一種&amp;#39;, &amp;#39;電影&amp;#39;, &amp;#39;大學&amp;#39;]&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="日期時間">日期時間&lt;/h4>
&lt;p>日期時間相關數據，譬如：日期、時間、星期&amp;hellip;&amp;hellip;。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">am_pm&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># AM&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">iso8601&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 1988-07-01T02:40:03&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">date&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 1970-12-22&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">date_object&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># datetime.date(2004, 3, 20)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">date_this_month&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">before_today&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">True&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">after_today&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="bp">False&lt;/span>&lt;span class="p">))&lt;/span>
&lt;span class="c1"># 2020-11-07&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">day_of_month&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 01&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">day_of_week&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># Saturday&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">month_name&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># April&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 02:46:38&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">time_object&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># datetime.time(8, 43, 22)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">unix_time&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 1429693221&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="檔案">檔案&lt;/h4>
&lt;p>包括檔案名稱、附檔名、路徑等等。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">fake&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Faker&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">file_extension&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">category&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;image&amp;#39;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;span class="c1"># jpeg&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">file_name&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># central.png&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">file_path&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># /recently/pass.js&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">unix_device&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># /dev/sdg&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="網路">網路&lt;/h4>
&lt;p>與網路相關數據，例如：Email、HTTP方法、IP、網址、網域&amp;hellip;&amp;hellip;。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">company_email&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># dmeng@zou.com&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">domain_name&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># tang.com&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">domain_word&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># gao&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">email&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># slei@gmail.com&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">free_email&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># mliu@hotmail.com&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">free_email_domain&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># yahoo.com&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">hostname&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># desktop-15.wan.com&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">http_method&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># POST&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">image_url&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># https://placeimg.com/431/555/any&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ipv4&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 28.144.124.103&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ipv4_network_class&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># c&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ipv4_private&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 192.168.96.99&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ipv4_public&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 75.81.186.65&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">mac_address&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># d2:3c:7b:3b:93:4f&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">uri&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># http://fu.com/wp-content/categories/main/index/&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">uri_extension&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># .php&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">uri_page&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># search&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># http://qiao.com/&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">user_name&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># mingyan&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="顏色">顏色&lt;/h4>
&lt;p>生成顏色色碼，像是：HEX、RGB、HSV、HSL等等。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">color&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># #6626ef&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">color&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">hue&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;red&amp;#39;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;span class="c1"># #ed6595&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">color&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">hue&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">100&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">200&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">color_format&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;rgb&amp;#39;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;span class="c1"># rgb(36, 181, 79)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">color&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">hue&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">135&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">luminosity&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;dark&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">color_format&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;hsv&amp;#39;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;span class="c1"># hsv(135, 95, 65)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">color_name&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># DarkMagenta&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">hex_color&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># #dd5cbb&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">rgb_color&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 35,232,144&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="信用卡">信用卡&lt;/h4>
&lt;p>信用卡相關資訊。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">credit_card_full&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="c1"># 信用卡詳細信息&lt;/span>
&lt;span class="c1"># JCB 16 digit&lt;/span>
&lt;span class="c1"># 鈺婷 柳&lt;/span>
&lt;span class="c1"># 3580134175667608 07/21&lt;/span>
&lt;span class="c1"># CVC: 070&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">credit_card_number&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="c1"># 卡號&lt;/span>
&lt;span class="c1"># 377183544094989&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">credit_card_expire&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="c1"># 有效日期&lt;/span>
&lt;span class="c1"># 02/27&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">credit_card_provider&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="c1"># 提供商名稱&lt;/span>
&lt;span class="c1"># VISA 19 digit&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">credit_card_security_code&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="c1"># 安全碼&lt;/span>
&lt;span class="c1"># 320&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="python-相關">Python 相關&lt;/h4>
&lt;p>與 Python 相關資料格式，可能對於測試很好用(?)，例如：Email、HTTP方法、IP、網址、網域&amp;hellip;&amp;hellip;。&lt;br />
(竟然還有這種東西😮)&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pybool&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># False&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pydecimal&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># -7867266828.6&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pydict&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># {&amp;#39;都是&amp;#39;: &amp;#39;MyXkRCJjYanEWNNuYrLM&amp;#39;, &amp;#39;一次&amp;#39;: &amp;#39;qiang69@gmail.com&amp;#39;, &amp;#39;政府&amp;#39;: Decimal(&amp;#39;2879320.4&amp;#39;), &amp;#39;工作&amp;#39;: &amp;#39;fDURUWoCzsGhHdvjJHXM&amp;#39;, &amp;#39;信息&amp;#39;: 1080, &amp;#39;功能&amp;#39;: &amp;#39;hNvGqVhrMVwOYiYpYghC&amp;#39;, &amp;#39;要求&amp;#39;: Decimal(&amp;#39;41.93441406219&amp;#39;), &amp;#39;一切&amp;#39;: &amp;#39;https://mao.tw/homepage/&amp;#39;, &amp;#39;開始&amp;#39;: 446798.631125}&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pylist&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># [&amp;#39;IartORkSBcHGqJCpfbMq&amp;#39;, &amp;#39;https://www.cui.com/terms.htm&amp;#39;, datetime.datetime(1995, 12, 12, 4, 32, 50), &amp;#39;vsJNgfvnxjDttefVvoIu&amp;#39;, &amp;#39;JxzLdZhLDYvgZHiHWjdO&amp;#39;, 6960, &amp;#39;mojun@hotmail.com&amp;#39;, &amp;#39;liangchao@yahoo.com&amp;#39;, datetime.datetime(2013, 5, 9, 12, 38, 18), &amp;#39;phao@hotmail.com&amp;#39;, &amp;#39;https://mo.com/privacy/&amp;#39;, 6105]&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="其他更多">其他更多&lt;/h4>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random_digit&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 8&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random_digit_not_null&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># 3&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random_int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">min&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">max&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">15&lt;/span>&lt;span class="p">))&lt;/span>
&lt;span class="c1"># 12&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">random_element&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">elements&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;a&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;b&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;c&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;d&amp;#39;&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;span class="c1"># d&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">numerify&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;Intel Core i&lt;/span>&lt;span class="si">%-%&lt;/span>&lt;span class="s1">%##K vs AMD Ryzen &lt;/span>&lt;span class="si">% %%##X&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;span class="c1"># Intel Core i8-9363K vs AMD Ryzen 4 6134X&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">language_code&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="c1"># i18n 語言碼&lt;/span>
&lt;span class="c1"># uk&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">license_plate&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="c1"># 車牌&lt;/span>
&lt;span class="c1"># 048-DQU&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">isbn10&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="c1"># ISBN碼&lt;/span>
&lt;span class="c1"># 1-57202-578-6&lt;/span>
&lt;span class="c1"># user agent&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">android_platform_token&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># Android 4.1.1&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ios_platform_token&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># iPhone; CPU iPhone OS 10_3_3 like Mac OS X&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">chrome&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.0 (KHTML, like Gecko) Chrome/38.0.819.0 Safari/535.0&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">fake&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">user_agent&lt;/span>&lt;span class="p">())&lt;/span>
&lt;span class="c1"># Mozilla/5.0 (Windows 98; ug-CN; rv:1.9.1.20) Gecko/2016-01-13 09:28:45 Firefox/13.0&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>真的是太多了，這邊不一一列出，&lt;br />
更詳細參數介紹及其他方法請參閱 Faker 官方文件：&lt;a href="https://faker.readthedocs.io/en/master/providers.html" target="_blank" rel="noopener">
Standard Providers
&lt;/a>&lt;/p>
&lt;p>還有其他人提供並經過官方認可的，例如&amp;quot;汽車&amp;quot;、&amp;quot;Wi-Fi ESSID&amp;quot;、&amp;quot;Web相關&amp;quot;之類的類別：&lt;a href="https://faker.readthedocs.io/en/master/communityproviders.html" target="_blank" rel="noopener">
Community Providers
&lt;/a>&lt;/p>
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>有沒有覺得 Faker 套件所包含的假資料包羅萬象啊🤣，趕快將此網頁加入&amp;quot;我的最愛(書籤)&amp;quot;，搞不好以後就有機會使用到呢~&lt;/p>
&lt;br/>
&lt;br/>
&lt;p>如有遇到其他問題，或文章內容有誤，歡迎底下留言~😙&lt;/p>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://github.com/joke2k/faker" target="_blank" rel="noopener">
Faker 官方GitHub
&lt;/a>&lt;br />
&lt;a href="https://faker.readthedocs.io/en/master/" target="_blank" rel="noopener">
Faker 官方文件
&lt;/a>&lt;/p>
&lt;br/>
&lt;blockquote>
&lt;p>You've got to find what you love.&lt;br />
你必須找到你所愛的。&lt;/p>
&lt;p align="right">—— 賈伯斯(Steve Jobs)&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/faker.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><category>Python</category><category>套件</category><category>分享</category><category>Python套件</category></item><item><title>[Python爬蟲實例] YouTube-使用 YouTube Data API</title><link>https://blog.jiatool.com/posts/youtube_spider_api/</link><pubDate>Sun, 01 Nov 2020 20:40:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Thu, 03 Nov 2022 21:45:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/youtube_spider_api/</guid><description>前言 來到Python網路爬蟲實例系列 第四篇，本篇使用 Python 透過官方 YouTube Data API v3 來爬取 YouTube ，包含頻道資訊、影片清單、影片資訊等等資料。 從在 Google 雲端平台(G</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>來到&lt;a href="https://blog.jiatool.com/series/Python%e7%b6%b2%e8%b7%af%e7%88%ac%e8%9f%b2%e5%af%a6%e4%be%8b/" target="_blank" rel="noopener">
Python網路爬蟲實例系列
&lt;/a>第四篇，本篇使用 Python 透過官方 YouTube Data API v3 來爬取 &lt;a href="https://www.youtube.com" target="_blank" rel="noopener">
YouTube
&lt;/a>，包含頻道資訊、影片清單、影片資訊等等資料。&lt;/p>
&lt;p>從在 Google 雲端平台(Google Cloud Platform)創建一個專案開始，包括獲取 API 授權憑證、取得 API key，到撰寫抓取程式皆會一步步講解如何操作。最後同樣會附上完整程式碼供參考。&lt;/p>
&lt;p>而如果你是想下載 YouTube 影片的話，本篇內容並不會提及，這部分可參考其他套件，例如 &lt;a href="https://github.com/nficano/pytube" target="_blank" rel="noopener">
pytube
&lt;/a>。&lt;br />
之前還有另外一個套件 Youtube-dl，但在寫這篇文章時發現美國唱片業協會（RIAA）點名 Youtube-dl 程式碼違反著作權法，並要求GitHub將它們移除(&lt;a href="https://www.ithome.com.tw/news/140720" target="_blank" rel="noopener">
來源
&lt;/a>)。&lt;/p>
&lt;p>備註：此文僅教育學習，切勿用作商業用途，個人實作皆屬個人行為，本作者不負任何法律責任&lt;/p>
&lt;h2 id="套件">套件&lt;/h2>
&lt;p>本次主要使用到的套件：&lt;/p>
&lt;ul>
&lt;li>Requests [&lt;a href="https://requests.readthedocs.io/en/master/" target="_blank" rel="noopener">
Doc
&lt;/a>] [&lt;a href="https://github.com/psf/requests" target="_blank" rel="noopener">
GitHub
&lt;/a>]&lt;/li>
&lt;/ul>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="流程">流程&lt;/h2>
&lt;p>要使用官方 YouTube Data API 抓取資料前，要先取得 API Key。&lt;/p>
&lt;p>先到 Google 雲端平台(Google Cloud Platform)創建一個專案，並將 YouTube Data API 加入置專案內，獲取 API 授權憑證、取得 API key。&lt;/p>
&lt;p>爬取資料這邊以 &lt;a href="https://www.youtube.com/c/%E5%85%AD%E6%8C%87%E6%B7%B5Huber" target="_blank" rel="noopener">
&lt;strong>六指淵 Huber&lt;/strong>
&lt;/a> 頻道當範例，到上傳的影片列表抓取最新的前五則影片，再到影片內取得影片相關資訊及留言。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/youtube_spider_api/huber.jpg" alt="六指淵 Huber 頻道" data-caption="六指淵 Huber 頻道" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
六指淵 Huber 頻道
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;h2 id="-取得-youtube-data-api-key">🔑 取得 YouTube Data API Key&lt;/h2>
&lt;p>先到&lt;a href="https://console.developers.google.com/" target="_blank" rel="noopener">
Google 雲端平台(Google Cloud Platform)
&lt;/a>創建一個專案，如果是第一次進來會跳出服務條款，點選同意後繼續。&lt;br />
點擊右上角顯示&amp;quot;建立專案&amp;quot;，或到上方的&amp;quot;選取專案&amp;quot;處建立。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/youtube_spider_api/google_cloud_platform.jpg" alt="服務條款" data-caption="服務條款" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
服務條款
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>右上角&amp;quot;新增專案&amp;quot;。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/youtube_spider_api/create_project_1.jpg" alt="創建專案" data-caption="創建專案" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
創建專案
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>輸入&amp;quot;專案名稱&amp;quot;，點選&amp;quot;建立&amp;quot;。&lt;br />
(專案ID也可以修改)&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/youtube_spider_api/create_project_2.png" alt="創建專案" data-caption="創建專案" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
創建專案
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>等它跑完後會進到此頁面，接下來要將我們需要使用的 API 加進來啟用。&lt;br />
點選&amp;quot;啟用 API 和服務&amp;quot;。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/youtube_spider_api/enable_api_1.jpg" alt="啟用 API" data-caption="啟用 API" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
啟用 API
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>找到 YouTube Data API v3。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/youtube_spider_api/enable_api_2.png" alt="啟用 API" data-caption="啟用 API" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
啟用 API
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>點擊&amp;quot;啟用&amp;quot;。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/youtube_spider_api/enable_api_3.png" alt="啟用 API" data-caption="啟用 API" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
啟用 API
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>最後要建立憑證，並取得 API Key。&lt;br />
點擊右方&amp;quot;建立憑證&amp;quot;，或者點擊左方的&amp;quot;憑證&amp;quot;。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/youtube_spider_api/create_credential_1.png" alt="建立憑證" data-caption="建立憑證" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
建立憑證
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>如果你是點擊左方&amp;quot;憑證&amp;quot;，則依下圖所示建立 API 金鑰 (API Key)。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/youtube_spider_api/create_credential_2.jpg" alt="建立憑證" data-caption="建立憑證" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
建立憑證
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>如果你是點擊右方&amp;quot;建立憑證&amp;quot;，則依下圖選擇，並點擊&amp;quot;我需要那些憑證&amp;quot;。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/youtube_spider_api/create_credential_3.png" alt="建立憑證" data-caption="建立憑證" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='760px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:760px;height:;"/>
&lt;figcaption style="text-align: center;">
建立憑證
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>它會跳到此頁面，將 API 金鑰複製下來，待之後程式使用。&lt;br />
(也可以&amp;quot;為金鑰新增限制&amp;quot;)&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/youtube_spider_api/create_credential_4.png" alt="建立憑證" data-caption="建立憑證" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='740px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:740px;height:;"/>
&lt;figcaption style="text-align: center;">
建立憑證
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>到這邊就完成 YouTube Data API Key 的取得，看似步驟很多，但實際操作過一遍就會了解了。&lt;/p>
&lt;p>* &lt;a href="https://developers.google.com/youtube/v3/getting-started#before-you-start" target="_blank" rel="noopener">
官方說明文檔
&lt;/a>&lt;/p>
&lt;h2 id="-爬蟲程式">📘 爬蟲程式&lt;/h2>
&lt;p>本次是直接使用 API，因此在送出請求時就不需要加入 header 中 User-Agent 欄位了。&lt;/p>
&lt;p>先在上方定義剛剛取得的 API Key，待之後發出請求時帶入。&lt;br />
(&lt;code>YOUR_YOUTUBE_API_KEY&lt;/code> 換成剛剛在上一步取得的 API Key)&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">YOUTUBE_API_KEY&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;YOUR_YOUTUBE_API_KEY&amp;#34;&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="api-說明">API 說明&lt;/h3>
&lt;p>在&lt;a href="https://developers.google.com/youtube/v3/docs" target="_blank" rel="noopener">
官方 API 文件
&lt;/a>內，可以查詢各種資源及各種請求方法。&lt;/p>
&lt;p>在本次程式中會用到幾種資源 (這邊都只需使用 list 方法)：&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://developers.google.com/youtube/v3/docs/channels/list" target="_blank" rel="noopener">
channels
&lt;/a>：取得頻道&amp;quot;上傳影片清單&amp;quot;的 ID&lt;/li>
&lt;li>&lt;a href="https://developers.google.com/youtube/v3/docs/playlistItems/list" target="_blank" rel="noopener">
playlistItems
&lt;/a>：取得清單中的影片列表&lt;/li>
&lt;li>&lt;a href="https://developers.google.com/youtube/v3/docs/videos/list" target="_blank" rel="noopener">
videos
&lt;/a>：取得影片資訊&lt;/li>
&lt;li>&lt;a href="https://developers.google.com/youtube/v3/docs/commentThreads/list" target="_blank" rel="noopener">
commentThreads
&lt;/a>：取得影片底下留言&lt;/li>
&lt;/ul>
&lt;p>本教學都只使用到 list 方法(GET)，因此網址串好後可以直接貼到瀏覽器上測試，觀看它回傳的資料。&lt;/p>
&lt;br>
&lt;p>因為每一次送出請求皆需要帶上 API Key，而且回傳資料要轉換JSON，所以可以另外寫一個用於組合網址、請求的函式，也可在裡面做當請求失敗的處理。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_html_to_json&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">path&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;組合 URL 後 GET 網頁並轉換成 JSON&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">api_url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;{self.base_url}{path}&amp;amp;key={self.api_key}&amp;#34;&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">api_url&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">None&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">data&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>* 為了較清楚的了解流程，以下範例程式內沒有加入太多的例外處理。&lt;/p>
&lt;h3 id="取得頻道上傳影片清單的-id">取得頻道&amp;quot;上傳影片&amp;quot;清單的 ID&lt;/h3>
&lt;p>想要抓取頻道內上傳的影片前，需要先抓到&amp;quot;上傳影片&amp;quot;清單的 ID，再用此 ID 去取的影片清單。&lt;/p>
&lt;p>使用&lt;a href="https://developers.google.com/youtube/v3/docs/channels/list" target="_blank" rel="noopener">
channels
&lt;/a>路徑來取得，需帶上&amp;quot;id&amp;quot;、&amp;quot;key&amp;quot;、&amp;quot;part&amp;quot;等查詢參數。&lt;br />
&lt;code>id&lt;/code> 代表頻道 ID；&lt;code>key&lt;/code> 代表我們的 API Key；&lt;code>part&lt;/code> 代表想取得的資源屬性。&lt;/p>
&lt;p>頻道ID的取得方式可以先到頻道首頁，觀察網址後方帶的數值，例如：&lt;br />
&lt;code>https://www.youtube.com/channel/UC7ia-A8gma8qcdC6GDcjwsQ&lt;/code>&lt;br />
&amp;quot;channel/&amp;quot;後方的 &lt;code>UC7ia-A8gma8qcdC6GDcjwsQ&lt;/code> 就代表此頻道的 ID。&lt;/p>
&lt;p>不過有時會發現網址是呈現以下形式：&lt;br />
&lt;code>https://www.youtube.com/c/六指淵Huber&lt;/code>&lt;br />
別擔心，此時隨便點擊頻道底下的其中一支影片，在點中間的頻道名稱進入後，一樣即可看到網址後方的數值。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/youtube_spider_api/channel_id.jpg" alt="如何取得頻道 ID" data-caption="如何取得頻道 ID" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
如何取得頻道 ID
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>至於&amp;quot;part&amp;quot;需帶什麼數值可以參考&lt;a href="https://developers.google.com/youtube/v3/docs/channels/list#parameters" target="_blank" rel="noopener">
官方 API 文檔
&lt;/a>說明，也可以一個一個嘗試看看會回傳什麼資料。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/youtube_spider_api/parameters.jpg" alt="part 查詢參數" data-caption="part 查詢參數" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
part 查詢參數
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>因為請求方式是使用 &lt;code>GET&lt;/code>，因此可以直接貼到瀏覽器上測試。&lt;br />
&lt;code>https://www.googleapis.com/youtube/v3/channels?part=contentDetails&amp;amp;id=UC7ia-A8gma8qcdC6GDcjwsQ&amp;amp;key={YOUR_API_KEY}&lt;/code>&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/youtube_spider_api/channels.png" alt="取得上傳影片清單的 ID" data-caption="取得上傳影片清單的 ID" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='400px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:400px;height:;"/>
&lt;figcaption style="text-align: center;">
取得上傳影片清單的 ID
&lt;/figcaption>
&lt;/figure>&lt;br />
==&amp;gt; &lt;a href="https://blog.jiatool.com/code/youtube_api/channels.json" target="_blank" rel="noopener">
回應資料範例
&lt;/a>&lt;/p>
&lt;p>其中 &lt;code>uploads&lt;/code> 後面那串就是此頻道&amp;quot;上傳影片&amp;quot;清單的 ID，這邊是 &lt;code>UU7ia-A8gma8qcdC6GDcjwsQ&lt;/code>。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_channel_uploads_id&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">channel_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">part&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;contentDetails&amp;#39;&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;取得頻道上傳影片清單的ID&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">path&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;channels?part={part}&amp;amp;id={channel_id}&amp;#39;&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_html_to_json&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">path&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">try&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">uploads_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;items&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;contentDetails&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;relatedPlaylists&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;uploads&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="k">except&lt;/span> &lt;span class="ne">KeyError&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">uploads_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">None&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">uploads_id&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="取得清單中的影片列表">取得清單中的影片列表&lt;/h3>
&lt;p>好的，接下來取得&amp;quot;上傳影片&amp;quot;清單的影片吧~&lt;/p>
&lt;p>使用&lt;a href="https://developers.google.com/youtube/v3/docs/playlistItems/list" target="_blank" rel="noopener">
playlistItems
&lt;/a>路徑來取得，需帶上&amp;quot;playlistId&amp;quot;、&amp;quot;key&amp;quot;、&amp;quot;part&amp;quot;等查詢參數。&lt;br />
&lt;code>playlistId&lt;/code> 代表播放列表 ID；&lt;code>key&lt;/code> 代表我們的 API Key；&lt;code>part&lt;/code> 代表想取得的資源屬性。&lt;/p>
&lt;p>這邊代的參數大部分與上方雷同，可以自行參考官方 API 文檔說明，就不多說介紹了。&lt;br />
我們要抓此頻道上傳影片，所以 &lt;code>playlistId&lt;/code> 帶入上一步抓到的&amp;quot;上傳影片&amp;quot;清單的 ID。&lt;/p>
&lt;p>&lt;code>https://www.googleapis.com/youtube/v3/playlistItems?part=contentDetails&amp;amp;playlistId=UU7ia-A8gma8qcdC6GDcjwsQ&amp;amp;key={YOUR_API_KEY}&lt;/code>&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/youtube_spider_api/playlistItems.png" alt="取得影片ID" data-caption="取得影片ID" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='400px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:400px;height:;"/>
&lt;figcaption style="text-align: center;">
取得影片ID
&lt;/figcaption>
&lt;/figure>&lt;br />
==&amp;gt; &lt;a href="https://blog.jiatool.com/code/youtube_api/playlistItems.json" target="_blank" rel="noopener">
回應資料範例
&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_playlist&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">playlist_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">part&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;contentDetails&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">max_results&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;取得影片清單ID中的影片&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">path&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;playlistItems?part={part}&amp;amp;playlistId={playlist_id}&amp;amp;maxResults={max_results}&amp;#39;&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_html_to_json&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">path&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;span class="n">video_ids&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">data_item&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;items&amp;#39;&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;span class="n">video_ids&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data_item&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;contentDetails&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;videoId&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">video_ids&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="取得影片資訊">取得影片資訊&lt;/h3>
&lt;p>針對每一支影片，來取得其影片相關資訊吧~&lt;/p>
&lt;p>使用&lt;a href="https://developers.google.com/youtube/v3/docs/videos/list" target="_blank" rel="noopener">
videos
&lt;/a>路徑來取得，需帶上&amp;quot;id&amp;quot;、&amp;quot;key&amp;quot;、&amp;quot;part&amp;quot;等查詢參數。&lt;br />
&lt;code>id&lt;/code> 代表影片 ID；&lt;code>key&lt;/code> 代表我們的 API Key；&lt;code>part&lt;/code> 代表想取得的資源屬性。&lt;/p>
&lt;p>&lt;code>https://www.googleapis.com/youtube/v3/videos?part=snippet,statistics&amp;amp;id=lM7ltxkXE40&amp;amp;key={YOUR_API_KEY}&lt;/code>&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/youtube_spider_api/videos.png" alt="取得影片資訊" data-caption="取得影片資訊" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
取得影片資訊
&lt;/figcaption>
&lt;/figure>&lt;br />
==&amp;gt; &lt;a href="https://blog.jiatool.com/code/youtube_api/videos.json" target="_blank" rel="noopener">
回應資料範例
&lt;/a>&lt;/p>
&lt;p>回傳資料有影片標題、頻道名稱、發布時間、縮圖網址、觀看數、留言數&amp;hellip;&amp;hellip;等等許多相關資訊。&lt;/p>
&lt;p>* 謝謝網友提醒，&lt;code>dislikeCount&lt;/code> 資訊現在無法取得了，這應該也是因應 YouTube 現在不能看到 Dislike 的數量了。&lt;/p>
&lt;blockquote>
&lt;p>Note: The statistics.dislikeCount property was made private as of December 13, 2021. This means that the property is included in an API response only if the API request was authenticated by the video owner. See the revision history for more information.&lt;/p>
&lt;/blockquote>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_video&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">video_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">part&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;snippet,statistics&amp;#39;&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;取得影片資訊&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">path&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;videos?part={part}&amp;amp;id={video_id}&amp;#39;&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_html_to_json&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">path&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;span class="c1"># 以下整理並提取需要的資料&lt;/span>
&lt;span class="n">data_item&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;items&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="k">try&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">time_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strptime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data_item&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;snippet&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;publishedAt&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="s1">&amp;#39;%Y-%m-&lt;/span>&lt;span class="si">%d&lt;/span>&lt;span class="s1">T%H:%M:%SZ&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">except&lt;/span> &lt;span class="ne">ValueError&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="c1"># 日期格式錯誤&lt;/span>
&lt;span class="n">time_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">None&lt;/span>
&lt;span class="n">url_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;https://www.youtube.com/watch?v={data_item[&amp;#39;id&amp;#39;]}&amp;#34;&lt;/span>
&lt;span class="n">info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;id&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">data_item&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;id&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="s1">&amp;#39;channelTitle&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">data_item&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;snippet&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;channelTitle&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="s1">&amp;#39;publishedAt&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">time_&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;video_url&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">url_&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;title&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">data_item&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;snippet&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;title&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="s1">&amp;#39;description&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">data_item&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;snippet&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;description&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="s1">&amp;#39;likeCount&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">data_item&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;statistics&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;likeCount&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="c1"># &amp;#39;dislikeCount&amp;#39;: data_item[&amp;#39;statistics&amp;#39;][&amp;#39;dislikeCount&amp;#39;],&lt;/span>
&lt;span class="s1">&amp;#39;commentCount&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">data_item&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;statistics&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;commentCount&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="s1">&amp;#39;viewCount&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">data_item&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;statistics&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;viewCount&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">info&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="取得留言資訊">取得留言資訊&lt;/h3>
&lt;p>那該如何取得影片底下的留言呢？&lt;/p>
&lt;p>使用&lt;a href="https://developers.google.com/youtube/v3/docs/commentThreads/list" target="_blank" rel="noopener">
commentThreads
&lt;/a>路徑來取得，需帶上&amp;quot;videoId&amp;quot;、&amp;quot;key&amp;quot;、&amp;quot;part&amp;quot;等查詢參數。&lt;br />
&lt;code>videoId&lt;/code> 代表播放列表 ID；&lt;code>key&lt;/code> 代表我們的 API Key；&lt;code>part&lt;/code> 代表想取得的資源屬性。&lt;/p>
&lt;p>&lt;code>https://www.googleapis.com/youtube/v3/commentThreads?part=snippet&amp;amp;videoId=lM7ltxkXE40&amp;amp;key={YOUR_API_KEY}&lt;/code>&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/youtube_spider_api/commentThreads.png" alt="取得留言資訊" data-caption="取得留言資訊" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
取得留言資訊
&lt;/figcaption>
&lt;/figure>&lt;br />
==&amp;gt; &lt;a href="https://blog.jiatool.com/code/youtube_api/commentThreads.json" target="_blank" rel="noopener">
回應資料範例
&lt;/a>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_comments&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">video_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">page_token&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">part&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;snippet&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">max_results&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">100&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;取得影片留言&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">path&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;commentThreads?part={part}&amp;amp;videoId={video_id}&amp;amp;maxResults={max_results}&amp;amp;pageToken={page_token}&amp;#39;&lt;/span>
&lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_html_to_json&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">path&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="p">[],&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>
&lt;span class="c1"># 下一頁的數值&lt;/span>
&lt;span class="n">next_page_token&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;nextPageToken&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 以下整理並提取需要的資料&lt;/span>
&lt;span class="n">comments&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">data_item&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;items&amp;#39;&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;span class="n">data_item&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data_item&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;snippet&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="n">top_comment&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">data_item&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;topLevelComment&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="k">try&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">time_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strptime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">top_comment&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;snippet&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;publishedAt&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="s1">&amp;#39;%Y-%m-&lt;/span>&lt;span class="si">%d&lt;/span>&lt;span class="s1">T%H:%M:%SZ&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">except&lt;/span> &lt;span class="ne">ValueError&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="c1"># 日期格式錯誤&lt;/span>
&lt;span class="n">time_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="bp">None&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="s1">&amp;#39;authorChannelId&amp;#39;&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">top_comment&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;snippet&amp;#39;&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;span class="n">ru_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">top_comment&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;snippet&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;authorChannelId&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;value&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">ru_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>
&lt;span class="n">ru_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">top_comment&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;snippet&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;authorDisplayName&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">ru_name&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">ru_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>
&lt;span class="n">comments&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">({&lt;/span>
&lt;span class="s1">&amp;#39;reply_id&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">top_comment&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;id&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="s1">&amp;#39;ru_id&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">ru_id&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;ru_name&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">ru_name&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;reply_time&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">time_&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;reply_content&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">top_comment&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;snippet&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;textOriginal&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;span class="s1">&amp;#39;rm_positive&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">top_comment&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;snippet&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;likeCount&amp;#39;&lt;/span>&lt;span class="p">]),&lt;/span>
&lt;span class="s1">&amp;#39;rn_comment&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data_item&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;totalReplyCount&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="p">})&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">comments&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">next_page_token&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="其他查詢參數">其他查詢參數&lt;/h3>
&lt;p>還有其他常用的查詢參數：&lt;/p>
&lt;p>像是 &lt;code>maxResults&lt;/code> 可以限制回傳筆數，搭配 commentThreads 帶入 &lt;code>maxResults=10&lt;/code> 代表最多回傳 10 筆留言。&lt;/p>
&lt;p>又例如 &lt;code>pageToken&lt;/code> 是用來換頁的，什麼意思呢？&lt;br />
像是 API 有限制留言最多一次只能抓 100 筆留言，就算你帶入 &lt;code>maxResults=200&lt;/code> 也只能抓到 100 筆。&lt;br />
但在回傳的資料中可以發現一個 &lt;code>nextPageToken&lt;/code> 欄位，代表你再用一樣的網址請求一次，帶上 &lt;code>pageToken=QURTSl9pMmhMYktBc25xOHZtZTg3enJBTFFXNTFPbldJY05zTFFTTjdMM25VYThmdTBwWS1CNGFPZm1kQUU0WkJac0dWZkw3cWI2V1owOA==&lt;/code> 就能取得下一頁的資料(例如：101~200 筆留言)。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/youtube_spider_api/nextPageToken.png" alt="nextPageToken 欄位" data-caption="nextPageToken 欄位" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
nextPageToken 欄位
&lt;/figcaption>
&lt;/figure>&lt;br />
在像是有多個留言(commentThreads)或多支影片(playlistItems)時需要用到。&lt;br />
以上一段取得留言為例，會像是如下：&lt;br />
&lt;code>https://www.googleapis.com/youtube/v3/commentThreads?part=snippet&amp;amp;videoId=lM7ltxkXE40&amp;amp;pageToken=QURTSl9pMmhMYktBc25xOHZtZTg3enJBTFFXNTFPbldJY05zTFFTTjdMM25VYThmdTBwWS1CNGFPZm1kQUU0WkJac0dWZkw3cWI2V1owOA==&amp;amp;key={YOUR_API_KEY}&lt;/code>&lt;/p>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="完整程式碼">完整程式碼&lt;/h2>
&lt;p>附上完整程式碼：&lt;a href="https://blog.jiatool.com/code/youtube_spider_api.py" target="_blank" rel="noopener">
youtube_spider_api.py
&lt;/a>&lt;br />
(對超連結右鍵 &amp;gt; 另存連結為)&lt;/p>
&lt;h2 id="注意事項">注意事項&lt;/h2>
&lt;p>要注意的是這個 API 有額度的限制，為每天 10,000 個單位(&lt;a href="https://developers.google.com/youtube/v3/getting-started#quota" target="_blank" rel="noopener">
官方說明
&lt;/a>)，如果想將影片的留言都抓下來，可能就會耗費較多額度。&lt;br />
像上方使用的查詢都是消耗 1 單位。&lt;/p>
&lt;p>在&lt;a href="https://console.cloud.google.com/apis/api/youtube.googleapis.com/quotas" target="_blank" rel="noopener">
配額頁面
&lt;/a>可以查看此專案目前耗費的單位。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/youtube_spider_api/quotas.png" alt="配額頁面" data-caption="配額頁面" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
配額頁面
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;h2 id="延伸練習">延伸練習&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>在上方教學中，影片清單只有取得前 5 則影片，那如果我想取得前 100 則影片呢？是不是會遇到什麼問題？需不需要加上什麼參數？&lt;br />
* 提示：參考教學中爬取留言的方法，使用 &lt;code>pageToken&lt;/code> 參數。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>上方教學只說抓取留言，那我如何想取得留言的回覆呢？是要帶入什麼參數嗎？或者是使用不同的方法？&lt;br />
* 提示：&lt;code>part&lt;/code> 中的 &lt;a href="https://developers.google.com/youtube/v3/docs/commentThreads/list#parameters" target="_blank" rel="noopener">
replies
&lt;/a>，或&lt;a href="https://developers.google.com/youtube/v3/docs/comments/list" target="_blank" rel="noopener">
Comments
&lt;/a>資源。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>我會陸續寫一些網站的&lt;a href="https://blog.jiatool.com/series/Python%e7%b6%b2%e8%b7%af%e7%88%ac%e8%9f%b2%e5%af%a6%e4%be%8b/" target="_blank" rel="noopener">
Python網路爬蟲實例
&lt;/a>，如果你正好是剛開始想學爬蟲的新手、想知道某個網站如何爬取資料，或者遇到其他問題，歡迎過來參考和在底下留言~👇&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://developers.google.com/youtube/v3" target="_blank" rel="noopener">
官方 YouTube Data API 範例文檔
&lt;/a>&lt;/p>
&lt;br/>
&lt;blockquote>
&lt;p>每一個成功者都有一個開始。&lt;br />
勇於開始，才能找到成功的路。&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/youtube_spider_api.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><category>Python</category><category>YouTube</category><category>API</category><category>網路爬蟲</category><category>Python網路爬蟲實例</category></item><item><title>[Python爬蟲實例] 巴哈姆特哈啦區留言-動態載入</title><link>https://blog.jiatool.com/posts/gamer_commend_spider/</link><pubDate>Fri, 02 Oct 2020 21:10:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Fri, 02 Oct 2020 21:10:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/gamer_commend_spider/</guid><description>前言 Python網路爬蟲實例系列第一篇「巴哈姆特哈啦區 」裡，我們先跳過留言的爬取，並於延伸練習中的第二題讓大家嘗試。 而在經過了上一篇「聯合新</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>Python網路爬蟲實例系列第一篇「&lt;a href="https://blog.jiatool.com/posts/gamer_spider/" target="_blank" rel="noopener">
巴哈姆特哈啦區
&lt;/a>」裡，我們先跳過留言的爬取，並於延伸練習中的第二題讓大家嘗試。&lt;/p>
&lt;p>而在經過了上一篇「&lt;a href="https://blog.jiatool.com/posts/udn_spider/" target="_blank" rel="noopener">
聯合新聞網-動態載入
&lt;/a>」，應該大致知道該怎麼處理動態載入的部分。本文再實際帶著大家來爬取&amp;quot;巴哈姆特哈啦區的留言&amp;quot;，一樣是採用 Ajax 動態載入，最後也會附上完整程式碼供參考，那我們就開始吧~&lt;/p>
&lt;p>備註：此文僅教育學習，切勿用作商業用途，個人實作皆屬個人行為，本作者不負任何法律責任&lt;/p>
&lt;h2 id="套件">套件&lt;/h2>
&lt;p>此次 Python 爬蟲主要使用到的套件：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Requests [&lt;a href="https://requests.readthedocs.io/en/master/" target="_blank" rel="noopener">
Doc
&lt;/a>] [&lt;a href="https://github.com/psf/requests" target="_blank" rel="noopener">
GitHub
&lt;/a>]&lt;/p>
&lt;/li>
&lt;li>
&lt;p>BeautifulSoup [&lt;a href="https://www.crummy.com/software/BeautifulSoup/bs4/doc/" target="_blank" rel="noopener">
Doc
&lt;/a>] [&lt;a href="https://code.launchpad.net/beautifulsoup" target="_blank" rel="noopener">
Source
&lt;/a>]&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="流程">流程&lt;/h2>
&lt;p>首先進到巴哈姆特哈啦區中任一看板的任一文章，如同Python網路爬蟲實例第一篇「&lt;a href="https://blog.jiatool.com/posts/gamer_spider/" target="_blank" rel="noopener">
巴哈姆特哈啦區
&lt;/a>」先爬取各個樓層回覆，再進入抓取底下留言的部分。&lt;/p>
&lt;p>一樣要觀察其留言列表載入方式，使用瀏覽器的開發人員工具找出 Ajax 請求網址，透過此網址取得新聞列表的 JSON 格式資料。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_commend_spider/description.png" alt="欲爬取的留言" data-caption="欲爬取的留言" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
欲爬取的留言
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;h2 id="爬蟲程式">爬蟲程式&lt;/h2>
&lt;p>網站有些常見的反爬蟲機制是偵測你送來 requests 的 header 中 User-Agent 欄位，因此我們就需要模仿一般瀏覽器送出去的資料。&lt;br />
先在上方定義 HEADERS 變數，之後需要發出請求就帶入此數值。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">HEADERS&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;User-Agent&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="如何載入留言">如何載入留言&lt;/h3>
&lt;p>我們先找一則回覆的留言是需要點擊展開的，例如：&lt;a href="https://forum.gamer.com.tw/C.php?bsn=60076&amp;amp;snA=4549786" target="_blank" rel="noopener">
https://forum.gamer.com.tw/C.php?bsn=60076&amp;amp;snA=4549786
&lt;/a>，對網頁點滑鼠右鍵 &amp;gt; 檢視網頁原始碼，查看此網頁的原始碼，&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_commend_spider/view_page_source.jpg" alt="檢視網頁原始碼" data-caption="檢視網頁原始碼" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='750px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:750px;height:;"/>
&lt;figcaption style="text-align: center;">
檢視網頁原始碼
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>在其中試著搜尋(Ctrl + f)需要展開才能看到的留言，會發現並沒有在網頁原始碼內，因此可以推測留言可能使用動態載入的方式。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_commend_spider/search_commend.jpg" alt="試著搜尋留言" data-caption="試著搜尋留言" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
試著搜尋留言
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>打開瀏覽器的 &lt;strong>開發人員工具&lt;/strong> (F12 或 Ctrl + Shift + i) &amp;gt; &lt;strong>Network(網路)&lt;/strong> 分頁，切換到&lt;code>XHR&lt;/code>重整網頁一下(F5)，當點擊&amp;quot;還有 2 則留言&amp;quot;後會發現有新的項目出現。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_commend_spider/loading.jpg" alt="開發人員工具 &amp;gt; Network(網路) &amp;gt; XHR" data-caption="開發人員工具 &amp;gt; Network(網路) &amp;gt; XHR" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
開發人員工具 &amp;gt; Network(網路) &amp;gt; XHR
&lt;/figcaption>
&lt;/figure>&lt;br />
單點選它之後，右邊選擇 &lt;code>Preview&lt;/code> 分頁，即可發現這就是我們想要的資料！🤩&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_commend_spider/preview.png" alt="開發人員工具 &amp;gt; Network(網路) &amp;gt; XHR &amp;gt; Preview" data-caption="開發人員工具 &amp;gt; Network(網路) &amp;gt; XHR &amp;gt; Preview" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
開發人員工具 &amp;gt; Network(網路) &amp;gt; XHR &amp;gt; Preview
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;h3 id="試著載入留言">試著載入留言&lt;/h3>
&lt;p>切換到 &lt;code>Headers&lt;/code> 分頁，會顯示請求的網址(綠色框)以及請求方式(紫色框)，如此圖片顯示是使用 GET 方式，&lt;br />
&lt;a href="https://forum.gamer.com.tw/ajax/moreCommend.php?bsn=60076&amp;amp;snB=50892275&amp;amp;returnHtml=1">https://forum.gamer.com.tw/ajax/moreCommend.php?bsn=60076&amp;amp;snB=50892275&amp;amp;returnHtml=1&lt;/a>&lt;br />
將網址複製起來，開個新分頁貼上網址後前往，順利取得回傳的資料(留言)。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_commend_spider/headers.png" alt="開發人員工具 &amp;gt; Network(網路) &amp;gt; XHR &amp;gt; Headers" data-caption="開發人員工具 &amp;gt; Network(網路) &amp;gt; XHR &amp;gt; Headers" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
開發人員工具 &amp;gt; Network(網路) &amp;gt; XHR &amp;gt; Headers
&lt;/figcaption>
&lt;/figure>&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_commend_spider/more_commend_html.png" alt="回傳資料(留言)" data-caption="回傳資料(留言)" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='850px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:850px;height:;"/>
&lt;figcaption style="text-align: center;">
回傳資料(留言)
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>從上方回傳資料發現其留言已經使用 HTML 的格式，為了可以直接丟到網頁上顯示，雖然我們可以抓下來用 BeautifulSoup 解析，但注意觀察請求的網址會發現當中有帶一個參數 &lt;code>returnHtml&lt;/code>，如果將其參數的值改為1，或將此參數移除，它回傳的資料就變成我們喜歡的 JSON 格式~ (歡呼)&lt;br />
&lt;a href="https://forum.gamer.com.tw/ajax/moreCommend.php?bsn=60076&amp;amp;snB=50892275">https://forum.gamer.com.tw/ajax/moreCommend.php?bsn=60076&amp;amp;snB=50892275&lt;/a>&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_commend_spider/what_parameter.jpg" alt="觀察網址參數" data-caption="觀察網址參數" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='400px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:400px;height:;"/>
&lt;figcaption style="text-align: center;">
觀察網址參數
&lt;/figcaption>
&lt;/figure>&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_commend_spider/more_commend_json.png" alt="回傳資料(留言) JSON格式" data-caption="回傳資料(留言) JSON格式" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='850px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:850px;height:;"/>
&lt;figcaption style="text-align: center;">
回傳資料(留言) JSON格式
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>不用再耗費力氣去找哪個資料對應哪個Tag、Class之類的麻煩事~&lt;/p>
&lt;h3 id="觀察回傳資料">觀察回傳資料&lt;/h3>
&lt;p>將資料貼到線上 JSON 工具(&lt;a href="http://jsoneditoronline.org/" target="_blank" rel="noopener">
JSON Editor Online
&lt;/a>)來觀察，發現它除了有一個 &lt;code>next_snC&lt;/code>，剩下都是留言資料。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_commend_spider/json_editor.png" alt="觀察回傳資料" data-caption="觀察回傳資料" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='600px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:600px;height:;"/>
&lt;figcaption style="text-align: center;">
觀察回傳資料
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>其中比較重要的有以下欄位：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>參數&lt;/th>
&lt;th>代表意思&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>bsn&lt;/td>
&lt;td>板塊ID&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>snB&lt;/td>
&lt;td>回覆ID&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>sn&lt;/td>
&lt;td>留言ID&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>userid&lt;/td>
&lt;td>留言者ID&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>nick&lt;/td>
&lt;td>留言者名稱&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>comment、content&lt;/td>
&lt;td>留言內容 (目前不知道兩者差異)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>gp&lt;/td>
&lt;td>GP&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>bp&lt;/td>
&lt;td>BP&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>wtime&lt;/td>
&lt;td>發布時間&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>mtime&lt;/td>
&lt;td>編輯時間&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>OK！接下來就要實際動手寫 code 囉~ 😙&lt;/p>
&lt;h3 id="爬取每一樓層回覆">爬取每一樓層回覆&lt;/h3>
&lt;p>* 為了簡化程式碼方便理解，像之前判斷請求是否成功的部份，這次將其省略。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">HEADERS&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;網頁載入失敗&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>跟之前「&lt;a href="https://blog.jiatool.com/posts/gamer_spider/" target="_blank" rel="noopener">
[Python爬蟲實例] 巴哈姆特哈啦區
&lt;/a>」一樣，透過 Tag 的 id 爬取每一樓層回覆。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_commend_spider/reply_block.jpg" alt="每一樓層回覆" data-caption="每一樓層回覆" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
每一樓層回覆
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>這邊還需要取得&amp;quot;板塊ID&amp;quot;，因為爬取留言網址需要。&lt;br />
(這部分可以拉出來寫個 Function，之後需要使用比較方便。)&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_reply_info_list&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;爬取回覆列表&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">HEADERS&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">soup&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">BeautifulSoup&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">features&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;lxml&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">reply_blocks&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;section[id^=&amp;#34;post_&amp;#34;]&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 這部分可以拉出來寫個 Function，之後需要使用比較方便。&lt;/span>
&lt;span class="n">bsn&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">url&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">split&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;bsn=&amp;#39;&lt;/span>&lt;span class="p">)[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="n">bsn&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">bsn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">split&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;&amp;amp;&amp;#39;&lt;/span>&lt;span class="p">)[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="c1"># ......&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>也需要取得&amp;quot;回覆ID&amp;quot;，而其 Tag 的 id 後方接著的數字就是&amp;quot;回覆ID&amp;quot;。&lt;/p>
&lt;p>將&amp;quot;板塊ID&amp;quot;與&amp;quot;回覆ID&amp;quot;傳入 &lt;code>get_commend_info_list()&lt;/code> 供組合出爬取留言網址使用。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_reply_info_list&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;爬取回覆列表&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="c1"># ......&lt;/span>
&lt;span class="c1"># 對每一則回覆解析資料&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">reply_block&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">reply_blocks&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">floor&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">reply_block&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.floor&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;data-floor&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">reply_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">reply_block&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;id&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">reply_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">reply_id&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">split&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;_&amp;#39;&lt;/span>&lt;span class="p">)[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;第 {floor} 樓 ID:{reply_id}&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">commends&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_commend_info_list&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bsn&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">bsn&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">reply_id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">reply_id&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s1">&amp;#39;-&amp;gt; 總共有 {len(commends)} 則留言&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="爬取每一則留言">爬取每一則留言&lt;/h3>
&lt;p>組合出爬取留言用的網址，取得回傳資料，用 requests 提供的 &lt;code>r.json()&lt;/code> 解碼轉換成 Dict。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_commend_spider/commend_url.png" alt="留言網址" data-caption="留言網址" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
留言網址
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>這邊有一點要注意，回傳資料中會有一個叫&amp;quot;next_snC&amp;quot;，其他都是字串格式的數字。&lt;br />
數字的裡面放著留言，要排除掉&amp;quot;next_snC&amp;quot;。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_commend_spider/commend_data.png" alt="回傳資料" data-caption="回傳資料" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='250px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:250px;height:;"/>
&lt;figcaption style="text-align: center;">
回傳資料
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>這邊我們弄一個 commends 的列表保存需要的留言資料，最後回傳。&lt;/p>
&lt;p>備註：不太確定它一次最多可以回傳幾則留言，如果有人發現超過 1000 則留言的回覆，歡迎底下留言，我再將其補充。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_commend_info_list&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bsn&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">reply_id&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;https://forum.gamer.com.tw/ajax/moreCommend.php?bsn={bsn}&amp;amp;snB={reply_id}&amp;#34;&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">HEADERS&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">commends_duct&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">commends&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">key&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">value&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">commends_duct&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">items&lt;/span>&lt;span class="p">():&lt;/span>
&lt;span class="c1"># 判斷是否是數字(commend)，排除&amp;#34;next_snC&amp;#34;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">key&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">isdigit&lt;/span>&lt;span class="p">():&lt;/span>
&lt;span class="n">commends&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;板塊ID&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;bsn&amp;#39;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;span class="s1">&amp;#39;回覆ID&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;snB&amp;#39;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;span class="s1">&amp;#39;留言ID&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;sn&amp;#39;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;span class="s1">&amp;#39;留言者ID&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;userid&amp;#39;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;span class="s1">&amp;#39;留言者名稱&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;nick&amp;#39;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;span class="s1">&amp;#39;留言內容&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;comment&amp;#39;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;span class="s1">&amp;#39;GP&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;gp&amp;#39;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;span class="s1">&amp;#39;BP&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;bp&amp;#39;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;span class="s1">&amp;#39;發布時間&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;wtime&amp;#39;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;span class="s1">&amp;#39;編輯時間&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;mtime&amp;#39;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">commends&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>執行結果如下，這邊我顯示第一則留言方便觀察：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="err">第&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="err">樓&lt;/span> &lt;span class="n">ID&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="mi">50892275&lt;/span>
&lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;板塊ID&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;60076&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;回覆ID&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;50892275&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;留言ID&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;2434849&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;留言者ID&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;madaan40&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;留言者名稱&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;ABC123&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;留言內容&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;1&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;GP&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;0&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;BP&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;0&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;發布時間&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;2019-12-15 08:43:18&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;編輯時間&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;0000-00-00 00:00:00&amp;#39;&lt;/span>&lt;span class="p">}&lt;/span>
&lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="err">總共有&lt;/span> &lt;span class="mi">7&lt;/span> &lt;span class="err">則留言&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="完整程式碼">完整程式碼&lt;/h2>
&lt;p>附上完整程式碼：&lt;a href="https://blog.jiatool.com/code/gamer_commend_spider.py" target="_blank" rel="noopener">
gamer_commend_spider.py
&lt;/a>&lt;br />
(對超連結右鍵 &amp;gt; 另存連結為)&lt;/p>
&lt;h2 id="延伸練習">延伸練習&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>回傳的留言資料中，有一筆 &lt;code>&amp;quot;next_snC&amp;quot;:0&lt;/code> 資料，你可以猜測它是代表什麼意思嗎？&lt;/p>
&lt;/li>
&lt;li>
&lt;p>嘗試結合第一篇「&lt;a href="https://blog.jiatool.com/posts/gamer_spider/" target="_blank" rel="noopener">
巴哈姆特哈啦區
&lt;/a>」文章，寫出可以爬取&amp;quot;文章&amp;quot;、&amp;quot;回覆&amp;quot;、&amp;quot;留言&amp;quot;的爬蟲程式~&lt;/p>
&lt;/li>
&lt;/ol>
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>其實沒有想像中的難吧~趕快自己實際動手寫寫看~&lt;/p>
&lt;p>之後會繼續加入不同網站的&amp;quot;網路爬蟲實例&amp;quot;，如果你正好是剛開始想學爬蟲的新手、想知道某個網站如何爬取資料，又或者遇到其他問題，歡迎參考和在底下留言ㄛ~😙&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://forum.gamer.com.tw/" target="_blank" rel="noopener">
巴哈姆特 - 哈啦區
&lt;/a>&lt;/p>
&lt;br/>
&lt;blockquote>
&lt;p>別想一下造出大海，必須先由小河川開始。&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/gamer_commend_spider.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><category>Python</category><category>巴哈姆特</category><category>網路爬蟲</category><category>Python網路爬蟲實例</category></item><item><title>[Python爬蟲實例] 聯合新聞網-動態載入</title><link>https://blog.jiatool.com/posts/udn_spider/</link><pubDate>Sun, 27 Sep 2020 21:15:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sun, 27 Sep 2020 21:15:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/udn_spider/</guid><description>前言 Python網路爬蟲實例系列 第二篇，本篇一步步講解如何使用 Python 爬取 udn聯合新聞網 的即時列表新聞，包含更多新聞採 Ajax 動態載入的部分，最後也會</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>&lt;a href="https://blog.jiatool.com/series/Python%e7%b6%b2%e8%b7%af%e7%88%ac%e8%9f%b2%e5%af%a6%e4%be%8b/" target="_blank" rel="noopener">
Python網路爬蟲實例系列
&lt;/a>第二篇，本篇一步步講解如何使用 Python 爬取 &lt;a href="https://udn.com/news/breaknews/1/99" target="_blank" rel="noopener">
udn聯合新聞網
&lt;/a> 的即時列表新聞，包含更多新聞採 Ajax 動態載入的部分，最後也會附上完整程式碼供參考。&lt;/p>
&lt;p>備註：此文僅教育學習，切勿用作商業用途，個人實作皆屬個人行為，本作者不負任何法律責任&lt;/p>
&lt;h2 id="套件">套件&lt;/h2>
&lt;p>此次 Python 爬蟲主要使用到的套件：&lt;/p>
&lt;ul>
&lt;li>Requests [&lt;a href="https://requests.readthedocs.io/en/master/" target="_blank" rel="noopener">
Doc
&lt;/a>] [&lt;a href="https://github.com/psf/requests" target="_blank" rel="noopener">
GitHub
&lt;/a>]&lt;/li>
&lt;/ul>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="流程">流程&lt;/h2>
&lt;p>首先進入 &lt;a href="https://udn.com/news/breaknews/1/99" target="_blank" rel="noopener">
聯合新聞網-即時列表
&lt;/a> 網頁，觀察其新聞列表載入方式，使用瀏覽器的開發人員工具找出 Ajax 請求網址，透過此網址取得新聞列表的 JSON 格式資料，如此即可抓取新聞網址、標題、閱覽數等等資料。&lt;/p>
&lt;p>以下範例說明皆以「即時列表-不分類」舉例，其他類別所需要帶入的參數可能稍微不同。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/udn_spider/news_list.jpg" alt="即時列表-不分類" data-caption="即時列表-不分類" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
即時列表-不分類
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;h2 id="爬蟲程式">爬蟲程式&lt;/h2>
&lt;p>網站有些常見的反爬蟲機制是偵測你送來 requests 的 header 中 User-Agent 欄位，因此我們就需要模仿一般瀏覽器送出去的資料。&lt;br />
先在上方定義 HEADERS 變數，待之後需要發出請求就帶入此數值。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">HEADERS&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;User-Agent&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="如何載入更多新聞">如何載入更多新聞&lt;/h3>
&lt;p>跟前一篇實例教學 (&lt;a href="https://blog.jiatool.com/posts/gamer_spider/" target="_blank" rel="noopener">
[Python爬蟲實例] 巴哈姆特哈啦區
&lt;/a>) 最不一樣的，是使用瀏覽器閱覽網頁明明就看到許多篇新聞，一直往下滾就一直產生，但使用程式抓取只能取得前 28 篇新聞。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/udn_spider/crawler_news_list.png" alt="只能取得前 28 篇新聞" data-caption="只能取得前 28 篇新聞" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
只能取得前 28 篇新聞
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>為什麼會這樣？！&lt;br />
原來當我們網頁往下滾後，它會透過 Ajax 動態載入後續新聞資料，並不在我們一開始請求後回傳的網頁原始碼內，難怪無法抓取。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/udn_spider/loading.jpg" alt="新聞採動態載入" data-caption="新聞採動態載入" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
新聞採動態載入
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>針對這種採用 Ajax 動態載入的網頁，有兩種方式來取得資料：&lt;/p>
&lt;ol>
&lt;li>一種是使用 &lt;a href="https://www.selenium.dev/" target="_blank" rel="noopener">
Selenium
&lt;/a> 來操作瀏覽器載入資料。&lt;/li>
&lt;li>另一種(也就是本篇教學要使用的方式)是找出 Ajax 去請求的網址，然後照他的請求方式、參數來取得資料。&lt;/li>
&lt;/ol>
&lt;p>我們來試著找出它動態載入的網址吧。&lt;/p>
&lt;p>打開瀏覽器的 &lt;strong>開發人員工具&lt;/strong> (F12 或 Ctrl + Shift + i) &amp;gt; &lt;strong>Network(網路)&lt;/strong> 分頁，切換到&lt;code>XHR&lt;/code>，重整網頁一下(F5)讓它載入資料﹐並把網頁往下滾讓它載入更多新聞資料，會發現有新的項目出現。&lt;br />
單點選它之後，右邊選擇 &lt;code>Preview&lt;/code> 分頁，即可發現這就是我們想要的資料。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/udn_spider/xhr.jpg" alt="開發人員工具 &amp;gt; Network(網路) &amp;gt; XHR &amp;gt; Preview" data-caption="開發人員工具 &amp;gt; Network(網路) &amp;gt; XHR &amp;gt; Preview" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
開發人員工具 &amp;gt; Network(網路) &amp;gt; XHR &amp;gt; Preview
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>所以概念就是，是當我們網頁往下滾到底部後，會觸發網頁的 JavaScript 程式，讓它透過 Ajax 動態載入，將新聞資料一直載入進來。&lt;/p>
&lt;h3 id="試著載入更多新聞">試著載入更多新聞&lt;/h3>
&lt;p>切換到 &lt;code>Headers&lt;/code> 分頁，會顯示請求的網址(綠色框)以及請求方式(紫色框)，如此圖片顯示是使用 GET 方式，我們在瀏覽器中輸入網址前往就是 GET 請求方式。&lt;br />
&lt;a href="https://udn.com/api/more?page=2&amp;amp;id=&amp;amp;channelId=1&amp;amp;cate_id=99&amp;amp;type=breaknews&amp;amp;totalRecNo=17749">https://udn.com/api/more?page=2&amp;amp;id=&amp;amp;channelId=1&amp;amp;cate_id=99&amp;amp;type=breaknews&amp;amp;totalRecNo=17749&lt;/a>&lt;br />
將網址複製起來，瀏覽器開個新分頁，貼上網址後 Enter 前往，收到的資料即是我們需要的更多新聞。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/udn_spider/headers.png" alt="開發人員工具 &amp;gt; Network(網路) &amp;gt; XHR &amp;gt; Headers" data-caption="開發人員工具 &amp;gt; Network(網路) &amp;gt; XHR &amp;gt; Headers" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
開發人員工具 &amp;gt; Network(網路) &amp;gt; XHR &amp;gt; Headers
&lt;/figcaption>
&lt;/figure>&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/udn_spider/more_news.jpg" alt="回傳資料" data-caption="回傳資料" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
回傳資料
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;h3 id="觀察回傳資料">觀察回傳資料&lt;/h3>
&lt;p>取得資料後，為了方便觀察，可以找尋線上 JSON 工具或瀏覽器擴充功能來輔助，這邊我使用 &lt;a href="http://jsoneditoronline.org/" target="_blank" rel="noopener">
JSON Editor Online
&lt;/a> 來演示。&lt;/p>
&lt;p>進入網頁後，將剛剛回傳的資料貼在左方欄位內，點擊 Copy(綠色框) 將文字整理、檢查、轉碼並顯示於右側，為了方便觀察，點擊 tree(藍色框) 將其以樹狀結構來顯示。&lt;/p>
&lt;p>而且可以發現它有幫我們把原本看不懂的 Unicode編碼 轉換過來。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/udn_spider/json_editor.jpg" alt="JSON Editor Online" data-caption="JSON Editor Online" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
JSON Editor Online
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>新聞資料都放在 lists 底下，共有 20 篇，其每一篇所包含的欄位有&lt;code>url&lt;/code>、&lt;code>titleLink&lt;/code>、&lt;code>title&lt;/code>、&lt;code>paragraph&lt;/code>、&lt;code>time&lt;/code>、&lt;code>view&lt;/code>，代表意義如下表：&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/udn_spider/news_data.png" alt="單一則新聞資料" data-caption="單一則新聞資料" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='700px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:700px;height:;"/>
&lt;figcaption style="text-align: center;">
單一則新聞資料
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>參數&lt;/th>
&lt;th>代表意思&lt;/th>
&lt;th>格式&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>url&lt;/td>
&lt;td>圖片網址&lt;/td>
&lt;td>&lt;em>文字&lt;/em>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>titleLink&lt;/td>
&lt;td>新聞文章網址&lt;/td>
&lt;td>&lt;em>文字&lt;/em>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>title&lt;/td>
&lt;td>新聞標題&lt;/td>
&lt;td>&lt;em>文字&lt;/em>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>paragraph&lt;/td>
&lt;td>段落簡介&lt;/td>
&lt;td>&lt;em>文字&lt;/em>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>time&lt;/td>
&lt;td>日期時間&lt;/td>
&lt;td>&lt;em>文字&lt;/em>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>view&lt;/td>
&lt;td>閱覽數&lt;/td>
&lt;td>&lt;em>數字&lt;/em>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>好了！大致都知道了，來開始將想法轉換為程式吧~ 😙&lt;/p>
&lt;h3 id="爬取文章列表">爬取文章列表&lt;/h3>
&lt;p>* 為了簡化程式碼方便理解，像上次判斷請求是否成功的部份，這次將其省略。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">HEADERS&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;網頁載入失敗&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>來看一下前面動態載入的網址，&lt;br />
&lt;a href="https://udn.com/api/more?page=2&amp;amp;id=&amp;amp;channelId=1&amp;amp;cate_id=99&amp;amp;type=breaknews&amp;amp;totalRecNo=17749">https://udn.com/api/more?page=2&amp;amp;id=&amp;amp;channelId=1&amp;amp;cate_id=99&amp;amp;type=breaknews&amp;amp;totalRecNo=17749&lt;/a>&lt;br />
網址後方參數的部分有 &lt;code>page&lt;/code>、&lt;code>id&lt;/code>、&lt;code>channelId&lt;/code>、&lt;code>cate_id&lt;/code>、&lt;code>type&lt;/code>、&lt;code>totalRecNo&lt;/code> 六個，經過我的測試，只需要的 &lt;code>page&lt;/code>、&lt;code>channelId&lt;/code>、&lt;code>cate_id&lt;/code>、&lt;code>type&lt;/code> 四個即可取得一樣的資料。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/udn_spider/url.jpg" alt="動態載入的網址" data-caption="動態載入的網址" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='350px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:350px;height:;"/>
&lt;figcaption style="text-align: center;">
動態載入的網址
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>除了 &lt;code>page&lt;/code> 是頁數，其他的需要自行前往網站找尋&amp;quot;什麼類別、分類對應哪個編號&amp;quot;、&amp;quot;需要那些參數&amp;quot;。&lt;br />
像是：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>即時列表-不分類&lt;br />
&lt;code>channelId: 1&lt;/code>&lt;br />
&lt;code>cate_id: 99&lt;/code>&lt;br />
&lt;code>type: breaknews&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>即時列表-地方&lt;br />
&lt;code>channelId: 1&lt;/code>&lt;br />
&lt;code>cate_id: 3&lt;/code>&lt;br />
&lt;code>type: breaknews&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>運動-最新&lt;br />
&lt;code>channelId: 2&lt;/code>&lt;br />
&lt;code>type: cate_latest_news&lt;/code>&lt;br />
&lt;code>cate_id: 7227&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>運動-棒球&lt;br />
&lt;code>channelId: 2&lt;/code>&lt;br />
&lt;code>type: subcate_articles&lt;/code>&lt;br />
&lt;code>cate_id: 7227&lt;/code>&lt;br />
&lt;code>sub_id: 7001&lt;/code>&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>將網址與參數組合起來準備送出請求，頁數 &lt;code>page&lt;/code> 的部分可使用 &lt;code>for&lt;/code> 迴圈來歷遍。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_news_list&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">page_num&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;爬取新聞列表&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">base_url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;https://udn.com/api/more&amp;#34;&lt;/span>
&lt;span class="n">news_list&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">page&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">page_num&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="n">channelId&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>
&lt;span class="n">cate_id&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="n">type_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;breaknews&amp;#39;&lt;/span>
&lt;span class="n">query&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;page={page+1}&amp;amp;channelId={channelId}&amp;amp;cate_id={cate_id}&amp;amp;type={type_}&amp;#34;&lt;/span>
&lt;span class="n">news_list_url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">base_url&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="s1">&amp;#39;?&amp;#39;&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">query&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">news_list_url&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># ......&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">news_list&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>回傳資料是以 JSON 的格式，跟 HTML 相比很方便從中取出資料，也不要再使用 BeautifulSoup 解析，在 Python 類似 Dict 格式。&lt;br />
有兩種方式將其轉成 Dict：&lt;/p>
&lt;ol>
&lt;li>requests 提供的 &lt;code>r.json()&lt;/code> 解碼轉換&lt;/li>
&lt;li>一樣使用 &lt;code>r.text&lt;/code> 取出字串，再用 &lt;code>json.loads()&lt;/code> 將其轉換&lt;/li>
&lt;/ol>
&lt;p>這邊我就直接使用 requests 提供的 &lt;code>r.json()&lt;/code> 來轉換，最後將資料中 'lists' 抓出來 (也就是新聞資料)。&lt;/p>
&lt;p>一樣加上時間延遲 &lt;code>time.sleep()&lt;/code>，避免太頻繁的爬取，造成對方伺服器的負擔。&lt;br />
注意，這邊使用 &lt;a href="https://docs.python.org/3/library/random.html?highlight=uniform#random.uniform" target="_blank" rel="noopener">
random.uniform
&lt;/a> 來達到一段隨機範圍時間。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_news_list&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">page_num&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;爬取新聞列表&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">base_url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;https://udn.com/api/more&amp;#34;&lt;/span>
&lt;span class="n">news_list&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">page&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">page_num&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="c1"># ......&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">news_list_url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">HEADERS&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">news_data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">news_list&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extend&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">news_data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;lists&amp;#39;&lt;/span>&lt;span class="p">])&lt;/span>
&lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">random&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">uniform&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">))&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">news_list&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>執行結果如下：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">https&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="o">//&lt;/span>&lt;span class="n">udn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">com&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">api&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">more&lt;/span>&lt;span class="err">?&lt;/span>&lt;span class="n">page&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">channelId&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">cate_id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="nb">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">breaknews&lt;/span>
&lt;span class="n">https&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="o">//&lt;/span>&lt;span class="n">udn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">com&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">api&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">more&lt;/span>&lt;span class="err">?&lt;/span>&lt;span class="n">page&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">channelId&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">cate_id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="nb">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">breaknews&lt;/span>
&lt;span class="n">https&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="o">//&lt;/span>&lt;span class="n">udn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">com&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">api&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="n">more&lt;/span>&lt;span class="err">?&lt;/span>&lt;span class="n">page&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">channelId&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">cate_id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="nb">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">breaknews&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;url&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;https://pgw.udn.com.tw/gw/photo.php?u=https://p.udn.com.tw/upf/2017_news/noimg_cid7227_1.jpg&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;titleLink&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;/news/story/6999/4891968?from=udn-ch1_breaknews-1-0-news&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;title&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;MLB／永遠當巨人球迷 潘斯宣布退休&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;paragraph&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;兩度獲得世界大賽冠軍的外野手潘斯（Hunter Pence），今天透過社群平台宣布退休，結束14年的大聯盟旅程。&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;time&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;date&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;2020-09-27 09:32&amp;#39;&lt;/span>&lt;span class="p">},&lt;/span>
&lt;span class="s1">&amp;#39;view&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">27&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="err">共抓到&lt;/span> &lt;span class="mi">60&lt;/span> &lt;span class="err">篇新聞&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;!--adsense-->
&lt;h2 id="完整程式碼">完整程式碼&lt;/h2>
&lt;p>附上完整程式碼：&lt;a href="https://blog.jiatool.com/code/udn_spider.py" target="_blank" rel="noopener">
udn_spider.py
&lt;/a>&lt;br />
(對超連結右鍵 &amp;gt; 另存連結為)&lt;/p>
&lt;h2 id="延伸練習">延伸練習&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>試著抓取不同分類裡的新聞列表，例如：&amp;quot;即時列表-運動&amp;quot;、&amp;quot;數位-數位焦點&amp;quot;。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>如果想抓取文章內容全文，則需進入文章網址爬取，但這邊要注意的是其有幾種不同的網頁結構，需各別判斷並有不同的解析方式。例如：&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://udn.com/news/story/6904/4698001">https://udn.com/news/story/6904/4698001&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://udn.com/news/story/6809/4699983">https://udn.com/news/story/6809/4699983&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://udn.com/news/story/6809/4699958">https://udn.com/news/story/6809/4699958&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://udn.com/news/story/6812/4700330">https://udn.com/news/story/6812/4700330&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>我會陸續慢慢寫一些網站的&amp;quot;網路爬蟲實例&amp;quot;，如果你正好是剛開始想學爬蟲的新手、想知道某個網站如何爬取資料，又或遇到其他問題，歡迎過來參考和在底下留言ㄛ~😙&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="http://jsoneditoronline.org/" target="_blank" rel="noopener">
JSON Editor Online
&lt;/a>&lt;/p>
&lt;blockquote>
&lt;p>用你的微笑改變世界，&lt;br />
但別讓世界改變了你的微笑。&lt;/p>
&lt;p align="right">—— 劉軒&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/udn_spider.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><category>Python</category><category>網路爬蟲</category><category>Python網路爬蟲實例</category></item><item><title>[Python爬蟲實例] 巴哈姆特哈啦區</title><link>https://blog.jiatool.com/posts/gamer_spider/</link><pubDate>Sun, 13 Sep 2020 21:10:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sun, 20 Sep 2020 11:00:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/gamer_spider/</guid><description>前言 本篇主要一步步講解如何使用 Python 爬取巴哈姆特哈啦區的文章及回覆，最後也會附上完整程式碼供參考。 備註：此文僅教育學習，切勿用作商業用途，個人實</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>本篇主要一步步講解如何使用 Python 爬取巴哈姆特哈啦區的文章及回覆，最後也會附上完整程式碼供參考。&lt;/p>
&lt;p>備註：此文僅教育學習，切勿用作商業用途，個人實作皆屬個人行為，本作者不負任何法律責任&lt;/p>
&lt;h2 id="套件">套件&lt;/h2>
&lt;p>此次 Python 爬蟲主要使用到的套件有：&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Requests [&lt;a href="https://requests.readthedocs.io/en/master/" target="_blank" rel="noopener">
Doc
&lt;/a>] [&lt;a href="https://github.com/psf/requests" target="_blank" rel="noopener">
GitHub
&lt;/a>]&lt;/p>
&lt;/li>
&lt;li>
&lt;p>BeautifulSoup [&lt;a href="https://www.crummy.com/software/BeautifulSoup/bs4/doc/" target="_blank" rel="noopener">
Doc
&lt;/a>] [&lt;a href="https://code.launchpad.net/beautifulsoup" target="_blank" rel="noopener">
Source
&lt;/a>]&lt;/p>
&lt;/li>
&lt;/ul>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="流程">流程&lt;/h2>
&lt;p>先來講一下我們這次寫爬蟲想抓取的資料及流程，在 &lt;a href="https://forum.gamer.com.tw/" target="_blank" rel="noopener">
巴哈姆特哈啦區
&lt;/a> 中選擇一個看板，想抓取文章列表中的文章及回覆。&lt;/p>
&lt;p>一開始要先在文章列表中抓取每一篇文章的網址，再來進入文章網址中抓取每一樓層的回覆。&lt;br />
那因為這是 &lt;a href="https://blog.jiatool.com/series/%e7%88%ac%e8%9f%b2%e5%af%a6%e4%be%8b" target="_blank" rel="noopener">
本系列
&lt;/a> 第一篇文章，較複雜的部分先省略，在文章列表中只抓第一頁的文章就好，回覆底下的留言是採用動態載入(AJAX)的方式，本次也先跳過，等後續文章再講解。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_spider/description.jpg" alt="爬取說明" data-caption="爬取說明" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
爬取說明
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;h2 id="爬蟲程式">爬蟲程式&lt;/h2>
&lt;p>首先查看網站對於爬蟲的規範(&lt;a href="https://zh.wikipedia.org/wiki/Robots.txt" target="_blank" rel="noopener">
robots.txt
&lt;/a>)，&lt;br />
&lt;a href="https://forum.gamer.com.tw/robots.txt">https://forum.gamer.com.tw/robots.txt&lt;/a>&lt;br />
OK 它只有這兩個路徑不允許，跟我們爬取哈啦區文章沒有關係。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_spider/robots.png" alt="robots.txt" data-caption="robots.txt" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
robots.txt
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>有些有反爬蟲的網站，基本的方式就是偵測你送來 requests 的 header 中 User-Agent 欄位，因此我們就需要模仿一般瀏覽器送出去的資料。&lt;br />
先在上方定義 HEADERS 變數，待之後需要發出請求就帶入此數值。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">HEADERS&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;User-Agent&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s1">&amp;#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="爬取文章列表">爬取文章列表&lt;/h3>
&lt;p>對網站伺服器發出請求後，要確認回傳的結果，如果是正常成功的才繼續後續的處理。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_article_url_list&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">forum_url&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;爬取文章列表&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">forum_url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">HEADERS&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;網頁載入失敗&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;span class="c1"># ......&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>這邊就以&lt;a href="https://forum.gamer.com.tw/B.php?bsn=32407" target="_blank" rel="noopener">
荒野亂鬥板
&lt;/a>來示範。&lt;br />
打開瀏覽器的 &lt;strong>開發人員工具&lt;/strong> (F12 或 Ctrl + Shift + i) &amp;gt; &lt;strong>Elements(元素)&lt;/strong> 分頁，&lt;br />
當你指到程式碼時，它對應網頁區塊就會用顏色顯示，&lt;/p>
&lt;p>但這樣找太麻煩費時了，有個好用的功能，就是位在開發人員工具左上角的選擇工具，&lt;br />
點一下它後，就可以直接在網頁上點擊想要查看的區塊，Elements(元素)裡的程式碼也會自動跳到相應的地方。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_spider/select_tool.png" alt="開發人員工具 &amp;gt; 選擇工具" data-caption="開發人員工具 &amp;gt; 選擇工具" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
開發人員工具 &amp;gt; 選擇工具
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>先指到文章區塊，在右方可以看到在 &lt;code>&amp;lt;table class=&amp;quot;b-list&amp;quot;&amp;gt;&lt;/code> 裡的每一個 &lt;code>&amp;lt;tr class=&amp;quot;b-list__row b-list-item b-imglist-item&amp;quot;&amp;gt;&lt;/code> 對應每一篇文章區塊，因此CSS選擇器可以使用 &lt;code>table.b-list tr.b-list-item&lt;/code> 去選擇。&lt;br />
* 這部分還不太懂的人，可以參考我之前整理的文章：&lt;a href="https://blog.jiatool.com/posts/sorted-out-css-selector/" target="_blank" rel="noopener">
網頁CSS節點定位整理
&lt;/a>。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_spider/article_block.png" alt="開發人員工具 &amp;gt; Elements(元素) &amp;gt; 文章區塊" data-caption="開發人員工具 &amp;gt; Elements(元素) &amp;gt; 文章區塊" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
開發人員工具 &amp;gt; Elements(元素) &amp;gt; 文章區塊
&lt;/figcaption>
&lt;/figure>
&lt;p>我們這邊只需要抓取文章的網址，再往下找在 &lt;code>class=&amp;quot;b-list__main__title&amp;quot;&lt;/code> 元素中的 &lt;code>href&lt;/code> 參數後方發現前往文章頁面的網址。&lt;br />
不過取出來時還要要加上網域，才是完整的文章網址。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_spider/article_url.png" alt="開發人員工具 &amp;gt; Elements(元素) &amp;gt; 文章區塊 &amp;gt; 文章網址" data-caption="開發人員工具 &amp;gt; Elements(元素) &amp;gt; 文章區塊 &amp;gt; 文章網址" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='850px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:850px;height:;"/>
&lt;figcaption style="text-align: center;">
開發人員工具 &amp;gt; Elements(元素) &amp;gt; 文章區塊 &amp;gt; 文章網址
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_article_url_list&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">forum_url&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;爬取文章列表&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="c1"># ......&lt;/span>
&lt;span class="n">article_url_list&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;span class="n">soup&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">BeautifulSoup&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">features&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;lxml&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">item_blocks&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;table.b-list tr.b-list-item&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">item_block&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">item_blocks&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">title_block&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">item_block&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.b-list__main__title&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">article_url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;https://forum.gamer.com.tw/{title_block.get(&amp;#39;href&amp;#39;)}&amp;#34;&lt;/span>
&lt;span class="n">article_url_list&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">article_url&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">article_url_list&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>先來稍微觀察一下文章網址，&lt;br />
&lt;a href="https://forum.gamer.com.tw/C.php?bsn=60076&amp;amp;snA=3919777&amp;amp;tnum=429">https://forum.gamer.com.tw/C.php?bsn=60076&amp;amp;snA=3919777&amp;amp;tnum=429&lt;/a>&lt;br />
網址中後方的參數有&amp;quot;bsn&amp;quot;、&amp;quot;snA&amp;quot;、&amp;quot;tnum&amp;quot;，其分別代表：&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>參數&lt;/th>
&lt;th>代表意思&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>bsn&lt;/td>
&lt;td>板塊 ID&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>snA&lt;/td>
&lt;td>文章 ID&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>tnum&lt;/td>
&lt;td>文章內目前最新回覆的樓層數&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>(bPage)&lt;/td>
&lt;td>在文章列表中此文章是出現在第幾頁&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>題外話：&amp;quot;tnum&amp;quot;參數可有可無，能的話最好把它拿掉，這樣網址比較&amp;quot;乾淨&amp;quot;。&lt;/p>
&lt;h3 id="爬取文章資訊">爬取文章資訊&lt;/h3>
&lt;p>此函式會爬取文章標題、網址、樓層回覆，網址剛剛已經知道了，標題也很容易就抓出來。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_spider/article_title.png" alt="文章標題" data-caption="文章標題" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
文章標題
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_article_info&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">article_url&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;爬取文章資訊(包含回覆)&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">r&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">article_url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">headers&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">HEADERS&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">codes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ok&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;網頁載入失敗&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;span class="n">soup&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">BeautifulSoup&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">features&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;lxml&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">article_title&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;h1.c-post__header__title&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>
&lt;span class="c1"># ......&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>這邊的重點就是如何抓取樓層回覆，&lt;br />
我們嘗試點選不同頁數，會發現網址會有個 &lt;code>page&lt;/code> 參數用來跳頁，藉由如此，我們就可以前往每一頁。&lt;/p>
&lt;p>但，我們要先知道這篇文章總共有幾頁啊！&lt;br />
觀察一下，只要取得 &lt;code>&amp;lt;p class=&amp;quot;BH-pagebtnA&amp;quot;&amp;gt;&lt;/code> 內最後一個 &lt;code>&amp;lt;a&amp;gt;&lt;/code> 元素即可。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_spider/total_page.png" alt="文章回覆頁數" data-caption="文章回覆頁數" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
文章回覆頁數
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_article_total_page&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">soup&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;取得文章總頁數&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="n">article_total_page&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.BH-pagebtnA &amp;gt; a:last-of-type&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">article_total_page&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>知道總頁數後，就可以使用 &lt;code>for&lt;/code> 迴圈來歷遍每一頁。&lt;br />
組出網址字串，接著就是抓取每一層回覆(等等會講)，並合併成 Dict 格式回傳。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_article_info&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">article_url&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;爬取文章資訊(包含回覆)&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="c1"># ......&lt;/span>
&lt;span class="n">article_total_page&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_article_total_page&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">soup&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">reply_info_list&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">page&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">article_total_page&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="n">crawler_url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="s2">&amp;#34;{article_url}&amp;amp;page={page + 1}&amp;#34;&lt;/span>
&lt;span class="n">reply_list&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_reply_info_list&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">crawler_url&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">reply_info_list&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extend&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">reply_list&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sleep&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">article_info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="s1">&amp;#39;title&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">article_title&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;url&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">article_url&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s1">&amp;#39;reply&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">reply_info_list&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">article_info&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>* &lt;code>for&lt;/code> 迴圈中加入時間延遲 &lt;code>time.sleep(1)&lt;/code> ，避免太頻繁的爬取，造成對方伺服器的負擔。1秒可以換成 &lt;code>random.uniform(1, 3)&lt;/code>，來達到一段隨機範圍延遲，更避免被伺服器偵測為爬蟲。&lt;/p>
&lt;h3 id="爬取回覆資訊">爬取回覆資訊&lt;/h3>
&lt;p>爬取回覆的部分，從下圖的綠色方框能得知每一層回覆都是位於 &lt;code>&amp;lt;section class=&amp;quot;c-section&amp;quot; id=&amp;quot;post_43280297&amp;quot;&amp;gt;&lt;/code> 裡。&lt;br />
但有些比較特殊的樓層，像是下圖中&amp;quot;已刪除&amp;quot;或&amp;quot;已摺疊&amp;quot;的樓層，可以看到其 &lt;code>id&lt;/code> 會是 &lt;code>disable_&lt;/code> 開頭，&amp;quot;已刪除&amp;quot;的樓層我們可以略過，但&amp;quot;已摺疊&amp;quot;的樓層該怎麼抓呢？&lt;br />
別擔心，在往下看可以發現一樣有被摺疊起來樓層的資料，只是它被隱藏起來而已(&lt;code>style=&amp;quot;display:none&amp;quot;&lt;/code>)&lt;br />
如下圖指示，綠色代表一般正常樓層；藍色代表已折疊樓層；深紅色代表已刪除樓層。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_spider/delete_fold_reply.png" alt="已刪除&amp;amp;已摺疊的樓層" data-caption="已刪除&amp;amp;已摺疊的樓層" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
已刪除&amp;amp;已摺疊的樓層
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_reply_info_list&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;爬取回覆列表&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="c1"># ......&lt;/span>
&lt;span class="n">reply_info_list&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;span class="n">soup&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">BeautifulSoup&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">features&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;lxml&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">reply_blocks&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;section[id^=&amp;#34;post_&amp;#34;]&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">reply_block&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">reply_blocks&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="c1"># ......&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">reply_info_list&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>接下來就是各別抓取需要的部分了，&lt;br />
例如&amp;quot;回覆樓層&amp;quot;雖然網頁上只顯示&lt;strong>樓主&lt;/strong>，看不到樓層的數字，但從網頁原始碼中能發現，此元素中 &lt;code>data-floor&lt;/code> 欄位裡有我們想要的樓層數字。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_spider/reply_floor.png" alt="回覆 樓層欄位" data-caption="回覆 樓層欄位" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='900px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:900px;height:;"/>
&lt;figcaption style="text-align: center;">
回覆 樓層欄位
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>又或者想抓取&amp;quot;發文時間&amp;quot;，但如果有編輯過的回覆，它網頁上顯示著是&amp;quot;編輯時間&amp;quot;，這時從網頁原始碼中也能發現，元素裏頭有 &lt;code>data-mtime&lt;/code> 欄位記錄著發文時間。&lt;br />
但抓下來的資料是文字格式(字串)的，最好轉成 datetime 格式方便後續的判斷、處理。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_spider/reply_time.png" alt="回覆 發文時間欄位" data-caption="回覆 發文時間欄位" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='800px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:800px;height:;"/>
&lt;figcaption style="text-align: center;">
回覆 發文時間欄位
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;p>而&amp;quot;推&amp;quot;、&amp;quot;噓&amp;quot;也要注意例外，當&amp;quot;推&amp;quot;超過 1000 時會顯示&amp;quot;爆&amp;quot;；當&amp;quot;噓&amp;quot;超過 500 時會顯示&amp;quot;X&amp;quot;、等於 0 會顯示&amp;quot;-&amp;quot;。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_reply_info_list&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;爬取回覆列表&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;span class="c1"># ......&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">reply_block&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">reply_blocks&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">reply_info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;span class="n">reply_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;floor&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">reply_block&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.floor&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;data-floor&amp;#39;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;span class="n">reply_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;user_name&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">reply_block&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.username&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>
&lt;span class="n">reply_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;user_id&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">reply_block&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.userid&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>
&lt;span class="n">publish_time&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">reply_block&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.edittime&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;data-mtime&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">reply_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;publish_time&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strptime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">publish_time&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;%Y-%m-&lt;/span>&lt;span class="si">%d&lt;/span>&lt;span class="s1"> %H:%M:%S&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">reply_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;content&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">reply_block&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.c-article__content&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>
&lt;span class="n">gp_count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">reply_block&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.postgp span&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">gp_count&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;-&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">gp_count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="k">elif&lt;/span> &lt;span class="n">gp_count&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;爆&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">gp_count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1000&lt;/span>
&lt;span class="n">reply_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;gp_count&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">gp_count&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">bp_count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">reply_block&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.postbp span&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="n">bp_count&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;-&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">bp_count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>
&lt;span class="k">elif&lt;/span> &lt;span class="n">bp_count&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;X&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">bp_count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">500&lt;/span>
&lt;span class="n">reply_info&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;bp_count&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">bp_count&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 從命名應該可以知道分別代表什麼資料，這邊我就不細說了&lt;/span>
&lt;span class="n">reply_info_list&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">reply_info&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">reply_info_list&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="完整程式碼">完整程式碼&lt;/h2>
&lt;p>附上完整程式碼：&lt;a href="https://blog.jiatool.com/code/gamer_spider.py" target="_blank" rel="noopener">
gamer_spider.py
&lt;/a>&lt;br />
(對超連結右鍵 &amp;gt; 另存連結為)&lt;/p>
&lt;h2 id="延伸練習">延伸練習&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>在本篇教學中只爬取第一頁的文章，該如何自動爬取前五頁的文章呢？&lt;br />
提示：參考爬取每一頁回覆的方式&lt;/p>
&lt;/li>
&lt;li>
&lt;p>為了簡單，本篇教學中並沒有爬取樓層回覆底下的留言，這部分有沒有什麼辦法可以做到？&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer_spider/message.png" alt="樓層回覆底下的留言" data-caption="樓層回覆底下的留言" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='550px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:550px;height:;"/>
&lt;figcaption style="text-align: center;">
樓層回覆底下的留言
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;/li>
&lt;/ol>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>有些機制這邊沒有寫出來，像是當網頁請求失敗該做什麼處理，將字串轉換為日期時間格式時(或將字串轉換為整數)時，需要加上 try-except 去捕抓錯誤等等。&lt;/p>
&lt;p>之後我會慢慢陸續寫一些網站的&amp;quot;網路爬蟲實例&amp;quot;，如果你正好是剛開始想學爬蟲的新手，或者是不知道某個網站如何爬取資料，都很歡迎過來參考ㄛ~&lt;/p>
&lt;p>有想推薦的網站，或遇到其他問題，也歡迎再底下留言。😙&lt;/p>
&lt;br/>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://blog.jiatool.com/posts/sorted-out-css-selector/" target="_blank" rel="noopener">
網頁CSS節點定位整理
&lt;/a>&lt;/p>
&lt;blockquote>
&lt;p>又不是所有的答案都必須完美，失敗和錯誤也是生命的養分。&lt;/p>
&lt;p align="right">—— Peter Su&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/gamer_spider.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><category>Python</category><category>巴哈姆特</category><category>網路爬蟲</category><category>Python網路爬蟲實例</category></item><item><title>Python 使用 Arrow 套件來處理日期時間</title><link>https://blog.jiatool.com/posts/arrow/</link><pubDate>Sun, 26 Jul 2020 13:35:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sun, 26 Jul 2020 13:35:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/arrow/</guid><description>前言 在寫網路爬蟲時，應該都會遇到需要解析日期時間的處理，但是Python內建有關日期時間的套件用久了覺得有點卡手，像是有以下缺點： 太多套件(</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>在寫網路爬蟲時，應該都會遇到需要解析日期時間的處理，但是Python內建有關日期時間的套件用久了覺得有點卡手，像是有以下缺點：&lt;/p>
&lt;ul>
&lt;li>太多套件(time、datetime、calendar、dateutil、pytz等)。&lt;/li>
&lt;li>有時需要在不同格式之間轉換，不是這麼的方便或繁瑣，例如時間格式、字串、時間戳、localtime和utctime、時區。&lt;/li>
&lt;li>在某些方面較不直觀或難記，像是格式化字串的參數。&lt;/li>
&lt;/ul>
&lt;br/>
&lt;p>在某天碰巧在網路的論壇中發現有人推薦 Arrow，看了一下，好像蠻不錯用的。&lt;/p>
&lt;p>例如我們想把某日期時間字串加上5小時，再轉回字串的話，使用內建的&lt;strong>datetime&lt;/strong>與&lt;strong>Arrow&lt;/strong>來比較：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="c1"># 使用內建的datetime&lt;/span>
&lt;span class="kn">from&lt;/span> &lt;span class="nn">datetime&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">timedelta&lt;/span>
&lt;span class="n">t&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strptime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;2020-07-25 10:00&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;%Y-%m-&lt;/span>&lt;span class="si">%d&lt;/span>&lt;span class="s2"> %H:%M&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">t&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">timedelta&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">hours&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strftime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;%Y-%m-&lt;/span>&lt;span class="si">%d&lt;/span>&lt;span class="s2"> %H:%M&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 2020-07-25 15:00&lt;/span>
&lt;span class="c1"># 使用Arrow&lt;/span>
&lt;span class="kn">import&lt;/span> &lt;span class="nn">arrow&lt;/span>
&lt;span class="n">t&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;2020-07-25 10:00&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">t&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shift&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">hours&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">format&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;YYYY-MM-DD HH:mm&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 2020-07-25 15:00&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="安裝">安裝&lt;/h2>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Shell" data-lang="Shell">pip install arrow
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>以下以撰寫文章時最新的版本 v0.15.7 為範例。&lt;br />
&lt;a href="https://github.com/crsmithdev/arrow" target="_blank" rel="noopener">
Arrow 官方GitHub
&lt;/a>&lt;br />
&lt;a href="https://arrow.readthedocs.io/" target="_blank" rel="noopener">
Arrow 官方文件
&lt;/a>&lt;/p>
&lt;h2 id="功能範例">功能範例&lt;/h2>
&lt;h4 id="創建時間">創建時間&lt;/h4>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="c1"># 當前時間&lt;/span>
&lt;span class="n">t&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">now&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="c1"># 2020-07-25T22:12:08.803133+08:00&lt;/span>
&lt;span class="c1"># 當前UTC時間&lt;/span>
&lt;span class="n">t&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">utcnow&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="c1"># 2020-07-25T14:12:08.803133+00:00&lt;/span>
&lt;span class="c1"># 自訂時間&lt;/span>
&lt;span class="n">t&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Arrow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2020&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">7&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">25&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">21&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">50&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">45&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 2020-07-25T21:50:45+00:00&lt;/span>
&lt;span class="c1"># 取得其中的數值&lt;/span>
&lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">year&lt;/span>
&lt;span class="c1"># 2020&lt;/span>
&lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">hour&lt;/span>
&lt;span class="c1"># 21&lt;/span>
&lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">timestamp&lt;/span> &lt;span class="c1"># 時間戳&lt;/span>
&lt;span class="c1"># 1594504245&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="格式化成字串-format">格式化成字串 [format]&lt;/h4>
&lt;p>&lt;a href="#%e8%a7%a3%e6%9e%90%e5%92%8c%e6%a0%bc%e5%bc%8f%e5%8c%96-%e5%8f%83%e6%95%b8" target="_blank" rel="noopener">
格式化參數
&lt;/a>放置於文章最後。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">format&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;YYYY/MM/DD HH:mm:ss&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 2020/07/25 21:50:45&lt;/span>
&lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">format&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;MMM DD dddd&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># Jul 25 Saturday&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="轉換為-datetime-函數中的-datetimedatetime">轉換為 datetime 函數中的 [datetime、date、time]&lt;/h4>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">t&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Arrow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2020&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">7&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">25&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">21&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">50&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">45&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;class &amp;#39;arrow.arrow.Arrow&amp;#39;&amp;gt; 2020-07-25T21:50:45+00:00&lt;/span>
&lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">datetime&lt;/span>
&lt;span class="c1"># &amp;lt;class &amp;#39;datetime.datetime&amp;#39;&amp;gt; 2020-07-25 21:50:45+00:00&lt;/span>
&lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">date&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="c1"># &amp;lt;class &amp;#39;datetime.date&amp;#39;&amp;gt; 2020-07-25&lt;/span>
&lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="c1"># &amp;lt;class &amp;#39;datetime.time&amp;#39;&amp;gt; 21:50:45&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="移動時間-shift">移動時間 [shift]&lt;/h4>
&lt;p>參數有 years, months, days, hours, minutes, seconds, microseconds, weeks, quarters, weekday。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">t&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Arrow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2020&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">7&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">25&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">21&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">50&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">45&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 3天前&lt;/span>
&lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shift&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">days&lt;/span>&lt;span class="o">=-&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 2020-07-22T21:50:45+00:00&lt;/span>
&lt;span class="c1"># 50天又2小時後&lt;/span>
&lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shift&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">days&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">50&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">hours&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 2020-09-13T23:50:45+00:00&lt;/span>
&lt;span class="c1"># 上星期&lt;/span>
&lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shift&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">weeks&lt;/span>&lt;span class="o">=-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 2020-07-18T21:50:45+00:00&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="修改日期-replace">修改日期 [replace]&lt;/h4>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">t&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Arrow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2020&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">7&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">25&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">21&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">50&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">45&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">replace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">year&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">2025&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">month&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">12&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">day&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">31&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 2025-12-31T21:50:45+00:00&lt;/span>
&lt;span class="c1"># 替換時區&lt;/span>
&lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">replace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tzinfo&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;Asia/Taipei&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 2020-07-25T21:50:45+08:00&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="轉換時區-to">轉換時區 [to]&lt;/h4>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">t&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Arrow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2020&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">7&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">25&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">20&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mo">00&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mo">00&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 2020-07-25T20:00:00+00:00&lt;/span>
&lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">to&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;Asia/Taipei&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 2020-07-26T04:00:00+08:00&lt;/span>
&lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">to&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;local&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 2020-07-26T04:00:00+08:00&lt;/span>
&lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">to&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;utc&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 2020-07-25T20:00:00+00:00&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="從不同的格式轉換為arrow格式-get">從不同的格式轉換為Arrow格式 [get]&lt;/h4>
&lt;p>他還可以自動判斷！&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;2020/10/09 16:15:14&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 2020-10-09T16:15:14+00:00&lt;/span>
&lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;2020-07-30T01:26:43.8&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 2020-07-30T01:26:43.800000+00:00&lt;/span>
&lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">datetime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2020&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">7&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">25&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">30&lt;/span>&lt;span class="p">))&lt;/span>
&lt;span class="c1"># 2020-07-25T10:10:30+00:00&lt;/span>
&lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">date&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2020&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">7&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">25&lt;/span>&lt;span class="p">))&lt;/span>
&lt;span class="c1"># 2020-07-25T00:00:00+00:00&lt;/span>
&lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2020&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">7&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">25&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">12&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">30&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">45&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 2020-07-25T12:30:45+00:00&lt;/span>
&lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;2020-07-25 11:30&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;YYYY-MM-DD HH:mm&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 2020-07-25T11:30:00+00:00&lt;/span>
&lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1595651445&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 2020-07-25T04:30:45+00:00&lt;/span>
&lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;1595651445&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;X&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 2020-07-25T04:30:45+00:00&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="產生一段範圍-range-span">產生一段範圍 [range span]&lt;/h4>
&lt;p>range：時間範圍內依某級別(hour)產生時間點&lt;br />
span：初始與結尾時間點&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">start&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Arrow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2020&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">7&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">25&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">11&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">50&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">end&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Arrow&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2020&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">7&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">25&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">13&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">50&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;hour&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">start&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">end&lt;/span>&lt;span class="p">):&lt;/span>
&lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">t&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 2020-07-25T11:50:00+00:00&lt;/span>
&lt;span class="c1"># 2020-07-25T12:50:00+00:00&lt;/span>
&lt;span class="c1"># 2020-07-25T13:50:00+00:00&lt;/span>
&lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">now&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">span&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;hour&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># (&amp;lt;Arrow [2020-07-25T11:00:00+08:00]&amp;gt;, &amp;lt;Arrow [2020-07-25T11:59:59.999999+08:00]&amp;gt;)&lt;/span>
&lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">now&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">span&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;hour&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">count&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># (&amp;lt;Arrow [2020-07-25T11:00:00+08:00]&amp;gt;, &amp;lt;Arrow [2020-07-25T12:59:59.999999+08:00]&amp;gt;)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="人性化敘述方式呈現-humanize">人性化(敘述)方式呈現 [humanize]&lt;/h4>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="n">arw&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">now&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shift&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">hours&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">arw&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">humanize&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="c1"># in an hour&lt;/span>
&lt;span class="n">arw&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">now&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shift&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">hours&lt;/span>&lt;span class="o">=-&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">arw&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">humanize&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="c1"># 2 hours ago&lt;/span>
&lt;span class="c1"># 也可以用中文顯示哦！！&lt;/span>
&lt;span class="c1"># https://github.com/crsmithdev/arrow/blob/master/arrow/locales.py&lt;/span>
&lt;span class="n">arw&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">humanize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">locale&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;zh_tw&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 2小時前&lt;/span>
&lt;span class="c1"># 指定要顯示的級別&lt;/span>
&lt;span class="n">arw&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">utcnow&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shift&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">seconds&lt;/span>&lt;span class="o">=+&lt;/span>&lt;span class="mi">8400&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">arw&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">humanize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">granularity&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;minute&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">locale&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;zh_tw&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 140分鐘後&lt;/span>
&lt;span class="n">arw&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">humanize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">granularity&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;hour&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;minute&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="n">locale&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;zh_tw&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 2小時 和 20分鐘後&lt;/span>
&lt;span class="c1"># 也可以拿兩個時間來比對&lt;/span>
&lt;span class="n">a&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">now&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">arrow&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">now&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">shift&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">weeks&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">a&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">humanize&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">locale&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;zh_tw&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 1週前&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="解析和格式化-參數">解析和格式化 參數&lt;/h4>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>說明&lt;/th>
&lt;th>語法&lt;/th>
&lt;th>結果&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Year 年&lt;/td>
&lt;td>YYYY&lt;/td>
&lt;td>2000, 2001, 2002 &amp;hellip; 2012, 2013&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>YY&lt;/td>
&lt;td>00, 01, 02 &amp;hellip; 12, 13&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Month 月&lt;/td>
&lt;td>MMMM&lt;/td>
&lt;td>January, February, March &amp;hellip;&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>MMM&lt;/td>
&lt;td>Jan, Feb, Mar &amp;hellip;&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>MM&lt;/td>
&lt;td>01, 02, 03 &amp;hellip; 11, 12&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>M&lt;/td>
&lt;td>1, 2, 3 &amp;hellip; 11, 12&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Day of Year 一年中的天數&lt;/td>
&lt;td>DDDD&lt;/td>
&lt;td>001, 002, 003 &amp;hellip; 364, 365&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>DDD&lt;/td>
&lt;td>1, 2, 3 … 364, 365&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Day of Month 一個月中的天數&lt;/td>
&lt;td>DD&lt;/td>
&lt;td>01, 02, 03 &amp;hellip; 30, 31&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>D&lt;/td>
&lt;td>1, 2, 3 &amp;hellip; 30, 31&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>Do&lt;/td>
&lt;td>1st, 2nd, 3rd &amp;hellip; 30th, 31st&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Day of Week 一週中的天數&lt;/td>
&lt;td>dddd&lt;/td>
&lt;td>Monday, Tuesday, Wednesday &amp;hellip;&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>ddd&lt;/td>
&lt;td>Mon, Tue, Wed &amp;hellip;&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>d&lt;/td>
&lt;td>1, 2, 3 &amp;hellip; 6, 7&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Hour 小時&lt;/td>
&lt;td>HH&lt;/td>
&lt;td>00, 01, 02 &amp;hellip; 23, 24&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>H&lt;/td>
&lt;td>0, 1, 2 &amp;hellip; 23, 24&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>hh&lt;/td>
&lt;td>01, 02, 03 &amp;hellip; 11, 12&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>h&lt;/td>
&lt;td>1, 2, 3 &amp;hellip; 11, 12&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>AM / PM&lt;/td>
&lt;td>A&lt;/td>
&lt;td>AM, PM, am, pm&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>a&lt;/td>
&lt;td>am, pm&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Minute 分鐘&lt;/td>
&lt;td>mm&lt;/td>
&lt;td>00, 01, 02 &amp;hellip; 58, 59&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>m&lt;/td>
&lt;td>0, 1, 2 &amp;hellip; 58, 59&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Second 秒&lt;/td>
&lt;td>ss&lt;/td>
&lt;td>00, 01, 02 &amp;hellip; 58, 59&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>s&lt;/td>
&lt;td>0, 1, 2 &amp;hellip; 58, 59&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Sub-second&lt;/td>
&lt;td>S&lt;/td>
&lt;td>0, 02, 003, 000006, 123123123123&amp;hellip;&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Timezone 時區&lt;/td>
&lt;td>ZZZ&lt;/td>
&lt;td>Asia/Taipei, Europe/Warsaw, GMT &amp;hellip;&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>ZZ&lt;/td>
&lt;td>-08:00, -07:00 &amp;hellip; +07:00, +08:00&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>&lt;/td>
&lt;td>Z&lt;/td>
&lt;td>-0800, -0700 &amp;hellip; +0700, +0800&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Seconds Timestamp 時間戳&lt;/td>
&lt;td>X&lt;/td>
&lt;td>1381685817, 1381685817.915482&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>ms or µs Timestamp 時間戳&lt;/td>
&lt;td>x&lt;/td>
&lt;td>1569980330813, 1569980330813221&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;h2 id="結語">結語&lt;/h2>
&lt;p>其他更進階的語法可以前往&lt;a href="https://arrow.readthedocs.io/" target="_blank" rel="noopener">
Arrow 官方文件
&lt;/a>查閱~&lt;/p>
&lt;p>相比Python內建的日期時間套件，用起來應該清楚、好用吧。&lt;br />
只是缺點是使用前要先安裝。&lt;/p>
&lt;br/>
&lt;br/>
&lt;br/>
&lt;p>如有遇到其他問題，或文章內容有誤，歡迎底下留言~😙&lt;/p>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://github.com/crsmithdev/arrow" target="_blank" rel="noopener">
Arrow 官方GitHub
&lt;/a>&lt;br />
&lt;a href="https://arrow.readthedocs.io/" target="_blank" rel="noopener">
Arrow 官方文件
&lt;/a>&lt;/p>
&lt;blockquote>
&lt;p>當你認為全世界都在跟你做對時，&lt;br />
請記得 飛機是逆風而飛的。&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/arrow.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><category>Python</category><category>套件</category><category>分享</category><category>Python套件</category></item><item><title>常用網頁 CSS Selector (選擇器)取得元素，搭配 Python BeautifulSoup 套件</title><link>https://blog.jiatool.com/posts/sorted-out-css-selector/</link><pubDate>Fri, 12 Jun 2020 22:29:06 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sun, 17 Mar 2024 08:25:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/sorted-out-css-selector/</guid><description>(2021/10/03 新增) 瀏覽器使用 CSS Selectors 搜尋教學。 最近開始接觸網路爬蟲，因此順便把一些常用網頁取得元素(element)的 CSS Selectors 方式整理一下，第一部分是純 CSS</description><content:encoded>&lt;p>(2021/10/03 新增) 瀏覽器使用 CSS Selectors 搜尋教學。&lt;/p>
&lt;p>最近開始接觸網路爬蟲，因此順便把一些常用網頁取得元素(element)的 CSS Selectors 方式整理一下，第一部分是純 CSS，第二部分則是 Python 搭配 BeautifulSoup 套件。&lt;/p>
&lt;p>喜歡網路爬蟲也歡迎觀看 &lt;a href="https://blog.jiatool.com/series/Python%e7%b6%b2%e8%b7%af%e7%88%ac%e8%9f%b2%e5%af%a6%e4%be%8b/" target="_blank" rel="noopener">
Python網路爬蟲實例
&lt;/a> 系列文章~&lt;/p>
&lt;br/>
&lt;!--adsense-->
&lt;h2 id="純css">純CSS&lt;/h2>
&lt;p>先上表格，後面還有範例。&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>說明&lt;/th>
&lt;th>語法&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>tag 定位&lt;/td>
&lt;td>span font&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>id 定位&lt;/td>
&lt;td>#ID&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>class 定位&lt;/td>
&lt;td>.CLASS&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>排除&lt;/td>
&lt;td>:not()&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>屬性值&lt;/td>
&lt;td>[name=&amp;quot;NAME&amp;quot;]&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>屬性值(不等於)&lt;/td>
&lt;td>[name!=&amp;quot;NAME&amp;quot;]&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>屬性值包含&lt;/td>
&lt;td>[title*=&amp;quot;TITLE&amp;quot;]&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>屬性值開頭&lt;/td>
&lt;td>[title^=&amp;quot;start&amp;quot;]&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>屬性值結尾&lt;/td>
&lt;td>[title$=&amp;quot;end&amp;quot;]&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>第 1 個子元素 (全部)&lt;/td>
&lt;td>ul li:first-child&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>最後 1 個子元素 (全部)&lt;/td>
&lt;td>ul li:last-child&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>第 2 個子元素 (全部)&lt;/td>
&lt;td>ul li:nth-child(2)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>倒數第 2 個子元素 (全部)&lt;/td>
&lt;td>ul li:nth-last-child(2)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>第 1 個子元素 (指定)&lt;/td>
&lt;td>ul li:first-of-type&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>最後 1 個子元素 (指定)&lt;/td>
&lt;td>ul li:last-of-type&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>第 2 個子元素 (指定)&lt;/td>
&lt;td>ul li:nth-of-type(2)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>倒數第 2 個子元素 (指定)&lt;/td>
&lt;td>ul li:nth-last-of-type(2)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>第奇數個子元素 (指定)&lt;/td>
&lt;td>ul li:nth-of-type(odd)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>第偶數個子元素 (指定)&lt;/td>
&lt;td>ul li:nth-of-type(even)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>第 3 的倍數個子元素 (指定)&lt;/td>
&lt;td>ul li:nth-of-type(3n)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>第 3 的倍數+1個子元素 (指定)&lt;/td>
&lt;td>ul li:nth-of-type(3n+1)&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>同一層往後尋找元素&lt;/td>
&lt;td>#ID ~ i&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>同一層的&amp;quot;下一個&amp;quot;元素&lt;/td>
&lt;td>#ID + *&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>同時尋找多種選擇器&lt;/td>
&lt;td>#id1 , #id2&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;div class="expand">
&lt;button type="button" class="expand__button" aria-label="Expand Button">
&lt;span class="expand-icon expand-icon__right">
&lt;svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">&lt;path fill="currentColor" d="M9.29 15.88L13.17 12 9.29 8.12c-.39-.39-.39-1.02 0-1.41.39-.39 1.02-.39 1.41 0l4.59 4.59c.39.39.39 1.02 0 1.41L10.7 17.3c-.39.39-1.02.39-1.41 0-.38-.39-.39-1.03 0-1.42z"/>&lt;/svg>
&lt;/span>
以下程式碼省略
&lt;/button>
&lt;div class="expand__content">
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="kn">import&lt;/span> &lt;span class="nn">re&lt;/span>
&lt;span class="kn">from&lt;/span> &lt;span class="nn">bs4&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">BeautifulSoup&lt;/span>
&lt;span class="n">soup&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">BeautifulSoup&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">html&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;html.parser&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;br/>
&lt;h3 id="標籤定位tagidclass">標籤定位(tag、id、class)&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-HTML" data-lang="HTML">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">html&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">span&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&amp;lt;&lt;/span>&lt;span class="nt">font&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>001&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">font&lt;/span>&lt;span class="p">&amp;gt;&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">font&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>002&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">font&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">span&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;ID&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>003&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;CLASS CLASS2&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>004&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">i&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;NAME&amp;#34;&lt;/span> &lt;span class="na">style&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;STYLE&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>005&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">i&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">i&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;NAME2&amp;#34;&lt;/span> &lt;span class="na">style&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;STYLE&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>006&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">i&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">title&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;TITLE&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>007&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">title&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;start-TITLE&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>008&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">title&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;TITLE-end&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>009&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">html&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="c1"># tag定位：&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;span font&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;font&amp;gt;001&amp;lt;/font&amp;gt;&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;span &amp;gt; font&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;font&amp;gt;002&amp;lt;/font&amp;gt;&lt;/span>
&lt;span class="c1"># id定位：&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;#ID&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;div#ID&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;div id=&amp;#34;ID&amp;#34;&amp;gt;003&amp;lt;/div&amp;gt;&lt;/span>
&lt;span class="c1"># class定位：&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;.CLASS&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;div.CLASS&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;div.CLASS.CLASS2&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;div class=&amp;#34;CLASS CLASS2&amp;#34;&amp;gt;004&amp;lt;/div&amp;gt;&lt;/span>
&lt;span class="c1"># 同時尋找多種選擇器&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;#ID , .CLASS&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># [&amp;lt;div id=&amp;#34;ID&amp;#34;&amp;gt;003&amp;lt;/div&amp;gt;, &amp;lt;div class=&amp;#34;CLASS CLASS2&amp;#34;&amp;gt;004&amp;lt;/div&amp;gt;]&lt;/span>
&lt;span class="c1"># 排除&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;div:not(#ID):not(.CLASS)&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># [&amp;lt;div&amp;gt;&amp;lt;font&amp;gt;001&amp;lt;/font&amp;gt;&amp;lt;/div&amp;gt;, &amp;lt;div title=&amp;#34;TITLE&amp;#34;&amp;gt;007&amp;lt;/div&amp;gt;, &amp;lt;div title=&amp;#34;start-TITLE&amp;#34;&amp;gt;008&amp;lt;/div&amp;gt;, &amp;lt;div title=&amp;#34;TITLE-end&amp;#34;&amp;gt;009&amp;lt;/div&amp;gt;]&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="元素屬性">元素屬性&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="c1"># 元素有某屬性：&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;i[name]&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;i name=&amp;#34;NAME&amp;#34; style=&amp;#34;STYLE&amp;#34;&amp;gt;005&amp;lt;/i&amp;gt;&lt;/span>
&lt;span class="c1"># 屬性值：&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;i[name=&amp;#34;NAME&amp;#34;]&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;i[name=&amp;#34;NAME&amp;#34;][style=&amp;#34;STYLE&amp;#34;]&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;i name=&amp;#34;NAME&amp;#34; style=&amp;#34;STYLE&amp;#34;&amp;gt;005&amp;lt;/i&amp;gt;&lt;/span>
&lt;span class="c1"># 屬性值不等於：&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;i[name!=&amp;#34;NAME&amp;#34;]&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;i name=&amp;#34;NAME2&amp;#34; style=&amp;#34;STYLE&amp;#34;&amp;gt;006&amp;lt;/i&amp;gt;&lt;/span>
&lt;span class="c1"># 屬性值包含某字串：&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;div[title*=&amp;#34;TITLE&amp;#34;]&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;div title=&amp;#34;TITLE&amp;#34;&amp;gt;007&amp;lt;/div&amp;gt;&lt;/span>
&lt;span class="c1"># 屬性值以某字串開頭：&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;div[title^=&amp;#34;start&amp;#34;]&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;div title=&amp;#34;start-TITLE&amp;#34;&amp;gt;008&amp;lt;/div&amp;gt;&lt;/span>
&lt;span class="c1"># 屬性值以某字串結尾：&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;div[title$=&amp;#34;end&amp;#34;]&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;div title=&amp;#34;TITLE-end&amp;#34;&amp;gt;009&amp;lt;/div&amp;gt;&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="子元素">子元素&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-HTML" data-lang="HTML">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">html&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;list&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">p&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>101&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">p&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">p&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>102&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">p&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">span&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>201&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">span&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">span&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>202&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">span&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">span&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>203&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">span&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">p&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>103&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">p&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">span&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>204&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">span&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">p&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>104&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">p&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">html&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="c1"># -child&lt;/span>
&lt;span class="c1"># 第1個、最後1個 子元素：&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;ul#list li:first-child&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;ul#list li:last-child&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;li&amp;gt;1001&amp;lt;/li&amp;gt;&lt;/span>
&lt;span class="c1"># &amp;lt;li&amp;gt;1004&amp;lt;/li&amp;gt;&lt;/span>
&lt;span class="c1"># 第2個、倒數第2個 子元素：&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;ul#list li:nth-child(2)&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;ul#list li:nth-last-child(2)&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;p&amp;gt;102&amp;lt;/p&amp;gt;&lt;/span>
&lt;span class="c1"># None&lt;/span>
&lt;span class="c1"># 注意：倒數第2個元素不是&amp;#34;p&amp;#34;，因此找不到&lt;/span>
&lt;span class="c1"># -of-type&lt;/span>
&lt;span class="c1"># 第1個、最後1個 子元素：&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;#list p:first-of-type&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;#list p:last-of-type&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;p&amp;gt;101&amp;lt;/p&amp;gt;&lt;/span>
&lt;span class="c1"># &amp;lt;p&amp;gt;104&amp;lt;/p&amp;gt;&lt;/span>
&lt;span class="c1"># 第2個、倒數第2個 子元素：&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;#list p:nth-of-type(2)&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;#list p:nth-last-of-type(2)&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;p&amp;gt;102&amp;lt;/p&amp;gt;&lt;/span>
&lt;span class="c1"># &amp;lt;p&amp;gt;103&amp;lt;/p&amp;gt;&lt;/span>
&lt;span class="c1"># 以上兩種很像，他們的差別是：&lt;/span>
&lt;span class="c1"># nth-child 會把全部的元素加進去算；nth-of-type 只會針對你指定的元素去算。&lt;/span>
&lt;span class="c1"># 偶數、奇數 位置元素&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;#list p:nth-of-type(odd)&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;#list p:nth-of-type(even)&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># [&amp;lt;p&amp;gt;101&amp;lt;/p&amp;gt;, &amp;lt;p&amp;gt;103&amp;lt;/p&amp;gt;]&lt;/span>
&lt;span class="c1"># [&amp;lt;p&amp;gt;102&amp;lt;/p&amp;gt;, &amp;lt;p&amp;gt;104&amp;lt;/p&amp;gt;]&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="同一層元素">同一層元素&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-HTML" data-lang="HTML">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">html&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;ID&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>301&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;CLASS CLASS2&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>302&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">i&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;NAME&amp;#34;&lt;/span> &lt;span class="na">style&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;STYLE&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>303&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">i&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">i&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;NAME2&amp;#34;&lt;/span> &lt;span class="na">style&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;STYLE&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>304&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">i&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">html&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="c1"># 在同一層往後尋找元素&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;#ID ~ i&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;i name=&amp;#34;NAME&amp;#34; style=&amp;#34;STYLE&amp;#34;&amp;gt;303&amp;lt;/i&amp;gt;&lt;/span>
&lt;span class="c1"># 在同一層的&amp;#34;下一個&amp;#34;元素&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;#ID + *&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;div class=&amp;#34;CLASS CLASS2&amp;#34;&amp;gt;302&amp;lt;/div&amp;gt;&lt;/span>
&lt;span class="c1"># 在同一層，往後尋找&amp;#34;下一個&amp;#34;元素&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;#ID + div&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;div class=&amp;#34;CLASS CLASS2&amp;#34;&amp;gt;302&amp;lt;/div&amp;gt;&lt;/span>
&lt;span class="c1"># 在同一層，往後尋找中間跳過一個元素的&amp;#34;下一個&amp;#34;元素&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;#ID + * + i&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;i name=&amp;#34;NAME&amp;#34; style=&amp;#34;STYLE&amp;#34;&amp;gt;303&amp;lt;/i&amp;gt;&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h2 id="搭配-beautifulsoup-套件">搭配 BeautifulSoup 套件&lt;/h2>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-HTML" data-lang="HTML">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">span&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>標題&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">span&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">span&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>副標題&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">span&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">span&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>第二副標題&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">span&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;a&amp;#34;&lt;/span> &lt;span class="na">title&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;first&amp;#34;&lt;/span> &lt;span class="na">href&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;/link&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>這是一行句子&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">a&lt;/span> &lt;span class="na">href&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;/link1&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>這是超連結1&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">a&lt;/span> &lt;span class="na">href&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;/link2&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>這是超連結2&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">data-target&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;value&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>data屬性&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;CLASS CLASS2&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>多個class&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="尋找標籤">尋找標籤&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="c1"># 返回符合的單個元素(如有多個符合，則回傳第一個)，當找不到則回傳None：&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;span&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;span&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;span&amp;gt;標題&amp;lt;/span&amp;gt;&lt;/span>
&lt;span class="c1"># 返回符合的全部元素(List)，當找不到則回傳空List：&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;span&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_all&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;span&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># [&amp;lt;span&amp;gt;標題&amp;lt;/span&amp;gt;, &amp;lt;span&amp;gt;副標題&amp;lt;/span&amp;gt;, &amp;lt;span&amp;gt;第二副標題&amp;lt;/span&amp;gt;]&lt;/span>
&lt;span class="c1"># 限制尋找元素數量：&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;span&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">limit&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># [&amp;lt;span&amp;gt;標題&amp;lt;/span&amp;gt;, &amp;lt;span&amp;gt;副標題&amp;lt;/span&amp;gt;]&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="取得元素文字值">取得元素文字、值&lt;/h3>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="c1"># 取得元素的文字：&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;div.a&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">text&lt;/span>
&lt;span class="c1"># 這是一行句子&lt;/span>
&lt;span class="c1"># 如果需要更多擷取方式，可使用get_text()&lt;/span>
&lt;span class="c1"># 取得元素屬性的值：&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;div.a&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;title&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># first&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;div.a&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;class&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># [&amp;#39;a&amp;#39;]&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;div.a&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;href&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># /link&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="元素屬性文字">元素屬性、文字&lt;/h3>
&lt;p>有些較複雜的也可以改用 find 或 find_all 來尋找。&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="c1"># 基本的&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_all&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">title&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;first&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># [&amp;lt;div class=&amp;#34;a&amp;#34; href=&amp;#34;/link&amp;#34; title=&amp;#34;first&amp;#34;&amp;gt;這是一行句子&amp;lt;/div&amp;gt;]&lt;/span>
&lt;span class="c1"># 因為 class 在 Python 中是保留字，所以尋找class時改使用 class_：&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_all&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">class_&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;CLASS&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># [&amp;lt;div class=&amp;#34;CLASS CLASS2&amp;#34;&amp;gt;多個class&amp;lt;/div&amp;gt;]&lt;/span>
&lt;span class="c1"># 當想比對全部class(注意順序)&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_all&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">class_&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;CLASS CLASS2&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># [&amp;lt;div class=&amp;#34;CLASS CLASS2&amp;#34;&amp;gt;多個class&amp;lt;/div&amp;gt;]&lt;/span>
&lt;span class="c1"># 某些HTML的屬性直接寫的話，會發生錯誤(例如 data-* 這類的屬性)，&lt;/span>
&lt;span class="c1"># 改使用另一種方式即可：&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_all&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">attrs&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;data-target&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;value&amp;#34;&lt;/span>&lt;span class="p">})&lt;/span>
&lt;span class="c1"># [&amp;lt;div data-target=&amp;#34;value&amp;#34;&amp;gt;data屬性&amp;lt;/div&amp;gt;]&lt;/span>
&lt;span class="c1"># 以正規表示式比對超連結網址：&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_all&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">href&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">re&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">compile&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;^/link\d&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;span class="c1"># [&amp;lt;a href=&amp;#34;/link1&amp;#34;&amp;gt;這是超連結1&amp;lt;/a&amp;gt;, &amp;lt;a href=&amp;#34;/link2&amp;#34;&amp;gt;這是超連結2&amp;lt;/a&amp;gt;]&lt;/span>
&lt;span class="c1"># 以文字內容尋找(也可搭配正規表示式)&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_all&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;div&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">string&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;這是一行句子&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_all&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;div&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">string&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">re&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">compile&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;句子&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;span class="c1"># [&amp;lt;div class=&amp;#34;a&amp;#34; href=&amp;#34;/link&amp;#34; title=&amp;#34;first&amp;#34;&amp;gt;這是一行句子&amp;lt;/div&amp;gt;]&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h3 id="父元素同一層元素">父元素、同一層元素&lt;/h3>
&lt;p>前面說的是以其元素往下尋找子元素，那如果要找父元素或同一層元素，使用以下方式：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-HTML" data-lang="HTML">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;div2&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;div1&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">p&lt;/span> &lt;span class="na">id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;a&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>第一點&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">p&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">p&lt;/span> &lt;span class="na">id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;b&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>第二點&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">p&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">p&lt;/span> &lt;span class="na">id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;my&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>第三點&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">p&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">p&lt;/span> &lt;span class="na">id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;c&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>第四點&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">p&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">p&lt;/span> &lt;span class="na">id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;d&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>第五點&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">p&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="c1"># 先以 &amp;lt;p id=&amp;#34;my&amp;#34;&amp;gt;第三點&amp;lt;/p&amp;gt; 元素為基準&lt;/span>
&lt;span class="n">my_tag&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">id&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;my&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 函式名稱多加s，代表尋找多個&lt;/span>
&lt;span class="c1"># 向上尋找父元素&lt;/span>
&lt;span class="n">my_tag&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_parent&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;div&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">my_tag&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_parents&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;div&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># 在同一層往前尋找元素&lt;/span>
&lt;span class="n">my_tag&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_previous_sibling&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;p&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;p id=&amp;#34;b&amp;#34;&amp;gt;第二點&amp;lt;/p&amp;gt;&lt;/span>
&lt;span class="n">my_tag&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_previous_siblings&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;p&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># [&amp;lt;p id=&amp;#34;b&amp;#34;&amp;gt;第二點&amp;lt;/p&amp;gt;, &amp;lt;p id=&amp;#34;a&amp;#34;&amp;gt;第一點&amp;lt;/p&amp;gt;]&lt;/span>
&lt;span class="c1"># 在同一層往後尋找元素&lt;/span>
&lt;span class="n">my_tag&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_next_sibling&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;p&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># &amp;lt;p id=&amp;#34;c&amp;#34;&amp;gt;第四點&amp;lt;/p&amp;gt;&lt;/span>
&lt;span class="n">my_tag&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_next_siblings&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;p&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c1"># [&amp;lt;p id=&amp;#34;c&amp;#34;&amp;gt;第四點&amp;lt;/p&amp;gt;, &amp;lt;p id=&amp;#34;d&amp;#34;&amp;gt;第五點&amp;lt;/p&amp;gt;]&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;h3 id="其他">其他&lt;/h3>
&lt;p>其他在擷取網頁可能還需要的功能：&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre class="chroma">&lt;code class="language-Python" data-lang="Python">&lt;span class="c1"># 去除某個元素&lt;/span>
&lt;span class="n">node&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;#my&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extract&lt;/span>&lt;span class="p">()&lt;/span>
&lt;span class="c1"># 去除多個元素&lt;/span>
&lt;span class="c1"># 注意：前面已經將 #my 移除了&lt;/span>
&lt;span class="n">node&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">t&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">extract&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">soup&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">select&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;p&amp;#34;&lt;/span>&lt;span class="p">)]&lt;/span>
&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;br/>
&lt;br/>
&lt;h2 id="瀏覽器使用-css-selectors-搜尋">瀏覽器使用 CSS Selectors 搜尋&lt;/h2>
&lt;p>你知道在撰寫網路爬蟲程式時，可以有什麼方式快速找到元素的標籤嗎？&lt;br />
瀏覽器的 &lt;strong>開發人員工具&lt;/strong> 有許多方便的功能讓我們使用~&lt;/p>
&lt;br/>
&lt;p>Q. 如何開啟瀏覽器的 &lt;strong>開發人員工具&lt;/strong> 呢？&lt;/p>
&lt;p>A. 有以下三種方式：&lt;/p>
&lt;ol>
&lt;li>網頁空白處點擊滑鼠右鍵 &amp;gt; 檢查。&lt;/li>
&lt;li>瀏覽器(Chrome)右上選單 &amp;gt; 更多工具 &amp;gt; 開發人員工具。&lt;/li>
&lt;li>快捷鍵 F12。&lt;/li>
&lt;/ol>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/sorted-out-css-selector/open_developer_tools_01.png" alt="開發人員工具" data-caption="第一種開啟方式" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='300px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:300px;height:;"/>
&lt;figcaption style="text-align: center;">
第一種開啟方式
&lt;/figcaption>
&lt;/figure>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/sorted-out-css-selector/open_developer_tools_02.png" alt="開發人員工具" data-caption="第二種開啟方式" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='500px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:500px;height:;"/>
&lt;figcaption style="text-align: center;">
第二種開啟方式
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>Q. 那如何快速找到元素的標籤？&lt;/p>
&lt;p>A. 切換到 &lt;strong>Elements&lt;/strong> 分頁，點擊左上角箭頭，並滑鼠指到(或點選)網頁上的元素。&lt;br />
如此開發人員工具內會跳到此元素的位置，並標註出來。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/sorted-out-css-selector/developer_tools.png" alt="找到元素的標籤" data-caption="找到元素的標籤" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='650px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:650px;height:;"/>
&lt;figcaption style="text-align: center;">
找到元素的標籤
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>Q. 如何使用 CSS Selectors 或 XPath 搜尋元素？&lt;/p>
&lt;p>A. 在 &lt;strong>Elements&lt;/strong> 分頁，快捷鍵 Ctrl + F，會跳出下方搜尋欄，可以透過 &amp;quot;文字&amp;quot;、&amp;quot;CSS Selectors&amp;quot;、&amp;quot;XPath&amp;quot; 搜尋元素。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/sorted-out-css-selector/elements.png" alt="Elements 下方搜尋欄" data-caption="Elements 下方搜尋欄" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='450px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:450px;height:;"/>
&lt;figcaption style="text-align: center;">
Elements 下方搜尋欄
&lt;/figcaption>
&lt;/figure>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/sorted-out-css-selector/search_selector.png" alt="使用 CSS Selectors 或 XPath 搜尋元素" data-caption="使用 CSS Selectors 或 XPath 搜尋元素" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='450px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:450px;height:;"/>
&lt;figcaption style="text-align: center;">
使用 CSS Selectors 或 XPath 搜尋元素
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;p>Q. 有辦法自動產生元素的 &amp;quot;CSS Selectors&amp;quot;、&amp;quot;XPath&amp;quot; 嗎？&lt;/p>
&lt;p>A. 是可以，但不那麼建議，因為網頁有時會更新、變動，建議自己找出較好的 Selector 寫法。&lt;br />
對元素點擊滑鼠右鍵 &amp;gt; Copy &amp;gt; Copy selector。&lt;/p>
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/sorted-out-css-selector/copy_selector.png" alt="複製元素的 CSS Selector 或 XPath" data-caption="複製元素的 CSS Selector 或 XPath" src="data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='450px' height='' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath fill='%23aaa' d='M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-1 16H6c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1h12c.55 0 1 .45 1 1v12c0 .55-.45 1-1 1zm-4.44-6.19l-2.35 3.02-1.56-1.88c-.2-.25-.58-.24-.78.01l-1.74 2.23c-.26.33-.02.81.39.81h8.98c.41 0 .65-.47.4-.8l-2.55-3.39c-.19-.26-.59-.26-.79 0z'/%3E%3C/svg%3E" class="lazyload" style="width:450px;height:;"/>
&lt;figcaption style="text-align: center;">
複製元素的 CSS Selector 或 XPath
&lt;/figcaption>
&lt;/figure>
&lt;br/>
&lt;!--adsense-->
&lt;br/>
&lt;br/>
&lt;p>如有發現任何錯誤，歡迎底下留言告知~&lt;/p>
&lt;br/>
&lt;br/>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://blog.csdn.net/huilan_same/article/details/52806985" target="_blank" rel="noopener">
Python selenium —— XPath and CSS cheat sheet
&lt;/a>&lt;br />
&lt;a href="https://blog.gtwang.org/programming/python-beautiful-soup-module-scrape-web-pages-tutorial/" target="_blank" rel="noopener">
Python 使用 Beautiful Soup 抓取與解析網頁資料，開發網路爬蟲教學
&lt;/a>&lt;/p>
&lt;br/>
&lt;blockquote>
&lt;p>不用很厲害才開始，要先開始才會很厲害。&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/sorted-out-css-selector.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><media:content url="https://blog.jiatool.comimages/posts/sorted-out-css-selector_meta.jpg" medium="image"><media:title type="html">meta image</media:title></media:content><category>BeautifulSoup</category><category>Python</category><category>CSS</category><category>HTML</category><category>網頁</category><category>網路爬蟲</category></item></channel></rss>