-
Notifications
You must be signed in to change notification settings - Fork 1
/
search.json
1 lines (1 loc) · 131 KB
/
search.json
1
[{"title":"Cos相似度實作","url":"/2020/01/18/Cos%E7%9B%B8%E4%BC%BC%E5%BA%A6%E5%AF%A6%E4%BD%9C/","content":"<h2 id=\"方法設計\"><a href=\"#方法設計\" class=\"headerlink\" title=\"方法設計\"></a>方法設計</h2><ol>\n<li>使用jieba斷詞,設置自定義字典</li>\n<li>每篇文章斷詞後,計算每篇文章對於這個集合中的詞的詞頻生成兩篇文章各自的詞頻向量</li>\n<li>計算兩個向量的餘弦相似度,值越大就表示越相似</li>\n</ol>\n<h2 id=\"實現說明\"><a href=\"#實現說明\" class=\"headerlink\" title=\"實現說明\"></a>實現說明</h2><h3 id=\"爬取文章\"><a href=\"#爬取文章\" class=\"headerlink\" title=\"爬取文章\"></a>爬取文章</h3><p>我們利用爬蟲爬取分析目標的粉絲專頁,並將其內容寫入MySQL裡的facebook資料表,並將jieba斷詞後不重複的結果寫入MySQL的dictionary資料表中word欄位</p>\n<span id=\"more\"></span>\n<blockquote>\n<p>我們選取怪奇事務所的粉專進行</p>\n</blockquote>\n<figure class=\"highlight python\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\">#Facebook粉絲頁網址</span></span><br><span class=\"line\">url = <span class=\"string\">"https://mbasic.facebook.com/IncredivilleTW/?refid=13&__tn__=%2Cg"</span></span><br><span class=\"line\"></span><br><span class=\"line\">resp = req.get(url, cookies=cookies)</span><br><span class=\"line\"></span><br><span class=\"line\">html_doc = resp.text</span><br><span class=\"line\"></span><br><span class=\"line\">soup = BeautifulSoup(html_doc, <span class=\"string\">'html.parser'</span>)</span><br><span class=\"line\">headers = {</span><br><span class=\"line\"> <span class=\"string\">'cookie'</span>: <span class=\"string\">'datr=lsdAXbRR26aO9ePicNOFFkF6; sb=v8dAXdIceUJHQYtxfH5yJghe; _fbp=fb.1.1568882205233.239187278; locale=zh_TW; c_user=531045890; xs=37%3AqDyc_aZQWbZqJQ%3A2%3A1570409723%3A17284%3A8670%3A4bOHmE1AjVm-UQ; presence=EDvF3EtimeF1570574420EuserFA2531045890A2EstateFDt3F_5bDiFA2user_3a506028681A2EoF1EfF1C_5dEutc3F1570409759903G570574420183Elm3FnullCEchFDp_5f531045890F1CC; wd=1280x648; fr=0POPFYG9NYhEAyYKy.AWUwzziefaPVhk_qeNUq-ORj_XI.BdQMTz.zg.F2a.0.0.BdnqEu.AWV_r9K_; spin=r.1001274804_b.trunk_t.1570680542_s.1_v.2_; dpr=2; act=1570684244969%2F1'</span></span><br><span class=\"line\">}</span><br><span class=\"line\">docs = []</span><br><span class=\"line\"><span class=\"built_in\">filter</span> = re.<span class=\"built_in\">compile</span>(<span class=\"string\">"[^\\u4e00-\\u9fa5A-Za-z]+"</span>)</span><br><span class=\"line\">titles = soup.find_all(<span class=\"string\">"a"</span>)</span><br><span class=\"line\"><span class=\"keyword\">for</span> t <span class=\"keyword\">in</span> titles:</span><br><span class=\"line\"> doc = []</span><br><span class=\"line\"> <span class=\"keyword\">if</span> t.has_attr(<span class=\"string\">"href"</span>):</span><br><span class=\"line\"> <span class=\"keyword\">if</span> <span class=\"string\">"story.php"</span> <span class=\"keyword\">in</span> t[<span class=\"string\">"href"</span>] <span class=\"keyword\">and</span> <span class=\"string\">"https://"</span> <span class=\"keyword\">not</span> <span class=\"keyword\">in</span> t[<span class=\"string\">"href"</span>]:</span><br><span class=\"line\"> <span class=\"comment\">#發文url</span></span><br><span class=\"line\"> post_url = <span class=\"string\">"https://mbasic.facebook.com"</span>+t[<span class=\"string\">"href"</span>]</span><br><span class=\"line\"> <span class=\"comment\">#文章id</span></span><br><span class=\"line\"> url_rex = re.<span class=\"built_in\">compile</span>(<span class=\"string\">"story_fbid=(.*?)(?:&|$)"</span>);</span><br><span class=\"line\"> post_id = url_rex.findall(post_url)[<span class=\"number\">0</span>]</span><br><span class=\"line\"> resp_1 = req.get(post_url, cookies=cookies,headers=headers)</span><br><span class=\"line\"> <span class=\"comment\">#Facebook發文文章</span></span><br><span class=\"line\"> html_doc_1 = resp_1.text</span><br><span class=\"line\"> </span><br><span class=\"line\"> soup_1 = BeautifulSoup(html_doc_1, <span class=\"string\">'html.parser'</span>)</span><br><span class=\"line\"> <span class=\"comment\">#存放文章內容的list</span></span><br><span class=\"line\"> docs_1 = []</span><br><span class=\"line\"> </span><br><span class=\"line\"> <span class=\"comment\">#取得所有文章,包含留言</span></span><br><span class=\"line\"> titles_1 = soup_1.find_all(<span class=\"string\">"div"</span>)</span><br><span class=\"line\"> reply_id_array = []</span><br><span class=\"line\"> post_id_array = []</span><br><span class=\"line\"> <span class=\"keyword\">for</span> t_1 <span class=\"keyword\">in</span> titles_1:</span><br><span class=\"line\"> <span class=\"keyword\">if</span>(t_1.find(<span class=\"string\">"h3"</span>)):</span><br><span class=\"line\"> name = t_1.find(<span class=\"string\">"h3"</span>).getText() <span class=\"comment\">#發文者</span></span><br><span class=\"line\"> <span class=\"comment\">#發文時間,有可能我們說到的結構沒有包含abbr,要判斷以濾掉</span></span><br><span class=\"line\"> <span class=\"keyword\">if</span> t_1.find(<span class=\"string\">"abbr"</span>) <span class=\"keyword\">is</span> <span class=\"literal\">None</span>:</span><br><span class=\"line\"> publish_date = <span class=\"literal\">None</span>;</span><br><span class=\"line\"> <span class=\"keyword\">else</span>:</span><br><span class=\"line\"> publish_date = t_1.find(<span class=\"string\">"abbr"</span>).getText()</span><br><span class=\"line\"> </span><br><span class=\"line\"> <span class=\"comment\">#內文</span></span><br><span class=\"line\"> sub_content= t_1.find(<span class=\"string\">"h3"</span>).find_next(<span class=\"string\">"div"</span>).getText()</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"comment\">#發文id,如果沒有id,就代表是原始文章</span></span><br><span class=\"line\"> reply_id= t_1.find(<span class=\"string\">"h3"</span>).find_parent(<span class=\"string\">"div"</span>).find_parent(<span class=\"string\">"div"</span>).get(<span class=\"string\">"id"</span>)</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">if</span> reply_id <span class=\"keyword\">is</span> <span class=\"literal\">None</span> <span class=\"keyword\">and</span> post_id <span class=\"keyword\">in</span> post_id_array:</span><br><span class=\"line\"> <span class=\"keyword\">continue</span>;</span><br><span class=\"line\"> <span class=\"keyword\">else</span>:</span><br><span class=\"line\"> post_id_array.append(post_id)</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">if</span> reply_id <span class=\"keyword\">is</span> <span class=\"keyword\">not</span> <span class=\"literal\">None</span> <span class=\"keyword\">and</span> reply_id <span class=\"keyword\">in</span> reply_id_array:</span><br><span class=\"line\"> <span class=\"keyword\">continue</span>;</span><br><span class=\"line\"> <span class=\"keyword\">else</span>:</span><br><span class=\"line\"> reply_id_array.append(reply_id)</span><br><span class=\"line\"> <span class=\"comment\">#將發文內容斷詞</span></span><br><span class=\"line\"> seg_list = jieba.cut(sub_content, cut_all=<span class=\"literal\">False</span>)</span><br><span class=\"line\"> insertDictionary(seg_list)</span><br><span class=\"line\"> item = {</span><br><span class=\"line\"> <span class=\"string\">"post_id"</span>:post_id,</span><br><span class=\"line\"> <span class=\"string\">"author"</span>:name,</span><br><span class=\"line\"> <span class=\"string\">"content"</span>:remove_emoji(sub_content),</span><br><span class=\"line\"> <span class=\"string\">"reply_id"</span>:t_1.find(<span class=\"string\">"h3"</span>).find_parent(<span class=\"string\">"div"</span>).find_parent(<span class=\"string\">"div"</span>).get(<span class=\"string\">"id"</span>),</span><br><span class=\"line\"> <span class=\"string\">"publish_date"</span>:publish_date,</span><br><span class=\"line\"> <span class=\"string\">"url"</span>:post_url,</span><br><span class=\"line\"> }</span><br><span class=\"line\"> insertContent(item)</span><br><span class=\"line\"> docs_1.append(item)</span><br></pre></td></tr></table></figure>\n<h3 id=\"製成字典\"><a href=\"#製成字典\" class=\"headerlink\" title=\"製成字典\"></a>製成字典</h3><p>將dictionary資料表word欄位中的資料取出,並製成字典</p>\n<figure class=\"highlight python\"><table><tr><td class=\"code\"><pre><span class=\"line\">dicts = []</span><br><span class=\"line\">sql = <span class=\"string\">"select * from dictionary"</span></span><br><span class=\"line\">mycursor = mydb.cursor()</span><br><span class=\"line\">mycursor.execute(sql)</span><br><span class=\"line\">myresult = mycursor.fetchall()</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">for</span> i <span class=\"keyword\">in</span> myresult:</span><br><span class=\"line\">dicts.append(i[<span class=\"number\">1</span>])</span><br><span class=\"line\"></span><br></pre></td></tr></table></figure>\n<h3 id=\"生成詞頻向量並且計算餘弦相似度\"><a href=\"#生成詞頻向量並且計算餘弦相似度\" class=\"headerlink\" title=\"生成詞頻向量並且計算餘弦相似度\"></a>生成詞頻向量並且計算餘弦相似度</h3><pre><code>取出欲分析之兩篇文章後,再次使用jieba斷詞,並且依照字典產生詞頻向量,計算兩篇文章之餘弦相似度,值愈大代表愈相似\n\n<figure class=\"highlight python\"><table><tr><td class=\"code\"><pre><span class=\"line\">sql = <span class=\"string\">"select post_id,content from facebook limit 2"</span></span><br><span class=\"line\">mycursor = mydb.cursor()</span><br><span class=\"line\">mycursor.execute(sql)</span><br><span class=\"line\">myresult = mycursor.fetchall()</span><br><span class=\"line\">post_ids = []</span><br><span class=\"line\">post_contents = []</span><br><span class=\"line\">post_array = []</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">for</span> i <span class=\"keyword\">in</span> myresult:</span><br><span class=\"line\"> post_ids.append(i[<span class=\"number\">0</span>])</span><br><span class=\"line\"> post_contents.append(i[<span class=\"number\">1</span>])</span><br><span class=\"line\"> seg_list = jieba.cut(i[<span class=\"number\">1</span>], cut_all=<span class=\"literal\">False</span>)</span><br><span class=\"line\"> docA = np.zeros(<span class=\"built_in\">len</span>(dicts))</span><br><span class=\"line\"> <span class=\"keyword\">for</span> j <span class=\"keyword\">in</span> seg_list:</span><br><span class=\"line\"> p = dicts.index(j)</span><br><span class=\"line\"> docA[p:p+<span class=\"number\">1</span>] = docA[p:p+<span class=\"number\">1</span>]+<span class=\"number\">1</span></span><br><span class=\"line\"> post_array.append(docA)</span><br><span class=\"line\">c = np.dot(post_array[<span class=\"number\">0</span>],post_array[<span class=\"number\">1</span>])</span><br><span class=\"line\">a_s = np.sqrt(np.<span class=\"built_in\">sum</span>(post_array[<span class=\"number\">0</span>]**<span class=\"number\">2</span>))</span><br><span class=\"line\">b_s = np.sqrt(np.<span class=\"built_in\">sum</span>(post_array[<span class=\"number\">1</span>]**<span class=\"number\">2</span>))</span><br><span class=\"line\"></span><br><span class=\"line\">result = c / (a_s * b_s)</span><br></pre></td></tr></table></figure>\n</code></pre>\n","categories":["資料科學"],"tags":["python","NLP"]},{"title":"[JS]利用echart.js繪圖","url":"/2021/02/15/JS-%E5%88%A9%E7%94%A8echart-js%E7%B9%AA%E5%9C%96/","content":"<h2 id=\"echart\"><a href=\"#echart\" class=\"headerlink\" title=\"echart\"></a>echart</h2><h3 id=\"基本運用\"><a href=\"#基本運用\" class=\"headerlink\" title=\"基本運用\"></a>基本運用</h3><p>echart是一個用js繪圖的框架,<a href=\"https://echarts.apache.org/zh/feature.html\">官方文檔</a>。</p>\n<p>引入echart後,首先必須準備一個畫圖的區塊。</p>\n<span id=\"more\"></span>\n\n<figure class=\"highlight html\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"tag\"><<span class=\"name\">div</span> <span class=\"attr\">class</span>=<span class=\"string\">"row"</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">div</span> <span class=\"attr\">id</span>=<span class=\"string\">"month_stat"</span> <span class=\"attr\">style</span>=<span class=\"string\">"width:50%; height:400px;"</span> <span class=\"attr\">class</span>=<span class=\"string\">"col"</span>></span><span class=\"tag\"></<span class=\"name\">div</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">div</span> <span class=\"attr\">id</span>=<span class=\"string\">"month_stat_2"</span> <span class=\"attr\">style</span>=<span class=\"string\">"width:50%; height:400px;"</span> <span class=\"attr\">class</span>=<span class=\"string\">"col"</span>></span><span class=\"tag\"></<span class=\"name\">div</span>></span></span><br><span class=\"line\"><span class=\"tag\"></<span class=\"name\">div</span>></span></span><br></pre></td></tr></table></figure>\n<p>我會繪製兩個圖表,一個負責AVG、OBP、SLG,另一個負責PA、AB、H、RBI、HR,並且利用Bootstrap將兩個圖表排在一列,會使用長條圖來表示。</p>\n<p>echart官網有即時顯示的<a href=\"https://echarts.apache.org/examples/zh/editor.html?c=bar-simple\">編輯器</a>可用。</p>\n<p><code>官方範例</code></p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"code\"><pre><span class=\"line\">option = {</span><br><span class=\"line\"> <span class=\"attr\">xAxis</span>: {</span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"string\">'category'</span>,</span><br><span class=\"line\"> <span class=\"attr\">data</span>: [<span class=\"string\">'Mon'</span>, <span class=\"string\">'Tue'</span>, <span class=\"string\">'Wed'</span>, <span class=\"string\">'Thu'</span>, <span class=\"string\">'Fri'</span>, <span class=\"string\">'Sat'</span>, <span class=\"string\">'Sun'</span>]</span><br><span class=\"line\"> },</span><br><span class=\"line\"> <span class=\"attr\">yAxis</span>: {</span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"string\">'value'</span></span><br><span class=\"line\"> },</span><br><span class=\"line\"> <span class=\"attr\">series</span>: [{</span><br><span class=\"line\"> <span class=\"attr\">data</span>: [<span class=\"number\">120</span>, <span class=\"number\">200</span>, <span class=\"number\">150</span>, <span class=\"number\">80</span>, <span class=\"number\">70</span>, <span class=\"number\">110</span>, <span class=\"number\">130</span>],</span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"string\">'bar'</span></span><br><span class=\"line\"> }]</span><br><span class=\"line\">};</span><br></pre></td></tr></table></figure>\n<p>xAxis為x軸的設置,其中type為x軸的屬性,可以選擇<code>value</code>、<code>category</code>、<code>time</code>、<code>log</code>四種,x軸我預定顯示數值種類,所以選擇<code>category</code>,而y軸為數值。</p>\n<p>如果要繪製橫向的長條圖,只要把xAxis和yAxis的內容對調就好,series中的data會自動對應。</p>\n<p>基本的長條圖介紹玩了,我想要繪製的長條圖x軸為月份,y軸為數值,並且每個月分都有每種數據,需要用到<a href=\"https://echarts.apache.org/examples/zh/editor.html?c=bar-stack\">官方範例</a>。</p>\n<p>跟上一個不同的是,這個範例有著標籤可以控制顯示,需要更改series裡面的內容,並且加入legend屬性。</p>\n<figure class=\"highlight pgsql\"><table><tr><td class=\"code\"><pre><span class=\"line\">series: [{</span><br><span class=\"line\"> <span class=\"type\">name</span>: <span class=\"string\">'AVG'</span>,</span><br><span class=\"line\"> <span class=\"keyword\">type</span>: <span class=\"string\">'bar'</span>,</span><br><span class=\"line\"> data: result[<span class=\"string\">'AVG'</span>]</span><br><span class=\"line\"> },{</span><br><span class=\"line\"> <span class=\"type\">name</span>: <span class=\"string\">'OBP'</span>,</span><br><span class=\"line\"> <span class=\"keyword\">type</span>: <span class=\"string\">'bar'</span>,</span><br><span class=\"line\"> data: result[<span class=\"string\">'OBP'</span>]</span><br><span class=\"line\"> },{</span><br><span class=\"line\"> <span class=\"type\">name</span>: <span class=\"string\">'SLG'</span>,</span><br><span class=\"line\"> <span class=\"keyword\">type</span>: <span class=\"string\">'bar'</span>,</span><br><span class=\"line\"> data: result[<span class=\"string\">'SLG'</span>]</span><br><span class=\"line\"> }]</span><br></pre></td></tr></table></figure>\n<blockquote>\n<p>result為ajax跟Falsk取的資料</p>\n</blockquote>\n<p>三種資料有三種name,則我必須在legend裡面宣告這三種name。</p>\n<figure class=\"highlight css\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"selector-tag\">legend</span>: {</span><br><span class=\"line\"> data: [<span class=\"string\">'AVG'</span>, <span class=\"string\">'SLG'</span>, <span class=\"string\">'OBP'</span>]</span><br><span class=\"line\"> }</span><br></pre></td></tr></table></figure>\n\n<h3 id=\"增加圖表功能\"><a href=\"#增加圖表功能\" class=\"headerlink\" title=\"增加圖表功能\"></a>增加圖表功能</h3><h4 id=\"toolbox\"><a href=\"#toolbox\" class=\"headerlink\" title=\"toolbox\"></a>toolbox</h4><p>echart有提供許多API來讓我們使用,在<a href=\"https://echarts.apache.org/zh/api.html#echarts\">官方文檔</a>中可以查到許多有用的API。</p>\n<p>今天我主要回會用toolbox這個配置項的功能,toolbox可以為圖表增添工具欄,有輸出圖片、數據圖、縮放等。</p>\n<p>首先要啟用toolbox要先設置<code>show</code>為true,並且可以在<code>feature</code>中設置各選項的內容。</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"attr\">toolbox</span>: {</span><br><span class=\"line\"> <span class=\"attr\">show</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"attr\">orient</span>: <span class=\"string\">'vertical'</span>,</span><br><span class=\"line\"> <span class=\"attr\">left</span>: <span class=\"string\">'right'</span>,</span><br><span class=\"line\"> <span class=\"attr\">top</span>: <span class=\"string\">'center'</span>,</span><br><span class=\"line\"> <span class=\"attr\">feature</span>: {</span><br><span class=\"line\"> <span class=\"attr\">magicType</span>: { <span class=\"attr\">show</span>: <span class=\"literal\">true</span>, <span class=\"attr\">type</span>: [<span class=\"string\">'line'</span>, <span class=\"string\">'bar'</span>, <span class=\"string\">'stack'</span>, <span class=\"string\">'tiled'</span>] },</span><br><span class=\"line\"> <span class=\"attr\">restore</span>: { <span class=\"attr\">show</span>: <span class=\"literal\">true</span> },</span><br><span class=\"line\"> <span class=\"attr\">saveAsImage</span>: { <span class=\"attr\">show</span>: <span class=\"literal\">true</span> }</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br></pre></td></tr></table></figure>\n<blockquote>\n<p>magicType可以讓長條圖轉成折線圖、堆疊圖等</p>\n</blockquote>\n<h4 id=\"dataZoom\"><a href=\"#dataZoom\" class=\"headerlink\" title=\"dataZoom\"></a>dataZoom</h4><p>接著我想要增加縮放月份的功能,這邊用到的是<code>dataZoom</code>,<code>dataZoom</code>的區域縮放功能可以選取想要的區域數值。</p>\n<p><code>dataZoom</code>有inside和slider兩種,在type屬性中宣告(預設是slider),inside是內置的,可以使用滑鼠的滾輪操作,手機可以用兩指放大,而slider則是外面有縮放條可以選取。</p>\n<p><code>slider</code><br><img src=\"https://i.imgur.com/zyRNbh4.png\"></p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"attr\">dataZoom</span>: [ </span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"attr\">show</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"attr\">realtime</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"attr\">start</span>: <span class=\"number\">0</span>,</span><br><span class=\"line\"> <span class=\"attr\">end</span>: <span class=\"number\">100</span></span><br><span class=\"line\"> }</span><br><span class=\"line\"> ],</span><br></pre></td></tr></table></figure>\n\n\n<h4 id=\"tooltip\"><a href=\"#tooltip\" class=\"headerlink\" title=\"tooltip\"></a>tooltip</h4><p>現在滑鼠移到圖表上會有顯示數據,但是都是每一條獨立觸發,我希望當我的滑鼠移到某個月分時,可以將三個數據都顯示出來,這時要用到<code>tooltip</code>的功能</p>\n<p>還沒有tooltip的提示<br><img src=\"https://i.imgur.com/VnNTtBa.png\"></p>\n<p>tooltip有兩種觸發條件:item和axis,item主要用在散點圖,透過點觸發,而axis用在長條圖,透過軸觸發。</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"attr\">tooltip</span>: {</span><br><span class=\"line\"> <span class=\"attr\">trigger</span>: <span class=\"string\">'axis'</span></span><br><span class=\"line\"> },</span><br></pre></td></tr></table></figure>\n\n<p><img src=\"https://i.imgur.com/KQRrNU3.png\"></p>\n<p>完整程式碼</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">function</span> <span class=\"title function_\">get_month</span>(<span class=\"params\"></span>){</span><br><span class=\"line\"> <span class=\"keyword\">let</span> p = $(<span class=\"string\">"#player"</span>).<span class=\"title function_\">val</span>();</span><br><span class=\"line\"> <span class=\"keyword\">let</span> chart = echarts.<span class=\"title function_\">init</span>(<span class=\"variable language_\">document</span>.<span class=\"title function_\">getElementById</span>(<span class=\"string\">'month_stat'</span>), <span class=\"string\">'white'</span>, { <span class=\"attr\">renderer</span>: <span class=\"string\">'canvas'</span> });</span><br><span class=\"line\"> <span class=\"keyword\">let</span> chart2 = echarts.<span class=\"title function_\">init</span>(<span class=\"variable language_\">document</span>.<span class=\"title function_\">getElementById</span>(<span class=\"string\">'month_stat_2'</span>), <span class=\"string\">'white'</span>, { <span class=\"attr\">renderer</span>: <span class=\"string\">'canvas'</span> });</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">if</span>(p!==<span class=\"string\">'選擇球員'</span>){</span><br><span class=\"line\"> $.<span class=\"title function_\">ajax</span>({</span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"string\">'POST'</span>,</span><br><span class=\"line\"> <span class=\"attr\">url</span>: <span class=\"string\">"/getchartinfo"</span>,</span><br><span class=\"line\"> <span class=\"attr\">data</span>: {<span class=\"string\">"p"</span>:p},</span><br><span class=\"line\"> <span class=\"attr\">success</span>: <span class=\"keyword\">function</span> (<span class=\"params\">result</span>) {</span><br><span class=\"line\"> <span class=\"keyword\">let</span> option = {</span><br><span class=\"line\"> <span class=\"attr\">title</span>: {</span><br><span class=\"line\"> <span class=\"attr\">text</span>: result[<span class=\"string\">'name'</span>]</span><br><span class=\"line\"> },</span><br><span class=\"line\"> <span class=\"attr\">legend</span>: {</span><br><span class=\"line\"> <span class=\"attr\">data</span>: [<span class=\"string\">'AVG'</span>, <span class=\"string\">'SLG'</span>, <span class=\"string\">'OBP'</span>]</span><br><span class=\"line\"> },</span><br><span class=\"line\"> <span class=\"attr\">toolbox</span>: {</span><br><span class=\"line\"> <span class=\"attr\">show</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"attr\">orient</span>: <span class=\"string\">'vertical'</span>,</span><br><span class=\"line\"> <span class=\"attr\">left</span>: <span class=\"string\">'right'</span>,</span><br><span class=\"line\"> <span class=\"attr\">top</span>: <span class=\"string\">'center'</span>,</span><br><span class=\"line\"> <span class=\"attr\">feature</span>: {</span><br><span class=\"line\"> <span class=\"attr\">magicType</span>: { <span class=\"attr\">show</span>: <span class=\"literal\">true</span>, <span class=\"attr\">type</span>: [<span class=\"string\">'line'</span>, <span class=\"string\">'bar'</span>, <span class=\"string\">'stack'</span>, <span class=\"string\">'tiled'</span>] },</span><br><span class=\"line\"> <span class=\"attr\">restore</span>: { <span class=\"attr\">show</span>: <span class=\"literal\">true</span> },</span><br><span class=\"line\"> <span class=\"attr\">saveAsImage</span>: { <span class=\"attr\">show</span>: <span class=\"literal\">true</span> }</span><br><span class=\"line\"> }</span><br><span class=\"line\"> },</span><br><span class=\"line\"> <span class=\"attr\">dataZoom</span>: [ </span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"attr\">show</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"attr\">realtime</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"attr\">start</span>: <span class=\"number\">0</span>,</span><br><span class=\"line\"> <span class=\"attr\">end</span>: <span class=\"number\">100</span></span><br><span class=\"line\"> }</span><br><span class=\"line\"> ],</span><br><span class=\"line\"> <span class=\"attr\">tooltip</span>: {</span><br><span class=\"line\"> <span class=\"attr\">trigger</span>: <span class=\"string\">'axis'</span></span><br><span class=\"line\"> },</span><br><span class=\"line\"> <span class=\"attr\">xAxis</span>: {</span><br><span class=\"line\"> <span class=\"attr\">data</span>: result[<span class=\"string\">'attr'</span>]</span><br><span class=\"line\"> },</span><br><span class=\"line\"> <span class=\"attr\">yAxis</span>: {},</span><br><span class=\"line\"> <span class=\"attr\">series</span>: [{</span><br><span class=\"line\"> <span class=\"attr\">name</span>: <span class=\"string\">'AVG'</span>,</span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"string\">'bar'</span>,</span><br><span class=\"line\"> <span class=\"attr\">data</span>: result[<span class=\"string\">'AVG'</span>]</span><br><span class=\"line\"> },{</span><br><span class=\"line\"> <span class=\"attr\">name</span>: <span class=\"string\">'OBP'</span>,</span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"string\">'bar'</span>,</span><br><span class=\"line\"> <span class=\"attr\">data</span>: result[<span class=\"string\">'OBP'</span>]</span><br><span class=\"line\"> },{</span><br><span class=\"line\"> <span class=\"attr\">name</span>: <span class=\"string\">'SLG'</span>,</span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"string\">'bar'</span>,</span><br><span class=\"line\"> <span class=\"attr\">data</span>: result[<span class=\"string\">'SLG'</span>]</span><br><span class=\"line\"> }]</span><br><span class=\"line\"> };</span><br><span class=\"line\"> chart.<span class=\"title function_\">setOption</span>(option);</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">let</span> option_2 = {</span><br><span class=\"line\"> <span class=\"attr\">title</span>: {</span><br><span class=\"line\"> <span class=\"attr\">text</span>: <span class=\"string\">'其他數據'</span></span><br><span class=\"line\"> },</span><br><span class=\"line\"> <span class=\"attr\">tooltip</span>: {},</span><br><span class=\"line\"> <span class=\"attr\">legend</span>: {</span><br><span class=\"line\"> <span class=\"attr\">data</span>: [<span class=\"string\">'PA'</span>, <span class=\"string\">'AB'</span>, <span class=\"string\">'RBI'</span>, <span class=\"string\">'H'</span>, <span class=\"string\">'HR'</span>]</span><br><span class=\"line\"> },</span><br><span class=\"line\"> <span class=\"attr\">toolbox</span>: {</span><br><span class=\"line\"> <span class=\"attr\">show</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"attr\">orient</span>: <span class=\"string\">'vertical'</span>,</span><br><span class=\"line\"> <span class=\"attr\">left</span>: <span class=\"string\">'right'</span>,</span><br><span class=\"line\"> <span class=\"attr\">top</span>: <span class=\"string\">'center'</span>,</span><br><span class=\"line\"> <span class=\"attr\">feature</span>: {</span><br><span class=\"line\"> <span class=\"attr\">mark</span>: { <span class=\"attr\">show</span>: <span class=\"literal\">true</span> },</span><br><span class=\"line\"> <span class=\"attr\">dataView</span>: { <span class=\"attr\">show</span>: <span class=\"literal\">true</span>, <span class=\"attr\">readOnly</span>: <span class=\"literal\">false</span> },</span><br><span class=\"line\"> <span class=\"attr\">magicType</span>: { <span class=\"attr\">show</span>: <span class=\"literal\">true</span>, <span class=\"attr\">type</span>: [<span class=\"string\">'line'</span>, <span class=\"string\">'bar'</span>, <span class=\"string\">'stack'</span>, <span class=\"string\">'tiled'</span>] },</span><br><span class=\"line\"> <span class=\"attr\">restore</span>: { <span class=\"attr\">show</span>: <span class=\"literal\">true</span> },</span><br><span class=\"line\"> <span class=\"attr\">saveAsImage</span>: { <span class=\"attr\">show</span>: <span class=\"literal\">true</span> }</span><br><span class=\"line\"> }</span><br><span class=\"line\"> },</span><br><span class=\"line\"> <span class=\"attr\">dataZoom</span>: [</span><br><span class=\"line\"> {</span><br><span class=\"line\"> <span class=\"attr\">show</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"attr\">realtime</span>: <span class=\"literal\">true</span>,</span><br><span class=\"line\"> <span class=\"attr\">start</span>: <span class=\"number\">0</span>,</span><br><span class=\"line\"> <span class=\"attr\">end</span>: <span class=\"number\">100</span></span><br><span class=\"line\"> }</span><br><span class=\"line\"> ],</span><br><span class=\"line\"> <span class=\"attr\">tooltip</span>: {</span><br><span class=\"line\"> <span class=\"attr\">trigger</span>: <span class=\"string\">'axis'</span></span><br><span class=\"line\"> },</span><br><span class=\"line\"> <span class=\"attr\">xAxis</span>: {</span><br><span class=\"line\"> <span class=\"attr\">data</span>: result[<span class=\"string\">'attr'</span>]</span><br><span class=\"line\"> },</span><br><span class=\"line\"> <span class=\"attr\">yAxis</span>: {},</span><br><span class=\"line\"> <span class=\"attr\">series</span>: [{</span><br><span class=\"line\"> <span class=\"attr\">name</span>: <span class=\"string\">'PA'</span>,</span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"string\">'bar'</span>,</span><br><span class=\"line\"> <span class=\"attr\">data</span>: result[<span class=\"string\">'PA'</span>]</span><br><span class=\"line\"> }, {</span><br><span class=\"line\"> <span class=\"attr\">name</span>: <span class=\"string\">'AB'</span>,</span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"string\">'bar'</span>,</span><br><span class=\"line\"> <span class=\"attr\">data</span>: result[<span class=\"string\">'AB'</span>]</span><br><span class=\"line\"> }, {</span><br><span class=\"line\"> <span class=\"attr\">name</span>: <span class=\"string\">'H'</span>,</span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"string\">'bar'</span>,</span><br><span class=\"line\"> <span class=\"attr\">data</span>: result[<span class=\"string\">'H'</span>]</span><br><span class=\"line\"> }, {</span><br><span class=\"line\"> <span class=\"attr\">name</span>: <span class=\"string\">'RBI'</span>,</span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"string\">'bar'</span>,</span><br><span class=\"line\"> <span class=\"attr\">data</span>: result[<span class=\"string\">'RBI'</span>]</span><br><span class=\"line\"> }, {</span><br><span class=\"line\"> <span class=\"attr\">name</span>: <span class=\"string\">'HR'</span>,</span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"string\">'bar'</span>,</span><br><span class=\"line\"> <span class=\"attr\">data</span>: result[<span class=\"string\">'HR'</span>]</span><br><span class=\"line\"> }]</span><br><span class=\"line\"> };</span><br><span class=\"line\"> chart2.<span class=\"title function_\">setOption</span>(option_2);</span><br><span class=\"line\"> }</span><br><span class=\"line\"> });</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>","categories":["資料視覺化"],"tags":["Javacscript","echart"]},{"title":"[Python]Flask串接Firebase","url":"/2021/02/08/Python-Flask%E4%B8%B2%E6%8E%A5Firebase/","content":"<h2 id=\"Flask\"><a href=\"#Flask\" class=\"headerlink\" title=\"Flask\"></a>Flask</h2><p>首先用pip安裝Flask,接者創建一個<code>app.py</code>。</p>\n<span id=\"more\"></span>\n\n<p><code>app.py</code></p>\n<figure class=\"highlight plaintext\"><table><tr><td class=\"code\"><pre><span class=\"line\">import flask</span><br><span class=\"line\">from flask import render_template, url_for, redirect, request, jsonify, Response #之後會用到的</span><br><span class=\"line\"></span><br><span class=\"line\">app = flask.Flask(__name__)</span><br><span class=\"line\">app.config["DEBUG"] = True</span><br><span class=\"line\"></span><br><span class=\"line\">@app.route('/', methods=['GET'])</span><br><span class=\"line\">def index():</span><br><span class=\"line\"> return render_template('index.html')</span><br></pre></td></tr></table></figure>\n\n<p>接著下<code>python app.py</code>就可以執行了,但是這邊還沒創建Html檔,所以會報錯,因為使用了render_template,需要再創建一個templates資料夾,並在資料夾內創建<code>index.html</code></p>\n<p>回到網頁,就會看到全白的網站了。</p>\n<h2 id=\"Header\"><a href=\"#Header\" class=\"headerlink\" title=\"Header\"></a>Header</h2><p>未來可能會用到許多頁面,而這些頁面通常會共用一個header,所以我這邊將它獨立為一個<code>header.html</code>。</p>\n<p><code>header.html</code></p>\n<figure class=\"highlight html\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\"><!DOCTYPE <span class=\"keyword\">html</span>></span></span><br><span class=\"line\"><span class=\"tag\"><<span class=\"name\">html</span> <span class=\"attr\">lang</span>=<span class=\"string\">"en"</span>></span></span><br><span class=\"line\"><span class=\"tag\"><<span class=\"name\">head</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">meta</span> <span class=\"attr\">charset</span>=<span class=\"string\">"UTF-8"</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">meta</span> <span class=\"attr\">name</span>=<span class=\"string\">"viewport"</span> <span class=\"attr\">content</span>=<span class=\"string\">"width=device-width, initial-scale=1.0"</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">script</span> <span class=\"attr\">src</span>=<span class=\"string\">"https://cdn.bootcss.com/jquery/3.0.0/jquery.min.js"</span>></span><span class=\"tag\"></<span class=\"name\">script</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">title</span>></span>Document<span class=\"tag\"></<span class=\"name\">title</span>></span></span><br><span class=\"line\"><span class=\"tag\"></<span class=\"name\">head</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">body</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">nav</span> <span class=\"attr\">class</span>=<span class=\"string\">"navbar navbar-expand-lg navbar-light bg-light"</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">a</span> <span class=\"attr\">class</span>=<span class=\"string\">"navbar-brand"</span> <span class=\"attr\">href</span>=<span class=\"string\">"/"</span>></span>中職球員數據<span class=\"tag\"></<span class=\"name\">a</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">button</span> <span class=\"attr\">class</span>=<span class=\"string\">"navbar-toggler"</span> <span class=\"attr\">type</span>=<span class=\"string\">"button"</span> <span class=\"attr\">data-toggle</span>=<span class=\"string\">"collapse"</span> <span class=\"attr\">data-target</span>=<span class=\"string\">"#navbarNavAltMarkup"</span></span></span><br><span class=\"line\"><span class=\"tag\"> <span class=\"attr\">aria-controls</span>=<span class=\"string\">"navbarNavAltMarkup"</span> <span class=\"attr\">aria-expanded</span>=<span class=\"string\">"false"</span> <span class=\"attr\">aria-label</span>=<span class=\"string\">"Toggle navigation"</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">span</span> <span class=\"attr\">class</span>=<span class=\"string\">"navbar-toggler-icon"</span>></span><span class=\"tag\"></<span class=\"name\">span</span>></span></span><br><span class=\"line\"> <span class=\"tag\"></<span class=\"name\">button</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">div</span> <span class=\"attr\">class</span>=<span class=\"string\">"collapse navbar-collapse"</span> <span class=\"attr\">id</span>=<span class=\"string\">"navbarNavAltMarkup"</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">div</span> <span class=\"attr\">class</span>=<span class=\"string\">"navbar-nav"</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">a</span> <span class=\"attr\">class</span>=<span class=\"string\">"nav-item nav-link"</span> <span class=\"attr\">href</span>=<span class=\"string\">"/"</span>></span>首頁 <span class=\"tag\"><<span class=\"name\">span</span> <span class=\"attr\">class</span>=<span class=\"string\">"sr-only"</span>></span>(current)<span class=\"tag\"></<span class=\"name\">span</span>></span><span class=\"tag\"></<span class=\"name\">a</span>></span></span><br><span class=\"line\"> <span class=\"tag\"></<span class=\"name\">div</span>></span></span><br><span class=\"line\"> <span class=\"tag\"></<span class=\"name\">div</span>></span></span><br><span class=\"line\"> <span class=\"tag\"></<span class=\"name\">nav</span>></span></span><br><span class=\"line\"> <span class=\"tag\"></<span class=\"name\">body</span>></span></span><br><span class=\"line\"><span class=\"tag\"></<span class=\"name\">html</span>></span></span><br></pre></td></tr></table></figure>\n\n<blockquote>\n<p>這邊我使用了bootstrap來進行排版</p>\n</blockquote>\n<p>回到<code>index.html</code>,因為Flask支援jinja 2,讓我能直接引入header。 <a href=\"https://jinja.palletsprojects.com/en/2.11.x/\">官方文件</a></p>\n<p><code>index.html</code></p>\n<figure class=\"highlight html\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"meta\"><!DOCTYPE <span class=\"keyword\">html</span>></span></span><br><span class=\"line\"><span class=\"tag\"><<span class=\"name\">html</span> <span class=\"attr\">lang</span>=<span class=\"string\">"en"</span>></span></span><br><span class=\"line\"><span class=\"tag\"><<span class=\"name\">head</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">meta</span> <span class=\"attr\">charset</span>=<span class=\"string\">"UTF-8"</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">meta</span> <span class=\"attr\">name</span>=<span class=\"string\">"viewport"</span> <span class=\"attr\">content</span>=<span class=\"string\">"width=device-width, initial-scale=1.0"</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">title</span>></span>數據可視化<span class=\"tag\"></<span class=\"name\">title</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">link</span> <span class=\"attr\">rel</span>=<span class=\"string\">"stylesheet"</span> <span class=\"attr\">href</span>=<span class=\"string\">"https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"</span></span></span><br><span class=\"line\"><span class=\"tag\"> <span class=\"attr\">integrity</span>=<span class=\"string\">"sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z"</span> <span class=\"attr\">crossorigin</span>=<span class=\"string\">"anonymous"</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">script</span> <span class=\"attr\">src</span>=<span class=\"string\">"https://cdn.bootcss.com/jquery/3.0.0/jquery.min.js"</span>></span><span class=\"tag\"></<span class=\"name\">script</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">script</span> <span class=\"attr\">type</span>=<span class=\"string\">"text/javascript"</span> <span class=\"attr\">src</span>=<span class=\"string\">"https://assets.pyecharts.org/assets/echarts.min.js"</span>></span><span class=\"tag\"></<span class=\"name\">script</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">script</span> <span class=\"attr\">src</span>=<span class=\"string\">"https://code.jquery.com/jquery-3.3.1.slim.min.js"</span></span></span><br><span class=\"line\"><span class=\"tag\"> <span class=\"attr\">integrity</span>=<span class=\"string\">"sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"</span> <span class=\"attr\">crossorigin</span>=<span class=\"string\">"anonymous"</span>></span></span><br><span class=\"line\"> <span class=\"tag\"></<span class=\"name\">script</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">script</span> <span class=\"attr\">src</span>=<span class=\"string\">"https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"</span></span></span><br><span class=\"line\"><span class=\"tag\"> <span class=\"attr\">integrity</span>=<span class=\"string\">"sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"</span> <span class=\"attr\">crossorigin</span>=<span class=\"string\">"anonymous"</span>></span></span><br><span class=\"line\"> <span class=\"tag\"></<span class=\"name\">script</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">script</span> <span class=\"attr\">src</span>=<span class=\"string\">"https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"</span></span></span><br><span class=\"line\"><span class=\"tag\"> <span class=\"attr\">integrity</span>=<span class=\"string\">"sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"</span> <span class=\"attr\">crossorigin</span>=<span class=\"string\">"anonymous"</span>></span></span><br><span class=\"line\"> <span class=\"tag\"></<span class=\"name\">script</span>></span></span><br><span class=\"line\"><span class=\"tag\"></<span class=\"name\">head</span>></span></span><br><span class=\"line\"><span class=\"tag\"><<span class=\"name\">body</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">div</span> <span class=\"attr\">class</span>=<span class=\"string\">"container"</span>></span></span><br><span class=\"line\"> {% include 'header.html' %}</span><br><span class=\"line\"> <span class=\"tag\"></<span class=\"name\">div</span>></span></span><br><span class=\"line\"><span class=\"tag\"><<span class=\"name\">body</span>></span></span><br><span class=\"line\"><span class=\"tag\"><<span class=\"name\">html</span>></span></span><br></pre></td></tr></table></figure>\n<blockquote>\n<p>上面引入的script都是之後會用的</p>\n</blockquote>\n<h2 id=\"從Firebase取得資料\"><a href=\"#從Firebase取得資料\" class=\"headerlink\" title=\"從Firebase取得資料\"></a>從Firebase取得資料</h2><p>前面有介紹到如何連接Firebase,而連接的程式碼就放在<code>app.py</code>裡面</p>\n<figure class=\"highlight python\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">import</span> flask</span><br><span class=\"line\"><span class=\"keyword\">from</span> flask <span class=\"keyword\">import</span> render_template, url_for, redirect, request, jsonify, Response </span><br><span class=\"line\"></span><br><span class=\"line\">app = flask.Flask(__name__)</span><br><span class=\"line\">app.config[<span class=\"string\">"DEBUG"</span>] = <span class=\"literal\">True</span></span><br><span class=\"line\"></span><br><span class=\"line\">cred = credentials.Certificate(<span class=\"string\">'path/to/serviceAccount.json'</span>)</span><br><span class=\"line\">firebase_admin.initialize_app(cred)</span><br><span class=\"line\"></span><br><span class=\"line\">...</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">if</span> __name__ == <span class=\"string\">'__main__'</span>:</span><br><span class=\"line\"> app.run()</span><br></pre></td></tr></table></figure>\n\n<p>為了不讓<code>app.py</code>太過雜亂,所以我把取資料的程式碼獨立為<code>db_connect.py</code>,並且連同之前儲存資料的程式碼一起放進來。</p>\n<p>取得資料的方法非常簡單,指定好collection和document後,使用get()就能取得,取出來的資料可以用to_dict()轉成dict,讓Python好處理。</p>\n<p><code>db_connect.py</code></p>\n<figure class=\"highlight python\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">import</span> firebase_admin</span><br><span class=\"line\"><span class=\"keyword\">from</span> firebase_admin <span class=\"keyword\">import</span> credentials</span><br><span class=\"line\"><span class=\"keyword\">from</span> firebase_admin <span class=\"keyword\">import</span> firestore</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">def</span> <span class=\"title function_\">get_hitter_stat</span>(<span class=\"params\">player_name</span>):</span><br><span class=\"line\"> db = firestore.client()</span><br><span class=\"line\"> doc_ref = db.collection(<span class=\"string\">u'打者'</span>).document(<span class=\"built_in\">str</span>(player_name))</span><br><span class=\"line\"> doc = doc_ref.get()</span><br><span class=\"line\"> <span class=\"keyword\">if</span> doc.exists:</span><br><span class=\"line\"> <span class=\"keyword\">return</span> doc.to_dict()</span><br><span class=\"line\"> <span class=\"keyword\">else</span>:</span><br><span class=\"line\"> <span class=\"keyword\">return</span> <span class=\"literal\">False</span></span><br><span class=\"line\"> </span><br><span class=\"line\"><span class=\"keyword\">def</span> <span class=\"title function_\">store_month</span>(<span class=\"params\">data</span>):</span><br><span class=\"line\"> db = firestore.client()</span><br><span class=\"line\"> batch = db.batch()</span><br><span class=\"line\"> <span class=\"keyword\">for</span> player <span class=\"keyword\">in</span> data:</span><br><span class=\"line\"> doc_ref = db.collection(<span class=\"string\">u'打者'</span>).document(player[<span class=\"string\">'Name'</span>])</span><br><span class=\"line\"> <span class=\"keyword\">del</span> player[<span class=\"string\">'Name'</span>]</span><br><span class=\"line\"> batch.update(doc_ref, {<span class=\"string\">u'月份'</span>:player})</span><br><span class=\"line\"> batch.commit()</span><br></pre></td></tr></table></figure>\n\n<p>接著把<code>db_connect.py</code>import進<code>app.py</code></p>\n<h2 id=\"前端設置\"><a href=\"#前端設置\" class=\"headerlink\" title=\"前端設置\"></a>前端設置</h2><p>接著要先把<code>index.html</code>切出我要顯示出來的位置,首先選擇球員需要用兩個下拉式選單<code><select></code>,並用bootstrap稍微美化一下表單。</p>\n<figure class=\"highlight html\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"tag\"><<span class=\"name\">form</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">div</span> <span class=\"attr\">class</span>=<span class=\"string\">"row"</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">div</span> <span class=\"attr\">class</span>=<span class=\"string\">"form-group col-6"</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">select</span> <span class=\"attr\">name</span>=<span class=\"string\">"team"</span> <span class=\"attr\">id</span>=<span class=\"string\">"team"</span> <span class=\"attr\">class</span>=<span class=\"string\">"form-control"</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">option</span> <span class=\"attr\">value</span>=<span class=\"string\">"中信兄弟"</span>></span>中信兄弟<span class=\"tag\"></<span class=\"name\">option</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">option</span> <span class=\"attr\">value</span>=<span class=\"string\">"統一獅"</span>></span>統一獅<span class=\"tag\"></<span class=\"name\">option</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">option</span> <span class=\"attr\">value</span>=<span class=\"string\">"富邦悍將"</span>></span>富邦悍將<span class=\"tag\"></<span class=\"name\">option</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">option</span> <span class=\"attr\">value</span>=<span class=\"string\">"樂天桃猿"</span>></span>樂天桃猿<span class=\"tag\"></<span class=\"name\">option</span>></span></span><br><span class=\"line\"> <span class=\"tag\"></<span class=\"name\">select</span>></span></span><br><span class=\"line\"> <span class=\"tag\"></<span class=\"name\">div</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">div</span> <span class=\"attr\">class</span>=<span class=\"string\">"form-group col-6"</span>></span></span><br><span class=\"line\"> <span class=\"tag\"><<span class=\"name\">select</span> <span class=\"attr\">name</span>=<span class=\"string\">"player"</span> <span class=\"attr\">id</span>=<span class=\"string\">"player"</span> <span class=\"attr\">class</span>=<span class=\"string\">"form-control"</span>></span></span><br><span class=\"line\"> <span class=\"tag\"></<span class=\"name\">select</span>></span></span><br><span class=\"line\"> <span class=\"tag\"></<span class=\"name\">div</span>></span></span><br><span class=\"line\"> <span class=\"tag\"></<span class=\"name\">div</span>></span></span><br><span class=\"line\"><span class=\"tag\"></<span class=\"name\">form</span>></span></span><br></pre></td></tr></table></figure>\n\n<p>並且我想要將這兩個下拉式選單連動,也就是當我選擇中信兄弟時,player的選單會顯示出中信兄弟的球員,這邊我需要用到select的onchange觸發ajax讓Flask傳球員名單過來,先寫一個js function。</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">function</span> <span class=\"title function_\">select_team</span>(<span class=\"params\"></span>){</span><br><span class=\"line\"> <span class=\"keyword\">let</span> team = $(<span class=\"string\">'#team'</span>).<span class=\"title function_\">val</span>();</span><br><span class=\"line\"> $.<span class=\"title function_\">ajax</span>({</span><br><span class=\"line\"> <span class=\"attr\">type</span>: <span class=\"string\">'POST'</span>,</span><br><span class=\"line\"> <span class=\"attr\">url</span>: <span class=\"string\">"/select_team"</span>,</span><br><span class=\"line\"> <span class=\"attr\">data</span>: {<span class=\"string\">"team"</span>:team},</span><br><span class=\"line\"> <span class=\"attr\">success</span>: <span class=\"keyword\">function</span>(<span class=\"params\">result</span>){</span><br><span class=\"line\"> $(<span class=\"string\">'#player'</span>).<span class=\"title function_\">empty</span>();</span><br><span class=\"line\"> $(<span class=\"string\">'#player'</span>).<span class=\"title function_\">append</span>($(<span class=\"string\">"<option/>"</span>, {</span><br><span class=\"line\"> <span class=\"attr\">value</span>: <span class=\"string\">'選擇球員'</span>,</span><br><span class=\"line\"> <span class=\"attr\">text</span>: <span class=\"string\">'選擇球員'</span></span><br><span class=\"line\"> }));</span><br><span class=\"line\"> <span class=\"keyword\">for</span>(<span class=\"keyword\">let</span> i = <span class=\"number\">0</span>; i < result.<span class=\"property\">length</span> ;i++){</span><br><span class=\"line\"> $(<span class=\"string\">'#player'</span>).<span class=\"title function_\">append</span>($(<span class=\"string\">"<option/>"</span>,{</span><br><span class=\"line\"> <span class=\"attr\">value</span>: result[i],</span><br><span class=\"line\"> <span class=\"attr\">text</span>: result[i]</span><br><span class=\"line\"> }));</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\"> });</span><br><span class=\"line\">}</span><br></pre></td></tr></table></figure>\n<p>這邊我用POST的方式,而data是前端必須傳給後端的資料,讓後端能判斷,<strong>empty很重要</strong>(de很久才想到),而for迴圈則是加入球員,前端的程式碼寫好了,接著回到<code>app.py</code>,我需要設置一個<code>/select_team</code>才能接起來。</p>\n<p><code>app.py</code></p>\n<figure class=\"highlight python\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">from</span> select_player <span class=\"keyword\">import</span> getplayer</span><br><span class=\"line\"><span class=\"meta\">@app.route(<span class=\"params\"><span class=\"string\">'/select_team'</span>, methods=[<span class=\"string\">'POST'</span>]</span>)</span></span><br><span class=\"line\"><span class=\"keyword\">def</span> <span class=\"title function_\">select_team</span>():</span><br><span class=\"line\"> team = request.form.getlist(<span class=\"string\">'team'</span>)</span><br><span class=\"line\"> player_list = getplayer(team[<span class=\"number\">0</span>])</span><br><span class=\"line\"> <span class=\"keyword\">return</span> jsonify(player_list)</span><br></pre></td></tr></table></figure>\n<p><strong>getlist進來會是list</strong></p>\n<p><code>select_player.py</code></p>\n<figure class=\"highlight python\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"comment\"># coding: utf-8</span></span><br><span class=\"line\"><span class=\"keyword\">import</span> csv</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">def</span> <span class=\"title function_\">getplayer</span>(<span class=\"params\">team</span>):</span><br><span class=\"line\"> <span class=\"keyword\">with</span> <span class=\"built_in\">open</span>(<span class=\"string\">'player_ID.csv'</span>, <span class=\"string\">'r'</span>,encoding=<span class=\"string\">'utf8'</span>) <span class=\"keyword\">as</span> csvfile:</span><br><span class=\"line\"> rows = csv.DictReader(csvfile)</span><br><span class=\"line\"> player_list = []</span><br><span class=\"line\"> <span class=\"keyword\">if</span> team == <span class=\"string\">'中信兄弟'</span>:</span><br><span class=\"line\"> <span class=\"keyword\">for</span> row <span class=\"keyword\">in</span> rows:</span><br><span class=\"line\"> <span class=\"keyword\">if</span> row[<span class=\"string\">'Team ID'</span>] == <span class=\"string\">'E02'</span>:</span><br><span class=\"line\"> player_list.append(row[<span class=\"string\">'Name'</span>])</span><br><span class=\"line\"> <span class=\"keyword\">elif</span> team == <span class=\"string\">'統一獅'</span>:</span><br><span class=\"line\"> <span class=\"keyword\">for</span> row <span class=\"keyword\">in</span> rows:</span><br><span class=\"line\"> <span class=\"keyword\">if</span> row[<span class=\"string\">'Team ID'</span>] == <span class=\"string\">'L01'</span>:</span><br><span class=\"line\"> player_list.append(row[<span class=\"string\">'Name'</span>])</span><br><span class=\"line\"> <span class=\"keyword\">elif</span> team == <span class=\"string\">'富邦悍將'</span>:</span><br><span class=\"line\"> <span class=\"keyword\">for</span> row <span class=\"keyword\">in</span> rows:</span><br><span class=\"line\"> <span class=\"keyword\">if</span> row[<span class=\"string\">'Team ID'</span>] == <span class=\"string\">'B04'</span>:</span><br><span class=\"line\"> player_list.append(row[<span class=\"string\">'Name'</span>])</span><br><span class=\"line\"> <span class=\"keyword\">elif</span> team == <span class=\"string\">'樂天桃猿'</span>:</span><br><span class=\"line\"> <span class=\"keyword\">for</span> row <span class=\"keyword\">in</span> rows:</span><br><span class=\"line\"> <span class=\"keyword\">if</span> row[<span class=\"string\">'Team ID'</span>] == <span class=\"string\">'AJL011'</span>:</span><br><span class=\"line\"> player_list.append(row[<span class=\"string\">'Name'</span>])</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">return</span> player_list</span><br></pre></td></tr></table></figure>\n\n<p>但是現在在第一次進網頁時,第二欄會是空的,我希望在載入好時能先執行一遍,這邊我用了ready來達成</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"code\"><pre><span class=\"line\">$(<span class=\"variable language_\">document</span>).<span class=\"title function_\">ready</span>(<span class=\"title function_\">select_team</span>());</span><br></pre></td></tr></table></figure>\n\n","categories":["資料視覺化"],"tags":["Python","Firebase","棒球分析","中職"]},{"title":"[Python]爬蟲","url":"/2021/02/03/Python-%E7%88%AC%E8%9F%B2/","content":"<h2 id=\"前言\"><a href=\"#前言\" class=\"headerlink\" title=\"前言\"></a>前言</h2><p>這篇文章主要是記錄我的學習歷程,以棒球為主題搭建一個數據查詢的網站,從取得資料到架設網站,過程會使用Python來爬取及架設網站。</p>\n<span id=\"more\"></span>\n<blockquote>\n<p>本系列是整理之前在鐵人賽的文章</p>\n</blockquote>\n<h2 id=\"取得數據\"><a href=\"#取得數據\" class=\"headerlink\" title=\"取得數據\"></a>取得數據</h2><p>數據的來源為中職的<a href=\"http://www.cpbl.com.tw/stats/all.html\">官網</a><br>但因為中職官網沒有進階數據如OPS+等,會從<a href=\"http://my.cpblstats.com/\">CPBL stat</a>來取得比較進階的數據</p>\n<p>首先要做的是逐月分的表現,只有中職官網有數據,首先觀察球員個人頁面的url</p>\n<p>林安可頁面<br><code>http://www.cpbl.com.tw/player/apart.html?player_id=k429&teamno=L01&year=2020&type=05</code></p>\n<p>蘇智傑頁面<br><code>http://www.cpbl.com.tw/player/apart.html?player_id=H594&teamno=L01&year=2020&type=05</code></p>\n<p>比較一下發現type與year是不變的,剩下兩個就是需要的變數,必須想辦法取得player_id與teamno,回到全紀錄查詢,按下F12發現在<td>下的<a>可以取得,接著決定要如何儲存資料,而這邊決定用csv來儲存。</p>\n<figure class=\"highlight python\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">import</span> requests</span><br><span class=\"line\"><span class=\"keyword\">from</span> bs4 <span class=\"keyword\">import</span> BeautifulSoup</span><br><span class=\"line\"><span class=\"keyword\">import</span> csv</span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"keyword\">def</span> <span class=\"title function_\">get_all_player</span>():</span><br><span class=\"line\"> url = <span class=\"string\">"http://www.cpbl.com.tw/stats/all.html?&game_type=01&&stat=pbat&year=2020&online=1&per_page="</span></span><br><span class=\"line\"></span><br><span class=\"line\"> fieldnames = [<span class=\"string\">'Name'</span>,<span class=\"string\">'ID'</span>,<span class=\"string\">'Team ID'</span>]</span><br><span class=\"line\"> <span class=\"keyword\">with</span> <span class=\"built_in\">open</span>(<span class=\"string\">"player_ID.csv"</span>, <span class=\"string\">'w'</span>) <span class=\"keyword\">as</span> csvfile:</span><br><span class=\"line\"> writer = csv.DictWriter(csvfile, fieldnames=fieldnames)</span><br><span class=\"line\"> writer.writeheader()</span><br><span class=\"line\"> <span class=\"keyword\">for</span> i <span class=\"keyword\">in</span> <span class=\"built_in\">range</span>(<span class=\"number\">5</span>):</span><br><span class=\"line\"> url = url</span><br><span class=\"line\"> </span><br><span class=\"line\"> <span class=\"built_in\">print</span>(<span class=\"string\">"爬取"</span> + url + <span class=\"built_in\">str</span>(i+<span class=\"number\">1</span>) + <span class=\"string\">"中"</span>)</span><br><span class=\"line\"> r = requests.get(url + <span class=\"built_in\">str</span>(i+<span class=\"number\">1</span>))</span><br><span class=\"line\"></span><br><span class=\"line\"> soup = BeautifulSoup(r.text, <span class=\"string\">'html.parser'</span>)</span><br><span class=\"line\"></span><br><span class=\"line\"> td = soup.select(<span class=\"string\">"td a"</span>)</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">for</span> j <span class=\"keyword\">in</span> <span class=\"built_in\">range</span>(<span class=\"built_in\">len</span>(td)):</span><br><span class=\"line\"> player_id = {}</span><br><span class=\"line\"> temp = td[j][<span class=\"string\">"href"</span>].split(<span class=\"string\">"?"</span>)[<span class=\"number\">1</span>].split(<span class=\"string\">"&"</span>)</span><br><span class=\"line\"> player_id[<span class=\"string\">'Name'</span>] = td[j].text.strip()</span><br><span class=\"line\"> player_id[<span class=\"string\">'ID'</span>] = temp[<span class=\"number\">0</span>].split(<span class=\"string\">"="</span>)[<span class=\"number\">1</span>]</span><br><span class=\"line\"> player_id[<span class=\"string\">'Team ID'</span>] = temp[<span class=\"number\">1</span>].split(<span class=\"string\">"="</span>)[<span class=\"number\">1</span>]</span><br><span class=\"line\"> writer.writerow(player_id)</span><br></pre></td></tr></table></figure>\n\n<p>有了ID後,接著要取得各個月份的數據。</p>\n<p>打開選手頁面,這個表就是目標<br><img src=\"https://i.imgur.com/Lqt1zp4.png\"><br>按下F12觀察,這個表是table來排版的<br>並且在數據的部分有加class<br>找到了目標位置就可以開始解析</p>\n<figure class=\"highlight python\"><table><tr><td class=\"code\"><pre><span class=\"line\">player_url = <span class=\"string\">"http://www.cpbl.com.tw/players/apart.html?year=2020&type=05&"</span></span><br><span class=\"line\"><span class=\"keyword\">with</span> <span class=\"built_in\">open</span>(<span class=\"string\">'player_ID.csv'</span>, <span class=\"string\">'r'</span>) <span class=\"keyword\">as</span> csvfile:</span><br><span class=\"line\"> rows = csv.DictReader(csvfile)</span><br><span class=\"line\"> <span class=\"keyword\">for</span> row <span class=\"keyword\">in</span> rows:</span><br><span class=\"line\"> player_url = player_url + <span class=\"string\">'player_id='</span> + <span class=\"built_in\">str</span>(row[<span class=\"string\">'ID'</span>]) + <span class=\"string\">'&teamno='</span> + <span class=\"built_in\">str</span>(row[<span class=\"string\">'Team ID'</span>])</span><br><span class=\"line\"> res = requests.get(player_url)</span><br><span class=\"line\"> soup = BeautifulSoup(res.text, <span class=\"string\">'html.parser'</span>)</span><br><span class=\"line\"> player_td = soup.select(<span class=\"string\">".display_a1"</span>)</span><br><span class=\"line\"> month = soup.select(<span class=\"string\">"td"</span>)</span><br><span class=\"line\"> month = soup.select(<span class=\"string\">"tr > td:nth-of-type(1)"</span>)</span><br><span class=\"line\"> month.remove(month[<span class=\"number\">0</span>])</span><br><span class=\"line\"> month.remove(month[<span class=\"number\">0</span>])</span><br><span class=\"line\"></span><br><span class=\"line\"> team = soup.select(<span class=\"string\">'span'</span>)</span><br><span class=\"line\"></span><br><span class=\"line\"> player_info, avg_list, OBP_list, SLG_list, PA_list, AB_list, RBI_list, H_list, HR_list = {</span><br><span class=\"line\"> }, {}, {}, {}, {}, {}, {}, {},{}</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">for</span> i <span class=\"keyword\">in</span> <span class=\"built_in\">range</span>(<span class=\"built_in\">len</span>(month)):</span><br><span class=\"line\"> avg_list[month[i].text] = player_td[<span class=\"number\">19</span> + i*<span class=\"number\">10</span>].text</span><br><span class=\"line\"> OBP_list[month[i].text] = player_td[<span class=\"number\">17</span> + i*<span class=\"number\">10</span>].text</span><br><span class=\"line\"> SLG_list[month[i].text] = player_td[<span class=\"number\">18</span> + i*<span class=\"number\">10</span>].text</span><br><span class=\"line\"> PA_list[month[i].text] = player_td[<span class=\"number\">10</span> + i*<span class=\"number\">10</span>].text</span><br><span class=\"line\"> AB_list[month[i].text] = player_td[<span class=\"number\">11</span> + i*<span class=\"number\">10</span>].text</span><br><span class=\"line\"> RBI_list[month[i].text] = player_td[<span class=\"number\">12</span> + i*<span class=\"number\">10</span>].text</span><br><span class=\"line\"> H_list[month[i].text] = player_td[<span class=\"number\">13</span>+i*<span class=\"number\">10</span>].text</span><br><span class=\"line\"> HR_list[month[i].text] = player_td[<span class=\"number\">14</span>+i*<span class=\"number\">10</span>].text</span><br><span class=\"line\"></span><br><span class=\"line\"> player_info[player_td[<span class=\"number\">9</span>].text] = avg_list</span><br><span class=\"line\"> player_info[player_td[<span class=\"number\">7</span>].text] = OBP_list</span><br><span class=\"line\"> player_info[player_td[<span class=\"number\">8</span>].text] = SLG_list</span><br><span class=\"line\"> player_info[player_td[<span class=\"number\">0</span>].text] = PA_list</span><br><span class=\"line\"> player_info[player_td[<span class=\"number\">1</span>].text] = AB_list</span><br><span class=\"line\"> player_info[player_td[<span class=\"number\">2</span>].text] = RBI_list</span><br><span class=\"line\"> player_info[player_td[<span class=\"number\">3</span>].text] = H_list</span><br><span class=\"line\"> player_info[player_td[<span class=\"number\">4</span>].text] = HR_list</span><br></pre></td></tr></table></figure>\n<blockquote>\n<p>這邊寫得很醜,<del>但我懶得改了</del><br>下個數據會用好一點的方法</p>\n</blockquote>\n<p>資料爬下來了,但是如果要進行繪圖的話還必須解決月份不一致的問題,有些選手可能一整個月都沒出賽,或是新秀升到一軍,導致長度不一,我這邊用一個長度為8的list來存(因為賽季長度的關係最多8個月)。</p>\n<figure class=\"highlight python\"><table><tr><td class=\"code\"><pre><span class=\"line\">total_info = {}</span><br><span class=\"line\"><span class=\"keyword\">for</span> info_type <span class=\"keyword\">in</span> player_info:</span><br><span class=\"line\"> info = [<span class=\"string\">'0'</span>, <span class=\"string\">'0'</span>, <span class=\"string\">'0'</span>, <span class=\"string\">'0'</span>, <span class=\"string\">'0'</span>, <span class=\"string\">'0'</span>, <span class=\"string\">'0'</span>, <span class=\"string\">'0'</span>]</span><br><span class=\"line\"> <span class=\"keyword\">for</span> data <span class=\"keyword\">in</span> player_info[info_type]:</span><br><span class=\"line\"> n = attr.index(data)</span><br><span class=\"line\"> info[n] = player_info[info_type][data]</span><br><span class=\"line\"> total_info[info_type] = info</span><br><span class=\"line\">total_info[<span class=\"string\">'Name'</span>] = row[<span class=\"string\">'Name'</span>]</span><br></pre></td></tr></table></figure>\n\n<p>到這邊各月份的數據都爬下來了,小缺點是爬取速度還需要再加強,接著會優化這隻爬蟲。</p>\n","categories":["資料視覺化"],"tags":["Python","棒球分析","中職","爬蟲"]},{"title":"[Vue筆記]建立第一個專案","url":"/2021/03/03/Vue%E7%AD%86%E8%A8%98-%E5%BB%BA%E7%AB%8B%E7%AC%AC%E4%B8%80%E5%80%8B%E5%B0%88%E6%A1%88/","content":"<h2 id=\"相關套件\"><a href=\"#相關套件\" class=\"headerlink\" title=\"相關套件\"></a>相關套件</h2><ul>\n<li>node.js</li>\n<li>vue cli</li>\n</ul>\n<span id=\"more\"></span>\n<h2 id=\"開始專案\"><a href=\"#開始專案\" class=\"headerlink\" title=\"開始專案\"></a>開始專案</h2><p>在command line輸入</p>\n<figure class=\"highlight xml\"><table><tr><td class=\"code\"><pre><span class=\"line\">vue init webpack <span class=\"tag\"><<span class=\"name\">project</span> <span class=\"attr\">name</span>></span></span><br></pre></td></tr></table></figure>\n\n<p>vue會自動建立一個資料夾,初始化完後移動到資料夾內,並用npm安裝相關套件</p>\n<figure class=\"highlight cmake\"><table><tr><td class=\"code\"><pre><span class=\"line\">cd <<span class=\"keyword\">project</span> name></span><br><span class=\"line\">npm <span class=\"keyword\">install</span></span><br></pre></td></tr></table></figure>\n\n<p>最後輸入</p>\n<figure class=\"highlight routeros\"><table><tr><td class=\"code\"><pre><span class=\"line\">npm <span class=\"built_in\">run</span> dev</span><br></pre></td></tr></table></figure>\n\n<p>就可以在<code>localhost:8080</code>看到初始的畫面了</p>\n<h2 id=\"修改頁面\"><a href=\"#修改頁面\" class=\"headerlink\" title=\"修改頁面\"></a>修改頁面</h2><p>在開發的時候只需要修改<code>/src</code>底下的檔案就好,現在的<code>/src</code>檔案結構為</p>\n<figure class=\"highlight stylus\"><table><tr><td class=\"code\"><pre><span class=\"line\">.</span><br><span class=\"line\">├── App<span class=\"selector-class\">.vue</span></span><br><span class=\"line\">├── assets</span><br><span class=\"line\">│ └── logo<span class=\"selector-class\">.png</span></span><br><span class=\"line\">├── components</span><br><span class=\"line\">│ └── HelloWorld<span class=\"selector-class\">.vue</span></span><br><span class=\"line\">├── <span class=\"selector-tag\">main</span><span class=\"selector-class\">.js</span></span><br><span class=\"line\">└── router</span><br><span class=\"line\"> └── index.js</span><br></pre></td></tr></table></figure>\n\n<p>現在先開啟<code>/components/HelloWorld.vue</code>,可以看到<code><script></code>裡有宣告data的區塊,修改<code>msg</code>的值網頁上的文字就會隨著修改。</p>\n<p>接著我想要讓使用者輸入值,然後顯示在網頁上,這會用到<code>v-model</code>,也就是需要先宣告一個input和變數</p>\n<figure class=\"highlight plaintext\"><table><tr><td class=\"code\"><pre><span class=\"line\"><template></span><br><span class=\"line\"> <div class="hello"></span><br><span class=\"line\"> <h1>{{ msg }}</h1> </span><br><span class=\"line\"> <input type="text" v-model="hello"></span><br><span class=\"line\"> <h2>{{ hello }}</h2></span><br><span class=\"line\"> </div></span><br><span class=\"line\"></template></span><br></pre></td></tr></table></figure>\n\n<blockquote>\n<p>template其它的程式碼都刪掉了</p>\n</blockquote>\n<p>接著在<code><script></code>內宣告hello</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"code\"><pre><span class=\"line\"><script></span><br><span class=\"line\"><span class=\"keyword\">export</span> <span class=\"keyword\">default</span> {</span><br><span class=\"line\"> <span class=\"attr\">name</span>: <span class=\"string\">'HelloWorld'</span>,</span><br><span class=\"line\"> data () {</span><br><span class=\"line\"> <span class=\"keyword\">return</span> {</span><br><span class=\"line\"> <span class=\"attr\">msg</span>: <span class=\"string\">'Welcome to Your Vue.js App'</span>,</span><br><span class=\"line\"> <span class=\"attr\">hello</span>: <span class=\"string\">'hello'</span></span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br><span class=\"line\"></script></span><br></pre></td></tr></table></figure>\n\n<p>這樣就完成了,修改完網頁會自動更新,不需要重整或重新輸入指令。</p>\n<h2 id=\"computed屬性\"><a href=\"#computed屬性\" class=\"headerlink\" title=\"computed屬性\"></a>computed屬性</h2><p><a href=\"https://cn.vuejs.org/v2/guide/computed.html\">官方文件</a></p>\n<p>如果想要將輸入得值做計算可以直接</p>\n<figure class=\"highlight plaintext\"><table><tr><td class=\"code\"><pre><span class=\"line\"><template></span><br><span class=\"line\"> <div class="hello"></span><br><span class=\"line\"> <h1>{{ msg }}</h1> </span><br><span class=\"line\"> <input type="text" v-model="num"></span><br><span class=\"line\"> <h2>{{ num * 100 }}</h2></span><br><span class=\"line\"> </div></span><br><span class=\"line\"></template></span><br></pre></td></tr></table></figure>\n\n<p>但如果要做複雜的計算,<code>computed</code>可以宣告一個function來處理,方便許多</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"code\"><pre><span class=\"line\"><template></span><br><span class=\"line\"> <span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">div</span> <span class=\"attr\">class</span>=<span class=\"string\">"hello"</span>></span></span></span><br><span class=\"line\"><span class=\"language-xml\"> 輸入值*100 <span class=\"tag\"><<span class=\"name\">input</span> <span class=\"attr\">type</span>=<span class=\"string\">"number"</span> <span class=\"attr\">v-model</span>=<span class=\"string\">"num"</span>></span></span></span><br><span class=\"line\"><span class=\"language-xml\"> <span class=\"tag\"><<span class=\"name\">h2</span>></span>{{ num * 100 }}<span class=\"tag\"></<span class=\"name\">h2</span>></span></span></span><br><span class=\"line\"><span class=\"language-xml\"> <span class=\"tag\"><<span class=\"name\">h2</span>></span>{{ new_num }}<span class=\"tag\"></<span class=\"name\">h2</span>></span></span></span><br><span class=\"line\"><span class=\"language-xml\"> <span class=\"tag\"></<span class=\"name\">div</span>></span></span></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"></<span class=\"name\">template</span>></span></span></span><br><span class=\"line\"></span><br><span class=\"line\"><span class=\"language-xml\"><span class=\"tag\"><<span class=\"name\">script</span>></span><span class=\"language-javascript\"></span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"><span class=\"keyword\">export</span> <span class=\"keyword\">default</span> {</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"> <span class=\"attr\">name</span>: <span class=\"string\">'HelloWorld'</span>,</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"> data () {</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"> <span class=\"keyword\">return</span> {</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"> <span class=\"attr\">num</span>: <span class=\"number\">0</span></span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"> }</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"> },</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"> <span class=\"attr\">computed</span>: {</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"> <span class=\"attr\">new_num</span>: <span class=\"keyword\">function</span> (<span class=\"params\"></span>) {</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"> <span class=\"keyword\">return</span> <span class=\"variable language_\">this</span>.<span class=\"property\">num</span> * <span class=\"number\">100</span></span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"> }</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"> }</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\">}</span></span></span><br><span class=\"line\"><span class=\"language-javascript\"><span class=\"language-xml\"></span><span class=\"tag\"></<span class=\"name\">script</span>></span></span></span><br></pre></td></tr></table></figure>\n\n<h3 id=\"利用compute做出簡單的加減\"><a href=\"#利用compute做出簡單的加減\" class=\"headerlink\" title=\"利用compute做出簡單的加減\"></a>利用compute做出簡單的加減</h3><p>跟前面的例子差不多,但是在<code>+</code>的運算下會是字串加減,像是 1+ 1 = 11,所以在做數字運算的時候,需要轉成int</p>\n<p>完整程式碼</p>\n<figure class=\"highlight javascript\"><table><tr><td class=\"code\"><pre><span class=\"line\"><template></span><br><span class=\"line\"> <div class="hello"></span><br><span class=\"line\"> <input type="number" v-model="num"></span><br><span class=\"line\"> +<input type="number" v-model.number="plus"></span><br><span class=\"line\"> -<input type="number" v-model="minus"></span><br><span class=\"line\"> 結果: {{ res }}</span><br><span class=\"line\"> </div></span><br><span class=\"line\"></template></span><br><span class=\"line\"></span><br><span class=\"line\"><script></span><br><span class=\"line\">export default {</span><br><span class=\"line\"> name: 'HelloWorld',</span><br><span class=\"line\"> data () {</span><br><span class=\"line\"> return {</span><br><span class=\"line\"> num: 0,</span><br><span class=\"line\"> plus: 0,</span><br><span class=\"line\"> minus: 0</span><br><span class=\"line\"> }</span><br><span class=\"line\"> },</span><br><span class=\"line\"> computed: {</span><br><span class=\"line\"> res () {</span><br><span class=\"line\"> return parseInt(this.num) + parseInt(this.plus) - parseInt(this.minus)</span><br><span class=\"line\"> }</span><br><span class=\"line\"> }</span><br><span class=\"line\">}</span><br><span class=\"line\"></script></span><br></pre></td></tr></table></figure>\n\n<p>結果<br><img src=\"https://i.imgur.com/1PME0l7.png\"></p>\n<p>接著會做些小專案來練習</p>\n","categories":["Vue筆記"],"tags":["Vue","Javascript"]},{"title":"[Python]資料存進Firebase","url":"/2021/02/05/Python-%E8%B3%87%E6%96%99%E5%AD%98%E9%80%B2Firebase/","content":"<h2 id=\"Firebase\"><a href=\"#Firebase\" class=\"headerlink\" title=\"Firebase\"></a>Firebase</h2><p>這邊只會用到Firebase的Cloud Firestore功能,<a href=\"https://firebase.google.com/docs/firestore?authuser=0\">官方文件</a>。</p>\n<span id=\"more\"></span>\n\n<p>之後搭建網站將會使用Flask,所以在這邊我們使用Python來串接,創建好自己的應用後,取得私鑰的json檔案,接者就可以連接到Firebase了。</p>\n<figure class=\"highlight plaintext\"><table><tr><td class=\"code\"><pre><span class=\"line\">import firebase_admin</span><br><span class=\"line\">from firebase_admin import credentials</span><br><span class=\"line\">from firebase_admin import firestore</span><br><span class=\"line\"></span><br><span class=\"line\"># Use a service account</span><br><span class=\"line\">cred = credentials.Certificate('path/to/serviceAccount.json')</span><br><span class=\"line\">firebase_admin.initialize_app(cred)</span><br><span class=\"line\"></span><br><span class=\"line\">db = firestore.client()</span><br></pre></td></tr></table></figure>\n\n<p>Firebase是No SQL,我們需要創建collection和document,這邊我將打者設為一個collection,每位選手為一個document,底下有選手的各個資料。</p>\n<figure class=\"highlight python\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">def</span> <span class=\"title function_\">store_month</span>(<span class=\"params\">data</span>):</span><br><span class=\"line\"> batch = db.batch()</span><br><span class=\"line\"></span><br><span class=\"line\"> <span class=\"keyword\">for</span> player <span class=\"keyword\">in</span> data:</span><br><span class=\"line\"> doc_ref = db.collection(<span class=\"string\">u'打者'</span>).document(player[<span class=\"string\">'Name'</span>])</span><br><span class=\"line\"> <span class=\"keyword\">del</span> player[<span class=\"string\">'Name'</span>]</span><br><span class=\"line\"> batch.update(doc_ref, {<span class=\"string\">u'月份'</span>:player})</span><br><span class=\"line\"> batch.commit()</span><br></pre></td></tr></table></figure>\n\n<p>這段程式碼我使用了batch,batch的好處在於只需要用一個request就能寫入多筆資料(單次上限為500),寫入時使用update則是因為有些球員的資料是不需要更新的。</p>\n<p><img src=\"https://i.imgur.com/bFtSS8v.png\"></p>\n<blockquote>\n<p>儲存成功的樣子</p>\n</blockquote>\n<p>接著讓爬蟲呼叫這個function就可以寫入了。</p>\n","categories":["資料視覺化"],"tags":["Python","Firebase","棒球分析","中職","爬蟲"]},{"title":"使用Docker 運行 Ubuntu","url":"/2019/09/23/%E4%BD%BF%E7%94%A8Docker-%E9%81%8B%E8%A1%8C-Ubuntu/","content":"<figure class=\"highlight\"><table><tr><td class=\"code\"><pre><span class=\"line\">環境:macOS</span><br></pre></td></tr></table></figure>\n\n<h2 id=\"建立Container\"><a href=\"#建立Container\" class=\"headerlink\" title=\"建立Container\"></a>建立Container</h2><p><code>$ docker run --name MyUbuntu -dt ubuntu</code></p>\n<p><code>docker run</code>會由image建立contaniner</p>\n<p>參數定義</p>\n<ul>\n<li><code>--name</code>: 命名container,上面那行指令我們將container命名成<code>MyUbuntu</code>,若省略,會隨機命名</li>\n<li><code>-d</code>:建立 container 後,就脫離目前 process</li>\n<li><code>-t</code>:預設執行 /bin/bash process,為了讓 container 啟動後不會立即停止</li>\n<li>ubuntu:官方image名字</li>\n</ul>\n<span id=\"more\"></span>\n<p><strong>一個container一個process</strong></p>\n<p>而process執行完container會自動釋放<br>因此加上<code>-t</code>使container執行<code>bash</code>,讓container不會自動釋放</p>\n<h2 id=\"進入Ubuntu\"><a href=\"#進入Ubuntu\" class=\"headerlink\" title=\"進入Ubuntu\"></a>進入Ubuntu</h2><p><code>$ docker exec -it MyUbuntu bash</code></p>\n<p><code>docker exec</code>對執行中的container下指令</p>\n<ul>\n<li>i:interactive,可對 terminal 輸入資料</li>\n<li>t:terminal,可對 terminal 顯示資料</li>\n<li>MyUbuntu : container 名稱</li>\n<li>bash : 對 container 下的指令</li>\n</ul>\n","tags":["docker","Ubuntu"]},{"title":"資料庫實作","url":"/2021/01/24/%E8%B3%87%E6%96%99%E5%BA%AB-%E5%AF%A6%E4%BD%9C/","content":"<h2 id=\"資料庫-實作\"><a href=\"#資料庫-實作\" class=\"headerlink\" title=\"資料庫(實作)\"></a>資料庫(實作)</h2><h3 id=\"SQL-基本類型\"><a href=\"#SQL-基本類型\" class=\"headerlink\" title=\"SQL 基本類型\"></a>SQL 基本類型</h3><ul>\n<li>char(n):用來存放固定長度為n的字串資料</li>\n<li>varchar(n):用來存放最大長度為n的字串資料,實際儲存長度會依資料量而調整</li>\n<li>int:用來存放整數資料,最大可存放長度為4位元</li>\n<li>smallint:用來存放整數資料,最大可存放長度為2位元</li>\n<li>numeric(p,d):用來存放帶有小數的數值,使用時須指明精確度與小數點位數。此表示資料精準度為p 位數,而p 位數中含有d 位數的小數</li>\n<li>real, double precision:用來存放近似浮點數值,其精準度會因機器而產生誤差</li>\n<li>float(n):用來存放浮點數值,精準度至少為n位數</li>\n</ul>\n<span id=\"more\"></span>\n\n<h3 id=\"建立資料表\"><a href=\"#建立資料表\" class=\"headerlink\" title=\"建立資料表\"></a>建立資料表</h3><figure class=\"highlight armasm\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"symbol\">create</span> table <TABLE NAME> (<span class=\"built_in\">A1</span> <span class=\"built_in\">D1</span>, <span class=\"built_in\">A2</span> <span class=\"built_in\">D2</span>, ..., An <span class=\"meta\">Dn</span>,)</span><br></pre></td></tr></table></figure>\n<ul>\n<li>A為資料表內之屬性名稱</li>\n<li>D為屬性之型態</li>\n</ul>\n<p>範例</p>\n<figure class=\"highlight pgsql\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">create</span> <span class=\"keyword\">table</span> instructor (</span><br><span class=\"line\"> ID <span class=\"type\">char</span>(<span class=\"number\">5</span>),</span><br><span class=\"line\"> <span class=\"type\">name</span> <span class=\"type\">varchar</span>(<span class=\"number\">20</span>) <span class=\"keyword\">not</span> <span class=\"keyword\">null</span>,</span><br><span class=\"line\"> dept_name <span class=\"type\">varchar</span>(<span class=\"number\">20</span>),</span><br><span class=\"line\"> salary <span class=\"type\">numeric</span>(<span class=\"number\">8</span>,<span class=\"number\">2</span>))</span><br></pre></td></tr></table></figure>\n<p>這個例子建立了instructor資料表,裡面有四個屬性</p>\n<figure class=\"highlight sql\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">create</span> <span class=\"keyword\">table</span> takes (</span><br><span class=\"line\"> ID <span class=\"type\">varchar</span>(<span class=\"number\">5</span>),</span><br><span class=\"line\"> course_id <span class=\"type\">varchar</span>(<span class=\"number\">8</span>),</span><br><span class=\"line\"> sec_id <span class=\"type\">varchar</span>(<span class=\"number\">8</span>),</span><br><span class=\"line\"> semester <span class=\"type\">varchar</span>(<span class=\"number\">6</span>),</span><br><span class=\"line\"> <span class=\"keyword\">year</span> <span class=\"type\">numeric</span>(<span class=\"number\">4</span>,<span class=\"number\">0</span>),</span><br><span class=\"line\"> grade <span class=\"type\">varchar</span>(<span class=\"number\">2</span>),</span><br><span class=\"line\"> <span class=\"keyword\">primary</span> key (ID, course_id, sec_id, semester, <span class=\"keyword\">year</span>),</span><br><span class=\"line\"> <span class=\"keyword\">foreign</span> key (ID) <span class=\"keyword\">references</span> student,</span><br><span class=\"line\"> <span class=\"keyword\">foreign</span> key (course_id, sec_id, semester, <span class=\"keyword\">year</span>) <span class=\"keyword\">references</span> section );</span><br></pre></td></tr></table></figure>\n<p>上面是加了primary key與foreign key的版本</p>\n<h3 id=\"插入資料\"><a href=\"#插入資料\" class=\"headerlink\" title=\"插入資料\"></a>插入資料</h3><figure class=\"highlight sql\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">insert</span> <span class=\"keyword\">into</span> <span class=\"operator\"><</span><span class=\"keyword\">TABLE</span> NAME<span class=\"operator\">></span> <span class=\"keyword\">values</span> (...)</span><br></pre></td></tr></table></figure>\n\n<p>我們可以使用這個關鍵字去插入資料,例如:</p>\n<figure class=\"highlight mipsasm\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">insert </span>into <span class=\"keyword\">instructor </span> values (‘<span class=\"number\">10211</span>’, ’Smith’, ’<span class=\"keyword\">Biology’, </span><span class=\"number\">66000</span>);</span><br></pre></td></tr></table></figure>\n<p>這筆資料的ID為10211,name為Smith以此類推。</p>\n<p>若使用</p>\n<figure class=\"highlight n1ql\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">insert</span> <span class=\"keyword\">into</span> instructor <span class=\"keyword\">values</span> (‘<span class=\"number\">10211</span>’, <span class=\"literal\">null</span>, ’Biology’, <span class=\"number\">66000</span>);</span><br></pre></td></tr></table></figure>\n<p>會失敗,因為name被定義為不能為空。</p>\n<h3 id=\"查詢資料\"><a href=\"#查詢資料\" class=\"headerlink\" title=\"查詢資料\"></a>查詢資料</h3><figure class=\"highlight pgsql\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">select</span> <<span class=\"type\">NAME</span>> <span class=\"keyword\">from</span> <<span class=\"keyword\">TABLE</span> <span class=\"type\">NAME</span>></span><br></pre></td></tr></table></figure>\n\n<h3 id=\"刪除及修改資料\"><a href=\"#刪除及修改資料\" class=\"headerlink\" title=\"刪除及修改資料\"></a>刪除及修改資料</h3><figure class=\"highlight pf\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">drop</span> <span class=\"built_in\">table</span> instructor</span><br></pre></td></tr></table></figure>\n<p>刪除資料表及其內容</p>\n<figure class=\"highlight pgsql\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">delete</span> <span class=\"keyword\">table</span> instructor</span><br></pre></td></tr></table></figure>\n<p>刪除所有資料表的內容,但<strong>保留此資料表</strong></p>\n<p>上述兩種都會使資料表內容完全清空</p>\n<p>若要修改資料表內的屬性值使用<em>alter</em></p>\n<figure class=\"highlight pgsql\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">alter</span> <span class=\"keyword\">table</span> <<span class=\"keyword\">TABLE</span> <span class=\"type\">NAME</span>> <span class=\"keyword\">add</span> A D</span><br></pre></td></tr></table></figure>\n<p>A 是新增的屬性名稱,而D則是新增屬性之資料類別<br>在一開始的新屬性中,所有關聯中的原組都會被指派為null</p>\n<figure class=\"highlight pgsql\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">alter</span> <span class=\"keyword\">table</span> <<span class=\"keyword\">TABLE</span> <span class=\"type\">NAME</span>> <span class=\"keyword\">drop</span> A</span><br></pre></td></tr></table></figure>\n<p>A為資料表中屬性名稱</p>\n<figure class=\"highlight sas\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">ALTER</span> <span class=\"keyword\">TABLE</span> Customer <span class=\"keyword\">ADD</span> <span class=\"keyword\">PRIMARY</span> <span class=\"keyword\">KEY</span> (SID);</span><br></pre></td></tr></table></figure>\n<p>為Customer 增加 primary key 若原本的attribute可以為空則必須下</p>\n<figure class=\"highlight sql\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">ALTER</span> <span class=\"keyword\">TABLE</span> Customer <span class=\"keyword\">ALTER</span> <span class=\"keyword\">COLUMN</span> SID <span class=\"type\">int</span> <span class=\"keyword\">not</span> <span class=\"keyword\">NULL</span>;</span><br></pre></td></tr></table></figure>\n<p>必須重複一次原本的型態</p>\n<h2 id=\"SQL查詢結構\"><a href=\"#SQL查詢結構\" class=\"headerlink\" title=\"SQL查詢結構\"></a>SQL查詢結構</h2><figure class=\"highlight css\"><table><tr><td class=\"code\"><pre><span class=\"line\">select <span class=\"selector-tag\">A</span> <span class=\"selector-tag\">From</span> r where <span class=\"selector-tag\">P</span></span><br></pre></td></tr></table></figure>\n\n<ul>\n<li>A為屬性</li>\n<li>r為資料表</li>\n<li>P為條件</li>\n</ul>\n<figure class=\"highlight n1ql\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">select</span> <span class=\"keyword\">distinct</span> Country <span class=\"keyword\">from</span> Customers</span><br></pre></td></tr></table></figure>\n<p>distinct關鍵字會使查詢結果不含重複值<br>所以上面的語句就是從Customers中抓出不重複的Country</p>\n<p><em>where</em>則是可以用來設定查詢的條件</p>\n<figure class=\"highlight axapta\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">select</span> ProductName <span class=\"keyword\">from</span> Products <span class=\"keyword\">where</span> CategoryID = <span class=\"string\">'1'</span> and Unitprice > <span class=\"number\">20</span></span><br></pre></td></tr></table></figure>\n<p>上面的語句為查詢Products中CategoryID為1且Uniprice > 20 的ProductName</p>\n<p><strong>SQL中的相等為=而不是==</strong></p>\n<p>between : 可用來指定值必須介於某一閥值之間</p>\n<figure class=\"highlight pgsql\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">select</span> <span class=\"type\">name</span></span><br><span class=\"line\"><span class=\"keyword\">from</span> instructor</span><br><span class=\"line\"><span class=\"keyword\">where</span> salary <span class=\"keyword\">between</span> <span class=\"number\">90000</span> <span class=\"keyword\">and</span> <span class=\"number\">100000</span></span><br></pre></td></tr></table></figure>\n<p>上面的語句為查詢instructor中salary介於90000和100000之間的教師名子</p>\n<h3 id=\"Join\"><a href=\"#Join\" class=\"headerlink\" title=\"Join\"></a>Join</h3><h4 id=\"Natural-Join\"><a href=\"#Natural-Join\" class=\"headerlink\" title=\"Natural Join\"></a>Natural Join</h4><p>運算涵蓋兩個資料表,然後產生一個共同的關聯為結果</p>\n<p>只考慮出現在雙方資料表且有相同屬性值的欄位<br><strong>兩資料表之間同名的欄位會被自動結合在一起</strong></p>\n<figure class=\"highlight pgsql\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">select</span> <span class=\"type\">name</span>, course_id</span><br><span class=\"line\"><span class=\"keyword\">from</span> instructor, teachers</span><br><span class=\"line\"><span class=\"keyword\">where</span> instructor.ID = teachers.ID;</span><br></pre></td></tr></table></figure>\n<p>等同於</p>\n<figure class=\"highlight pgsql\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">select</span> <span class=\"type\">name</span>, course_id</span><br><span class=\"line\"><span class=\"keyword\">from</span> instructors <span class=\"keyword\">natural</span> <span class=\"keyword\">join</span> teachers;</span><br></pre></td></tr></table></figure>\n\n<h4 id=\"其他Join\"><a href=\"#其他Join\" class=\"headerlink\" title=\"其他Join\"></a>其他Join</h4><p><img src=\"https://i.imgur.com/EiZnYLH.png\"></p>\n<h3 id=\"as-別名運算\"><a href=\"#as-別名運算\" class=\"headerlink\" title=\"as(別名運算)\"></a>as(別名運算)</h3><figure class=\"highlight pgsql\"><table><tr><td class=\"code\"><pre><span class=\"line\"> <span class=\"keyword\">SELECT</span> t1.student_number, [section].instructor ,t1.grade <span class=\"keyword\">FROM</span></span><br><span class=\"line\"> (<span class=\"keyword\">SELECT</span> student.student_number ,section_identifier ,grade </span><br><span class=\"line\"> <span class=\"keyword\">FROM</span> Grade_report, student</span><br><span class=\"line\"> <span class=\"keyword\">WHERE</span> Grade_report.student_number = student.student_number <span class=\"keyword\">and</span> student.name = <span class=\"string\">'Jeff'</span>) <span class=\"keyword\">as</span> t1</span><br><span class=\"line\"><span class=\"keyword\">INNER</span> <span class=\"keyword\">JOIN</span> [section] <span class=\"keyword\">on</span> [section].section_identifier = t1.section_identifier;</span><br></pre></td></tr></table></figure>\n<p>t1表示為Grade_report和student兩個表中student_number一樣且名字為Jeff的關聯<br>並且加入了section</p>\n<h3 id=\"like-字串運算\"><a href=\"#like-字串運算\" class=\"headerlink\" title=\"like(字串運算)\"></a>like(字串運算)</h3><ul>\n<li>%:任何含有零個或多個字元的字串</li>\n<li>_:表示任何單一字元</li>\n</ul>\n<figure class=\"highlight pgsql\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">select</span> <span class=\"type\">name</span></span><br><span class=\"line\"><span class=\"keyword\">from</span> instructor</span><br><span class=\"line\"><span class=\"keyword\">where</span> <span class=\"type\">name</span> <span class=\"keyword\">like</span> <span class=\"string\">'%dar%'</span>;</span><br></pre></td></tr></table></figure>\n<p>上面的語句為查詢instructor中含有dar的教師名稱</p>\n<ul>\n<li><em>intro%</em>:任何<strong>開頭</strong>為intro的字串</li>\n<li><em>%Comp</em>:含有Comp的字串</li>\n<li><em>___</em>:表示正好三個字源的字串</li>\n<li><em>___%</em>:表示至少四個字元的字串</li>\n</ul>\n<h3 id=\"order-by-查詢結果排序\"><a href=\"#order-by-查詢結果排序\" class=\"headerlink\" title=\"order by(查詢結果排序)\"></a>order by(查詢結果排序)</h3><figure class=\"highlight pgsql\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">select</span> <span class=\"keyword\">distinct</span> <span class=\"type\">name</span></span><br><span class=\"line\"><span class=\"keyword\">from</span> instructor</span><br><span class=\"line\"><span class=\"keyword\">order</span> <span class=\"keyword\">by</span> <span class=\"type\">name</span></span><br></pre></td></tr></table></figure>\n<p>上面的語句為依照name的字母順序列出所有不重複的instructor</p>\n<blockquote>\n<p>order by預設為升冪排序<br>若要降冪排序必須要在後面加desc</p>\n</blockquote>\n<p>例</p>\n<figure class=\"highlight pgsql\"><table><tr><td class=\"code\"><pre><span class=\"line\"><span class=\"keyword\">select</span> <span class=\"keyword\">distinct</span> <span class=\"type\">name</span></span><br><span class=\"line\"><span class=\"keyword\">from</span> instructor</span><br><span class=\"line\"><span class=\"keyword\">order</span> <span class=\"keyword\">by</span> <span class=\"type\">name</span> <span class=\"keyword\">desc</span></span><br></pre></td></tr></table></figure>\n\n<h3 id=\"集合運算\"><a href=\"#集合運算\" class=\"headerlink\" title=\"集合運算\"></a>集合運算</h3><ul>\n<li>union(交集)</li>\n<li>intersect(聯集)</li>\n<li>except(差集)</li>\n</ul>\n<blockquote>\n<p>上面三種運算都可以自動消除重複值<br>若要保留則要改寫成 union all, intersect all, except all</p>\n</blockquote>\n<p>查詢在2009 年秋季或2010 年春季有開課的課程代碼</p>\n<figure class=\"highlight sql\"><table><tr><td class=\"code\"><pre><span class=\"line\">(<span class=\"keyword\">select</span> course_id <span class=\"keyword\">from</span> section <span class=\"keyword\">where</span> sem <span class=\"operator\">=</span> ‘Fall’ <span class=\"keyword\">and</span> <span class=\"keyword\">year</span> <span class=\"operator\">=</span> <span class=\"number\">2009</span>)</span><br><span class=\"line\"> <span class=\"keyword\">union</span></span><br><span class=\"line\">(<span class=\"keyword\">select</span> course_id <span class=\"keyword\">from</span> section <span class=\"keyword\">where</span> sem <span class=\"operator\">=</span> ‘Spring’ <span class=\"keyword\">and</span> <span class=\"keyword\">year</span> <span class=\"operator\">=</span> <span class=\"number\">2010</span>)</span><br></pre></td></tr></table></figure>\n\n<p>查詢在2009 年秋季和2010 年春季皆有開課的課程代碼</p>\n<figure class=\"highlight sql\"><table><tr><td class=\"code\"><pre><span class=\"line\">(<span class=\"keyword\">select</span> course_id <span class=\"keyword\">from</span> section <span class=\"keyword\">where</span> sem <span class=\"operator\">=</span> ‘Fall’ <span class=\"keyword\">and</span> <span class=\"keyword\">year</span> <span class=\"operator\">=</span> <span class=\"number\">2009</span>)</span><br><span class=\"line\"> <span class=\"keyword\">intersect</span></span><br><span class=\"line\">(<span class=\"keyword\">select</span> course_id <span class=\"keyword\">from</span> section <span class=\"keyword\">where</span> sem <span class=\"operator\">=</span> ‘Spring’ <span class=\"keyword\">and</span> <span class=\"keyword\">year</span> <span class=\"operator\">=</span> <span class=\"number\">2010</span>)</span><br></pre></td></tr></table></figure>\n\n<p>查詢在2009 年秋季有開課但2010 年春季未開課的課程代碼</p>\n<figure class=\"highlight sql\"><table><tr><td class=\"code\"><pre><span class=\"line\">(<span class=\"keyword\">select</span> course_id <span class=\"keyword\">from</span> section <span class=\"keyword\">where</span> sem <span class=\"operator\">=</span> ‘Fall’ <span class=\"keyword\">and</span> <span class=\"keyword\">year</span> <span class=\"operator\">=</span> <span class=\"number\">2009</span>)</span><br><span class=\"line\"> <span class=\"keyword\">except</span></span><br><span class=\"line\">(<span class=\"keyword\">select</span> course_id <span class=\"keyword\">from</span> section <span class=\"keyword\">where</span> sem <span class=\"operator\">=</span> ‘Spring’ <span class=\"keyword\">and</span> <span class=\"keyword\">year</span> <span class=\"operator\">=</span> <span class=\"number\">2010</span>)</span><br></pre></td></tr></table></figure>","categories":["資料庫課程筆記"],"tags":["database","SQL","SQL server"]},{"title":"資料庫理論","url":"/2020/08/10/%E8%B3%87%E6%96%99%E5%BA%AB%E7%90%86%E8%AB%96/","content":"<h2 id=\"Database-System\"><a href=\"#Database-System\" class=\"headerlink\" title=\"Database System\"></a>Database System</h2><h3 id=\"設計資料庫的階段-Phases-for-designing-a-database\"><a href=\"#設計資料庫的階段-Phases-for-designing-a-database\" class=\"headerlink\" title=\"設計資料庫的階段(Phases for designing a database)\"></a>設計資料庫的階段(Phases for designing a database)</h3><ul>\n<li>Requirements specification and analysis </li>\n<li>Conceptual design </li>\n<li>Logical design</li>\n<li>Physical design</li>\n</ul>\n<span id=\"more\"></span>\n\n<h3 id=\"Database-System要素\"><a href=\"#Database-System要素\" class=\"headerlink\" title=\"Database System要素\"></a>Database System要素</h3><ul>\n<li>meta-data<ul>\n<li>描述database的結構</li>\n</ul>\n</li>\n<li>database catalog<ul>\n<li>DBMS使用</li>\n<li>給需要了解結構的user使用</li>\n</ul>\n</li>\n</ul>\n<p><img src=\"https://i.imgur.com/Id2bN5K.png\"></p>\n<p>Program-data independence<br>資料檔案的結構儲存在DBMS目錄裡和存取程式是隔離的</p>\n<h3 id=\"data-abstraction-資料抽象化\"><a href=\"#data-abstraction-資料抽象化\" class=\"headerlink\" title=\"data abstraction(資料抽象化)\"></a>data abstraction(資料抽象化)</h3><ul>\n<li>Conceptual representation <ul>\n<li>不包括資料是如何儲存的細節或是操作是如何實作出來的</li>\n</ul>\n</li>\n<li>Data model<ul>\n<li>Type of data abstraction used to provide conceptual representation</li>\n<li>提供conceptual representation的資料抽象化型態</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"Sharing-of-Data-and-Multiuser-Transaction-Processing-資料分享與多使用者交易處理\"><a href=\"#Sharing-of-Data-and-Multiuser-Transaction-Processing-資料分享與多使用者交易處理\" class=\"headerlink\" title=\"Sharing of Data and Multiuser Transaction Processing(資料分享與多使用者交易處理)\"></a>Sharing of Data and Multiuser Transaction Processing(資料分享與多使用者交易處理)</h3><p>允許多個使用者在同一時間連線到database</p>\n<p><strong>Concurrency control software</strong><br>確保數個使用者想要更新同一數據時,可以受到控制<br>ex. 售票員</p>\n<h3 id=\"Database-administrators-DBA\"><a href=\"#Database-administrators-DBA\" class=\"headerlink\" title=\"Database administrators(DBA)\"></a>Database administrators(DBA)</h3><ul>\n<li>授權存取資料庫</li>\n<li>監督資料庫的使用</li>\n<li>負責需要的軟硬體資源</li>\n</ul>\n<h3 id=\"Database-designers\"><a href=\"#Database-designers\" class=\"headerlink\" title=\"Database designers\"></a>Database designers</h3><ul>\n<li>識別要存取在資料庫的資料</li>\n<li>選擇合適的結構來儲存</li>\n</ul>\n<h3 id=\"End-users\"><a href=\"#End-users\" class=\"headerlink\" title=\"End users\"></a>End users</h3><ul>\n<li>需要連接到資料庫的人</li>\n</ul>\n<p><a href=\"http://epaper.gotop.com.tw/pdf/AEE003700.pdf\">參考資料</a></p>\n<h2 id=\"Database-Languages-and-Architectures\"><a href=\"#Database-Languages-and-Architectures\" class=\"headerlink\" title=\"Database Languages and Architectures\"></a>Database Languages and Architectures</h2><h3 id=\"Schemas-Instances-and-Database-State\"><a href=\"#Schemas-Instances-and-Database-State\" class=\"headerlink\" title=\"Schemas, Instances, and Database State\"></a>Schemas, Instances, and Database State</h3><ul>\n<li>Database schema<ul>\n<li>database的描述</li>\n</ul>\n</li>\n<li>Dchema diagram<ul>\n<li>呈現選取的schema</li>\n</ul>\n</li>\n<li>Schema construct<ul>\n<li>每個在schema的Object</li>\n</ul>\n</li>\n<li>Database state<ul>\n<li>Database中特定時間的Data</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"three-Schema-Architecture\"><a href=\"#three-Schema-Architecture\" class=\"headerlink\" title=\"three-Schema Architecture\"></a>three-Schema Architecture</h3><ul>\n<li>外部層(External Level)<ul>\n<li>描述資料庫的部分資料</li>\n<li>負責不同使用者所需要觀看的部分資料,而將資料庫的其他部分隱藏起來</li>\n</ul>\n</li>\n<li>概念層(Conceptual Level)<ul>\n<li>描述整個資料庫的結構</li>\n<li>是以DBA觀點所看到的完整資料庫系統</li>\n</ul>\n</li>\n<li>內部層(Internal Level)<ul>\n<li>描述架構中的有關資料庫實際的儲存與存取路徑的完整資訊</li>\n</ul>\n</li>\n</ul>\n<p><img src=\"https://i.imgur.com/ULEj9ei.png\"></p>\n<p><a href=\"https://myweb.ntut.edu.tw/~ycchu/DB/db-1.pdf\">補充</a></p>\n<p>目的是達到Data independence</p>\n<p>:::info<br><strong>Data Independence</strong><br>上下層並不會互相影響<br>:::</p>\n<p>而Data independence分為兩種</p>\n<ul>\n<li>Logical : 外部與概念對應,當Conceptual schema更改時,只要更改兩層之間的映對,而不需要直接更改其他層的Schema</li>\n<li>Physical : 概念與內部對應,當Internal schema更改時,只要更改Internal schema與conceptual schema的映對,而不需要更改Conceptual schema或External schema</li>\n</ul>\n<p><a href=\"http://faculty.stust.edu.tw/~jehuang/oracle/ch1/1-2.htm\">更詳細的說明</a></p>\n<h3 id=\"DBMS-language\"><a href=\"#DBMS-language\" class=\"headerlink\" title=\"DBMS language\"></a>DBMS language</h3><ul>\n<li>Data definition language(DDL, 資料定義語言)<ul>\n<li>定義schemas(Conceptual schema, Internal schema)</li>\n</ul>\n</li>\n<li>Storage definition language(SDL, 儲存定義語言)<ul>\n<li>明確定義internal schema</li>\n</ul>\n</li>\n<li>View definition language(VDL, 視野定義語言)<ul>\n<li>根據Conceptual schema 定義user views/mapping</li>\n</ul>\n</li>\n<li>Data manipulation language(DML, 資料操縱語言)<ul>\n<li>允許retrieval,insertion,deletion,modification</li>\n<li>High-level DML<ul>\n<li>高階DML為集合導向的(set-oriented)</li>\n</ul>\n</li>\n<li>Low-level DML<ul>\n<li>低階DML為一次一筆紀錄(record-at-a-time)</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"DBMS要素\"><a href=\"#DBMS要素\" class=\"headerlink\" title=\"DBMS要素\"></a>DBMS要素</h3><ul>\n<li>Buffer management</li>\n<li>Stored data manager</li>\n<li>DDL compiler</li>\n<li>Interactive query interface</li>\n<li>Precompiler</li>\n<li>Runtime database processor</li>\n<li>System catalog</li>\n<li>Comcurrency control system</li>\n<li>Backup and recovery system</li>\n</ul>\n<p><img src=\"https://i.imgur.com/zbF9tmo.png\"></p>\n<p>必須要有以下功能</p>\n<ul>\n<li>Loading(載入)</li>\n<li>Backup(備份)</li>\n<li>Database storage reorganization(重組檔案)</li>\n<li>Performance monitoring(效能監控)</li>\n</ul>\n<h3 id=\"兩層式C-x2F-S架構\"><a href=\"#兩層式C-x2F-S架構\" class=\"headerlink\" title=\"兩層式C/S架構\"></a>兩層式C/S架構</h3><ul>\n<li>Server handles<ul>\n<li>Query and transaction functionality related to SQL processing</li>\n</ul>\n</li>\n<li>Client handles<ul>\n<li>使用者介面或是程式</li>\n</ul>\n</li>\n</ul>\n<p>在兩層之間的介面稱為ODBC,是一種API使用戶端程式可以呼叫DBMS</p>\n<h3 id=\"三層式C-x2F-S架構\"><a href=\"#三層式C-x2F-S架構\" class=\"headerlink\" title=\"三層式C/S架構\"></a>三層式C/S架構</h3><p>在Web server常見</p>\n<p>會在Client和databese server中間加入intermediate layer,扮演在資料庫伺服器與用戶端之間傳送資料的中間角色</p>\n<p><img src=\"https://i.imgur.com/Wk4O7rw.png\"></p>\n<h3 id=\"DBMS分類\"><a href=\"#DBMS分類\" class=\"headerlink\" title=\"DBMS分類\"></a>DBMS分類</h3><ul>\n<li>Data model<ul>\n<li>Relational</li>\n<li>object</li>\n<li>Hierarchical and network(網路)</li>\n<li>native XML DBMS</li>\n</ul>\n</li>\n<li>User<ul>\n<li>單一使用者</li>\n<li>多使用者</li>\n</ul>\n</li>\n<li>Number of sites<ul>\n<li>集中式</li>\n<li>分散式</li>\n</ul>\n</li>\n</ul>\n<p><a href=\"https://www.lis.ntu.edu.tw/~khchen/course/db/db2007/DBCh02DBMS.pdf\">補充</a></p>\n<h2 id=\"The-basic-relational-model\"><a href=\"#The-basic-relational-model\" class=\"headerlink\" title=\"The basic relational model\"></a>The basic relational model</h2><h3 id=\"Relational-Model-Concepts\"><a href=\"#Relational-Model-Concepts\" class=\"headerlink\" title=\"Relational Model Concepts\"></a>Relational Model Concepts</h3><p>資料庫為多個集合的關聯<br><img src=\"https://i.imgur.com/IVhexH3.png\"></p>\n<p>名稱對應</p>\n<table>\n<thead>\n<tr>\n<th>理論</th>\n<th>實務</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>Relation</td>\n<td>Table</td>\n</tr>\n<tr>\n<td>Tuple</td>\n<td>Row</td>\n</tr>\n<tr>\n<td>Attribute</td>\n<td>Column</td>\n</tr>\n</tbody></table>\n<p>Domain為無法分割值的集合<br>(可稱為定義域)</p>\n<ul>\n<li>relation(relaiton state)<ul>\n<li>n-tuple的集合,可表示成 $r = { t_1, t_2,…,t_m}$</li>\n<li>每個n-tuple t<ul>\n<li>為有n個值的list</li>\n<li>每個 $v_i, 1\\leq i \\leq n$ 是 $dom(A_i)$中的一個元素或是<code>NULL</code>值</li>\n</ul>\n</li>\n<li>Degree of relation<ul>\n<li>relation schema中attribute的數目</li>\n</ul>\n</li>\n</ul>\n</li>\n<li>Cardinality<ul>\n<li>domain中值的數目</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"Characteristics-of-Relations(關聯的特性)\"><a href=\"#Characteristics-of-Relations(關聯的特性)\" class=\"headerlink\" title=\"Characteristics of Relations(關聯的特性)\"></a>Characteristics of Relations(關聯的特性)</h3><ul>\n<li>Relation 中的 tuple沒有順序</li>\n<li>tuple中的值<ul>\n<li>每個tuple的值都是atomic</li>\n<li>Flat relation model<ul>\n<li>Composite and multivalued attributes not allowed</li>\n<li>First normal form 假設<ul>\n<li><a href=\"https://hackmd.io/@TSMI_E7ORNeP8YBbWm-lFA/rykcj8kmM?type=view\">補充-第一正規化</a></li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n<li>NULL值<ul>\n<li>表示為unknown或是不能用tuple表示</li>\n<li>可能情況<ul>\n<li>未知值</li>\n<li>值存在但不可用</li>\n<li>這個attribute不能表示tuple</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n<p>Relation model 符號</p>\n<ul>\n<li>Relation schema R of degree n<ul>\n<li>表示為$R(A_1,A_2,…A_n)$</li>\n</ul>\n</li>\n<li>大寫的 $Q,R,S$<ul>\n<li>表示relation name</li>\n</ul>\n</li>\n<li>小寫的 $q,r,s$<ul>\n<li>表示relation state</li>\n</ul>\n</li>\n<li>$t,u,v$<ul>\n<li>表示tuple</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"Relation-model-限制\"><a href=\"#Relation-model-限制\" class=\"headerlink\" title=\"Relation model 限制\"></a>Relation model 限制</h3><ul>\n<li>Entity integrity constraint<ul>\n<li>Primary key不可為NULL</li>\n</ul>\n</li>\n<li>Key Constraints<ul>\n<li>super key 超鍵<ul>\n<li>符合唯一性的key</li>\n</ul>\n</li>\n<li>Candidate key 候選鍵<ul>\n<li>符合唯一性以及最小性的key</li>\n</ul>\n</li>\n<li>Primary key 主鍵<ul>\n<li>從Candidate key中選出來</li>\n<li>最具識別意義的屬性</li>\n<li>不可為空</li>\n</ul>\n</li>\n<li>Alternate Key 次要鍵<ul>\n<li>沒有被選為主鍵的其他Candidate key</li>\n</ul>\n</li>\n<li>Foreign Key 外鍵<ul>\n<li>Relation中被用來參考到其他表格Primary key的key,就是Foreign key</li>\n<li>必須和Primary key有相同的domain</li>\n<li>Foreign key 的值必須存在於Primary key的值=><a href=\"https://www.mysql.tw/2017/04/blog-post.html\">參考完整性 (Referential Integrity)</a></li>\n</ul>\n</li>\n</ul>\n</li>\n<li>State constraints<ul>\n<li>Define the constraints that a valid state of the database must satisfy</li>\n</ul>\n</li>\n<li>Transition constraints<ul>\n<li>Define to deal with state changes in the database</li>\n</ul>\n</li>\n</ul>\n<p>操作種類</p>\n<ul>\n<li>Insert<ul>\n<li>可以打破上面四個限制</li>\n<li>如果打破了任何一個限制,一般而言會拒絕</li>\n</ul>\n</li>\n<li>Delete<ul>\n<li>只能打破referential integrity</li>\n</ul>\n</li>\n<li>Update</li>\n</ul>\n","categories":["資料庫課程筆記"],"tags":["database","SQL"]},{"title":"資料庫邏輯設計","url":"/2021/01/27/%E8%B3%87%E6%96%99%E5%BA%AB%E9%82%8F%E8%BC%AF%E8%A8%AD%E8%A8%88/","content":"<h2 id=\"正規化\"><a href=\"#正規化\" class=\"headerlink\" title=\"正規化\"></a>正規化</h2><p>消除資料間的依賴性,而使得資料庫檔案內的資料欄位分配合理化,確定哪些資料欄位該在同一檔案內,哪些欄位又該分開在不同檔案內,使資料不重複。</p>\n<p>解決在資料更新、增刪時所衍生之問題。</p>\n<p>比較常見的有</p>\n<ul>\n<li>第一正規式</li>\n<li>第二正規式</li>\n<li>第三正規式</li>\n<li>BC正規式<span id=\"more\"></span></li>\n</ul>\n<h3 id=\"依賴性\"><a href=\"#依賴性\" class=\"headerlink\" title=\"依賴性\"></a>依賴性</h3><p>在一檔案中,若B欄位對A欄位依賴,則表示B欄位的值可由A欄位的值唯一決定,以A $\\rightarrow$ B表示。</p>\n<ul>\n<li>全依賴 : 主鍵由多個欄位組合而成,若某非主鍵欄位依賴主鍵之全部時,則稱該欄位<strong>全依賴</strong>於主鍵。</li>\n<li>部分依賴 : 主鍵由多個欄位組合而成,若某非主鍵欄位依賴主鍵之部分時,則稱該欄位<strong>部分依賴</strong>於主鍵。</li>\n<li>遞移依賴 : 若一檔案中的A、B、C三欄位,形成B依賴A,C依賴B,C也依賴A,即稱為遞移依賴。</li>\n</ul>\n<h3 id=\"第一正規化\"><a href=\"#第一正規化\" class=\"headerlink\" title=\"第一正規化\"></a>第一正規化</h3><p>沒有重複群組(repeating group)的檔案即為第一正規式。<br>重複群組之意為某一或多個欄位儲存於一個以上的資料值。</p>\n<h4 id=\"沒有第一正規化會衍生出的問題\"><a href=\"#沒有第一正規化會衍生出的問題\" class=\"headerlink\" title=\"沒有第一正規化會衍生出的問題\"></a>沒有第一正規化會衍生出的問題</h4><ul>\n<li><p>新增記錄時<br>當有一新人加入時,但未有任何經歷時,將造成資料記錄不完整,若資料已存在造成資料重複。</p>\n</li>\n<li><p>更新資料時<br>所某人有多種經歷,則有多筆記錄在檔案中,每筆記錄均含有此人之身分證字號、姓名、居住地等資料,此人若有資料異動,則必須更動多筆資料。如此不僅浪費空間,而且更新時亦浪費時間</p>\n</li>\n<li><p>刪除記錄時<br>若某人有多種經歷,則有多筆紀錄在檔案中,若我們要刪除此人的資料,則必須刪除多筆</p>\n</li>\n</ul>\n<blockquote>\n<p><strong>轉成第一正規化的方法</strong><br>去除重複群組的欄位<br>並將主鍵與重複群組建為一組</p>\n</blockquote>\n<h3 id=\"第二正規化\"><a href=\"#第二正規化\" class=\"headerlink\" title=\"第二正規化\"></a>第二正規化</h3><p>必為第一正規式<br>所有非主鍵欄位均對主鍵全依賴。</p>\n<p><img src=\"https://i.imgur.com/jl4ilRW.png\"></p>\n<h4 id=\"沒有第二正規化會衍生出的問題\"><a href=\"#沒有第二正規化會衍生出的問題\" class=\"headerlink\" title=\"沒有第二正規化會衍生出的問題\"></a>沒有第二正規化會衍生出的問題</h4><ul>\n<li><p>新增記錄時<br>當有一新供應商設立,但未供應任何零件時,我們無法將其名稱和基本資料鍵入檔案中,因主鍵中只有供應商代號而無零件代號,主鍵不完全的紀錄無存在的意義。</p>\n</li>\n<li><p>更新資料時<br>若某一供應商供應多種零件,則有多筆資料在檔案中,每筆紀錄均含有此時供應商名稱和基本資料,此時若該供應商的基本資料有異動,則有多筆資料需更新。如此不僅重複儲存浪費空間,而更新時亦浪費時間。</p>\n</li>\n<li><p>刪除記錄時<br>當某一供應商僅供應一種零件時,則僅有一筆紀錄在檔案中,此時若該供應商不供應該零件了,我們勢必要刪除此記錄,但這個動作將連結供應商名稱和基本資料一併刪除,這可能不是我們要的結果。</p>\n</li>\n</ul>\n<blockquote>\n<p><strong>轉成第二正規化的方法</strong><br>把部分依賴的欄位及他依賴的主鍵另建一組<br>原來的檔案只保留全依賴的欄位和主鍵</p>\n</blockquote>\n<h3 id=\"第三正規化\"><a href=\"#第三正規化\" class=\"headerlink\" title=\"第三正規化\"></a>第三正規化</h3><p>必為第二正規式<br>去除遞移依賴</p>\n<h4 id=\"沒有第三正規化會衍生出的問題\"><a href=\"#沒有第三正規化會衍生出的問題\" class=\"headerlink\" title=\"沒有第三正規化會衍生出的問題\"></a>沒有第三正規化會衍生出的問題</h4><ul>\n<li><p>新增記錄時<br>當學校新聘一位教師,但該教師未正式授課時,我們無法新增教師的資料,因主鍵為空白的紀錄無存在的意義。</p>\n</li>\n<li><p>更新資料時<br>若某一教師教授多門課時,則有多筆記錄在檔案中,每筆記錄均含有教師住所資料,此時若該教師住所資料有異動,則有多筆紀錄紀錄需更新,如此不僅重複儲存浪費空間,而更新時亦浪費時間。</p>\n</li>\n<li><p>刪除記錄時<br>當某教師僅教授一門課時,則僅有一筆紀錄在檔案中,此時若該門課停開,勢必刪除此記錄,但這個動作將連教師住所資料一併刪除。</p>\n</li>\n</ul>\n<blockquote>\n<p><strong>轉成第三正規化的方法</strong><br>把遞移依賴的欄位和其所依賴的主鍵欄位另組一檔,保留非遞移依賴的欄位和主鍵。</p>\n</blockquote>\n","categories":["資料庫課程筆記"],"tags":["database","SQL"]},{"title":"NASA2021黑客松參賽心得","url":"/2021/10/14/%E9%BB%91%E5%AE%A2%E6%9D%BE%E5%8F%83%E8%B3%BD%E5%BF%83%E5%BE%97/","content":"<p>今年為期兩天的黑客松終於結束了,獎項也公布了,雖然沒有獲得獎項,但我對我們的成品是滿意的。</p>\n<p>這是我第一次參加這種大型的黑客松活動,而我們隊選了LightCurve這個主題,對這個主題我是完全沒有相關知識及經驗,但是隊友們非常的厲害,開賽前把論文讀完並用matlab做了簡單的演示,目標是利用3D模型算出LightCurve並在前端顯示出來。</p>\n<p>首先是分工,計算LightCurve這部分就得將matlab的code轉成javascript的,還要利用three.js來做成小行星的動畫,這邊是由我的隊友們完成的,真的是非常厲害,而我和另一位隊友負責把網站整個流程做好,從選取、設定參數到結果頁面,我們選的是Vue+Bootstrap,第一天結束時,網站的各個頁面是大致完成,但是code也開始變得雜亂,也造就了第二天debug難度增加,然後為了開發快速,我們沒有使用資料庫,所有資料都存在localstorage裡(有一部分是因為Component的參數傳遞不太會),包括使用者上傳的OBJ檔都存在裡面,到後面受不了還是包成一個變數。</p>\n<p>在第二天時有個小成果發表的視訊會議,會有評審給相關意見,我們在發表前的內容是非常完整的,但是影片只有30秒,導致開完場能介紹操作的時間都不長了,播完影片、Demo完,評審唯一的意見是影片中的東西太少,非常多功能沒有介紹到,隊友還因為有我們有做但前端還沒顯示出來的東西跟評審有小爭執,最後我們利用比賽剩餘時間將這功能show出來。</p>\n<p>參賽完也深刻的理解到很多操作不太熟,很多問題是有非常多好的工具可以解的,然後在黑客松這個場合多多問隊友會更快,而且隊友有用非常多輔助討論的工具,對於想法的整理幫助很大,尤其miro在彙整想法時真的非常好用,甚至可以畫出簡單的wireframe讓我能知道要怎樣刻,最後感謝我的隊友們,希望之後能參加到實體的黑客松!</p>\n<p>最後附上 <a href=\"https://nasa-2021.netlify.app/\">成品</a></p>\n","tags":["黑客松","NASA","心得"]}]