<?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>巴哈姆特 on IT 空間</title><link>https://blog.jiatool.com/tags/%E5%B7%B4%E5%93%88%E5%A7%86%E7%89%B9/</link><description>Recent content in 巴哈姆特 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, 11 Dec 2021 20:55:00 +0800</lastBuildDate><atom:link href="https://blog.jiatool.com/tags/%E5%B7%B4%E5%93%88%E5%A7%86%E7%89%B9/index.xml" rel="self" type="application/rss+xml"/><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>[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/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>巴哈姆特 GNN 新聞統計分析</title><link>https://blog.jiatool.com/posts/gamer-gnn-statistics/</link><pubDate>Sun, 06 Sep 2020 15:20:00 +0800</pubDate><author>jia@jiatool.com (Jia)</author><atom:modified>Sun, 06 Sep 2020 15:20:00 +0800</atom:modified><guid>https://blog.jiatool.com/posts/gamer-gnn-statistics/</guid><description>前言 之前看到巴哈姆特 GNN 新聞發了這篇文章： 巴哈姆特 GNN 遊戲新聞達成 20 萬篇里程碑！ 感謝所有玩家一路相挺 慶祝經過服務誕生 20 周年之際，在此篇新聞正式邁</description><content:encoded>&lt;h2 id="前言">前言&lt;/h2>
&lt;p>之前看到巴哈姆特 GNN 新聞發了這篇文章：&lt;br />
&lt;a href="https://gnn.gamer.com.tw/detail.php?sn=200000" target="_blank" rel="noopener">
巴哈姆特 GNN 遊戲新聞達成 20 萬篇里程碑！ 感謝所有玩家一路相挺
&lt;/a>&lt;br />
慶祝經過服務誕生 20 周年之際，在此篇新聞正式邁入第 20 萬篇新聞的里程碑，並統計了 GNN 相關數據。&lt;br />
覺得這統計還蠻有趣的，在想是不是也可以藉由爬蟲，來抓取巴哈姆特 GNN 新聞做一些簡單的統計。&lt;br />
本分析也只是帶著趣味所做的統計而已，大家當茶餘飯後娛樂看看就好。🤣&lt;/p>
&lt;p>💬 本篇數據皆以我能收集到的 GNN 新聞文章進行統計，分析說明也只是本人見解。&lt;/p>
&lt;h2 id="資料說明">資料說明&lt;/h2>
&lt;p>使用 Python 爬蟲將 GNN 新聞抓取下來，保存其&amp;quot;文章編號&amp;quot;、&amp;quot;標題&amp;quot;、&amp;quot;發布時間&amp;quot;、&amp;quot;按讚數&amp;quot;、&amp;quot;留言數&amp;quot;、&amp;quot;來源(作者)&amp;quot;，並以這些資料來做簡單的統計、分析。&lt;br />
資料來源為&lt;a href="https://gnn.gamer.com.tw/" target="_blank" rel="noopener">
巴哈姆特 GNN 新聞列表
&lt;/a>的文章，這次我抓取了從 2000 年 11 月 20 日第一篇開始，到 2020 年 8 月 31 日為止的 199,472 篇巴哈姆特 GNN 新聞文章(包含巴友投稿)，某些文章不知名的原因已遭移除，因此才會不滿 20 萬篇。&lt;/p>
&lt;p>備註：&lt;br />
💬 &amp;quot;按讚機制&amp;quot;在GNN新聞頁面是&amp;quot;推&amp;quot;、小屋內是&amp;quot;喜歡&amp;quot;，本文統一叫做&amp;quot;讚&amp;quot;。&lt;br />
💬 文中所述&amp;quot;文章編號&amp;quot;代表網址 &lt;strong>&lt;a href="https://gnn.gamer.com.tw/detail.php?sn=200000">https://gnn.gamer.com.tw/detail.php?sn=200000&lt;/a>&lt;/strong> 中&lt;code>sn=&lt;/code>後方的數字。&lt;br />
💬 &amp;quot;投稿系統&amp;quot;、&amp;quot;留言系統&amp;quot;、&amp;quot;按讚機制&amp;quot;不是一開始就有的，是之後才加入，因此統計時也會區分排除開來。&lt;/p>
&lt;ul>
&lt;li>投稿系統：根據官方說法是從 2009 年開始啟用，不過也許之前投稿的文章會放置於 GNN 的頁面，不像現在連結到作者小屋的創作頁面，所以已我目前判斷的依據(文章位於作者小屋)，第一篇是編號 63168 於 2012-03-08 發表的文章開始計算。&lt;/li>
&lt;li>留言系統：官方是說從 2007 年 11 月 28 日正式導入，不過我從編號 312 於 2001-01-07 發表的文章就開始看到第一則留言，但之後這段時間內有留言的篇數很少，也許是官方在測試此功能(?)。&lt;/li>
&lt;li>按讚機制：官方貌似沒有說從何時加入，但我在編號 45 於 2000-12-04 的文章發現按讚按鈕，在編號 19743 於 2005-04-29 的文章出現了第一個讚。不過也許我了解不多，因為並不是每篇GNN新聞都有按讚的按鈕。&lt;/li>
&lt;/ul>
&lt;h2 id="篇數統計">篇數統計&lt;/h2>
&lt;h3 id="總篇數">總篇數&lt;/h3>
&lt;p>首先來看看目前還有效的文章總篇數為 199,472 篇，&lt;br />
其中 GNN 編輯部佔了 173,589 篇 (87.0%)；巴友投稿佔了 25,883 篇 (13.0 %)。&lt;br />
(這百分比還真的是這樣&amp;hellip;87)&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer-gnn-statistics/total_articles.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;a href="https://gnn.gamer.com.tw/detail.php?sn=200000" target="_blank" rel="noopener">
官方所述
&lt;/a>，10 萬篇新聞是於 2014 年 7 月達成 (花費 13 年 8 個月)，20 萬篇新聞是於 2020 年 7 月達成 (僅花費 6 年)。&lt;br />
我將其以每 5 萬篇文章切割，並換算成天數來比較，發現到前 5 萬篇所需要的時間最久，需要 3,698 天，後來大概都只需 1,000 多天：&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer-gnn-statistics/articles_spend_time_table.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;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer-gnn-statistics/articles_spend_time.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>假如以文章編號來計算，從 2000 年 11 月 20 日第一篇開始，到 2020 年 8 月 31 日為止，文章編號大約是 202600 左右 (因為玩家投稿的文章收錄後可能編號還比較後面，這邊以大略值估計)，共計 7225 天，等於平均一天發布 28 篇新聞文章。&lt;/p>
&lt;h3 id="最多篇數的一天">最多篇數的一天&lt;/h3>
&lt;p>發布最多文章的一天前三多的分別是&amp;quot;2014-08-15&amp;quot;、&amp;quot;2014-10-24&amp;quot;、&amp;quot;2020-06-12&amp;quot;、&amp;quot;2013-11-01&amp;quot;，各別有114、110、103、103篇文章，不知道是剛好有什麼盛大的活動還是什麼原因？&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer-gnn-statistics/max_day_total_articles.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;h3 id="各年月星期的篇數">各年月星期的篇數&lt;/h3>
&lt;p>這部分我各別依照文章發布日期的 &lt;strong>年&lt;/strong>、&lt;strong>月&lt;/strong>、&lt;strong>星期&lt;/strong> 做區分統計，並把官方發布跟巴友投稿拆分統計。&lt;/p>
&lt;h5 id="各年份的篇數">各年份的篇數&lt;/h5>
&lt;p>初期巴哈剛創立，而且可能全台瘋 ACG 的人數不像現在越來越多，發布的篇數相較後期是較少的。&lt;br />
照官方的說法從 2009 年起加入投稿系統，也透過各位巴友貢獻了許多文章，豐富了巴哈姆特 GNN 新聞。&lt;br />
(* 今年只統計到八月底，因此文章量較少)&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer-gnn-statistics/year_total_articles.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;h5 id="各月份的篇數">各月份的篇數&lt;/h5>
&lt;p>按照各月份統計的篇數就蠻平均的，二月份的那個窟窿應該是二月只有 28 天的關係。XD&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer-gnn-statistics/month_total_articles.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;h5 id="各星期的篇數">各星期的篇數&lt;/h5>
&lt;p>從依照星期來區分的數據中，可以很明顯地觀察出週末(六日)的文章非常少，就像日本製造的壓縮機非常稀少(X&lt;br />
而平日從週一到週五有逐步上升的趨勢，這與&amp;quot;星期一症候群&amp;quot;有關嗎?!😂&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer-gnn-statistics/week_total_articles.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;h2 id="按讚數">按讚數&lt;/h2>
&lt;p>全部文章中最多按讚的前五名如下表，第一名是 &lt;a href="https://gnn.gamer.com.tw/detail.php?sn=88969" target="_blank" rel="noopener">
[ 論遊戲 ] 為什麼我們輸很大?! 就認證角度淺談韓國遊戲人才培育
&lt;/a>，共有 1,535 個讚。&lt;br />
其中發現到作者&amp;quot;哈利菠菜&amp;quot;竟然有兩篇文章擠進前五名，真的是非常佩服。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer-gnn-statistics/top_likes_num.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>平均按讚數中，GNN 頁面上的平均一篇文章會有 2.11 個讚，而巴友投稿的平均多達 24.4 個讚。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer-gnn-statistics/average_likes_num.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;h2 id="留言數">留言數&lt;/h2>
&lt;p>全部文章中最多留言的前五名如下表，第一名是 &lt;a href="https://gnn.gamer.com.tw/detail.php?sn=175841" target="_blank" rel="noopener">
赤燭《還願》埋梗小熊維尼風波延燒 發行商宣布終止合作並將求償
&lt;/a>，竟多達 1,775 則留言，回應非常熱烈。&lt;br />
全部都是 GNN 官方文章，推測是在 GNN 網頁(不是個人小屋)，其留言的意願比較高。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer-gnn-statistics/top_comments_num.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>平均留言數中，GNN 頁面上的平均一篇文章會有 34.29 則留言，而巴友投稿的平均一篇文章會有 15.6 則留言。&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer-gnn-statistics/average_comments_num.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;a href="https://gnn.gamer.com.tw/detail.php?sn=200000" target="_blank" rel="noopener">
20 萬篇里程碑
&lt;/a>有說到 &amp;quot;於 2007 年 11 月 28 日正式導入留言系統，在這 12 年間累積超過 480 萬則留言，平均每篇新聞有 37 則留言&amp;quot;。&lt;br />
而我統計到今年 8 月底的數據，累積總留言數 542 萬則留言、平均每篇新聞有 32 則留言。&lt;/p>
&lt;p>而 &lt;a href="https://gnn.gamer.com.tw/detail.php?sn=194924" target="_blank" rel="noopener">
《劍俠情緣 3 免費版》代理商於中國哀悼日為維護台灣玩家權益 不惜與原廠終止合作
&lt;/a> 同時擠進最多按讚與最多留言的前五名，討論也是非常熱烈。&lt;/p>
&lt;h2 id="標題文字雲">標題文字雲&lt;/h2>
&lt;p>在展示標題的文字雲之前，先來看看最長、最短、平均標題字數(字元)為何。一個中文字、英文字母、標點符號、空白都算一個字元，例如：&amp;quot;最近最熱門的遊戲：Fall Guys&amp;quot; 這樣算 18 個字。&lt;br />
從統計結果看來，平均標題使用 32 個字元，最長的有到 94 個字元，最短的竟然只有 3 個字。😆&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer-gnn-statistics/title_num.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>這邊我簡單使用 jieba 套件加入繁體中文詞彙來分詞，並搭配 wordcloud 套件來繪製標題的文字雲。&lt;/p>
&lt;p>先來看看全部文章的標題文字雲：&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer-gnn-statistics/title_cloud_all.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>再來我將其依照年份分為四等分，分別為&amp;quot;2000年~2005年&amp;quot;、&amp;quot;2006年~2010年&amp;quot;、&amp;quot;2011年~2015年&amp;quot;、&amp;quot;2016年~2020年&amp;quot;：&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer-gnn-statistics/title_cloud_2000-2005.png" alt="標題文字雲 2000年~2005年" data-caption="標題文字雲 2000年~2005年" 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;">
標題文字雲 2000年~2005年
&lt;/figcaption>
&lt;/figure>&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer-gnn-statistics/title_cloud_2006-2010.png" alt="標題文字雲 2006年~2010年" data-caption="標題文字雲 2006年~2010年" 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;">
標題文字雲 2006年~2010年
&lt;/figcaption>
&lt;/figure>&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer-gnn-statistics/title_cloud_2011-2015.png" alt="標題文字雲 2011年~2015年" data-caption="標題文字雲 2011年~2015年" 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;">
標題文字雲 2011年~2015年
&lt;/figcaption>
&lt;/figure>&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer-gnn-statistics/title_cloud_2016-2020.png" alt="標題文字雲 2016年~2020年" data-caption="標題文字雲 2016年~2020年" 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;">
標題文字雲 2016年~2020年
&lt;/figcaption>
&lt;/figure>&lt;/p>
&lt;h2 id="題外話-八二法則">題外話 (八二法則)&lt;/h2>
&lt;p>突然想到試試看&lt;a href="https://zh.wikipedia.org/wiki/%E5%B8%95%E7%B4%AF%E6%89%98%E6%B3%95%E5%88%99" target="_blank" rel="noopener">
八二法則
&lt;/a> (關鍵少數法則、帕累托法則) 是否存在。&lt;br />
先以留言數來計算，總篇數 199,472 篇，前 20% 占了 70% 的留言數，只能算接近八二法則，不過我想是因為抓取時忘記將沒有留言區塊的文章去除&amp;hellip;&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer-gnn-statistics/82_comments.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>而按讚數有將沒有按讚區塊的文章排除掉，總篇數 81,948 篇，前 20% 占了 87% 的按讚數，不知是否跟不是每篇文章都有按讚區塊有關？&lt;br />
&lt;figure >
&lt;img data-src="https://res.cloudinary.com/jiablog/gamer-gnn-statistics/82_likes.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;br/>
&lt;br/>
&lt;p>歡迎底下留言你的看法、討論~~~📢&lt;/p>
&lt;hr />
&lt;p>參考：&lt;br />
&lt;a href="https://gnn.gamer.com.tw/detail.php?sn=200000" target="_blank" rel="noopener">
巴哈姆特 GNN 遊戲新聞達成 20 萬篇里程碑！ 感謝所有玩家一路相挺
&lt;/a>&lt;br />
&lt;a href="https://gnn.gamer.com.tw/detail.php?sn=100000" target="_blank" rel="noopener">
巴哈姆特 GNN 遊戲新聞突破 10 萬篇！ 感謝所有玩家一路相挺
&lt;/a>&lt;/p>
&lt;blockquote>
&lt;p>再小的努力，乘以 365 都很明顯；&lt;br />
再大的困難，除以 365 都很簡單。&lt;/p>
&lt;/blockquote></content:encoded><dc:creator>Jia</dc:creator><media:content url="https://blog.jiatool.comimages/cover/gamer-gnn-statistics.jpg" medium="image"><media:title type="html">featured image</media:title></media:content><category>巴哈姆特</category><category>統計分析</category></item></channel></rss>