2017年1月26日 星期四

輕鬆用VBA做網路爬蟲(中)之 字串處理

字串處理(String Parsing)簡單說就是將一堆文字(包括符號、數字等)清理、整理後擷取我們需要的部份;以輕鬆用VBA做網路爬蟲(上) 最後的小挑戰做例子的話,可以(跟面試官)說我們是在開發處理玩股網報價的演算法


開發一個網路爬蟲時,大概有八成以上的時間都在做字串處理,

在這篇文章中我會用網路爬蟲“上篇”中最後的小挑戰作為例子,

再用一個線上的字庫讓大家練習一下。


上一篇文章中我們抓下來的原始資料長這樣:

200.32▲3.861.96%
108.47▲2.011.89%
134.03▲2.41.82%
130.71▲2.341.82%
113.09▲1.861.67%
82.59▲1.161.42%
208.67▲2.581.25%
160.88▲1.941.22%
484.47▲5.691.19%
380.09▲4.31.14%
263.25▲2.921.12%

首先,我們在被證明錯誤前先找找其中自以為的規律:「

1. 指數報價一定都到小數點後兩位;
2. 指數報價後會跟著上漲▲或下跌▼的符號,平盤時沒有符號(某天看見的);
3. 當天漲跌(有負號)一定都到小數點兩位,平盤時為0(某天看見的);
4. 不論當天漲跌(有負號),漲跌幅一定到小數點後兩位(eg. x.xx%)。」

因此,萃取指數報價的方式就是:「

找到第一個"."的位置(假設為n),然後抓第1位~第n+2位,
也就是 Left( 原始資料, inStr( 1, 原始資料, "." )+2 )。」


再來,萃取指數漲跌的方法稍微複雜點:「

【先看原始資料中是否有那兩個符號,有的話:「

首先,我們知道指數報價的結尾在n+2處,
因此我們新創一個從n+3開始的資料叫做"改動資料",
改動資料= Right( 原始資料, (len( 原始資料) -(n+2)) ),

所以,我們一樣找改動資料中第一個"."的位置(假設為m),然後抓第1位~第m+2位就行了,
也就是 Left( 改動資料, inStr( 1, 改動資料, "." )+2 )。

如果找不到▲或▼的符號,那當日漲跌就是0了。】」


最後是當日漲跌幅:「

如果當日漲跌不為0,那麼改動資料的第m+3位~最後一位就是漲跌幅了,
也就是Right( 改動資料, (len( 改動資料) -(m+2)) )。

當日漲跌為0的話,漲跌幅自然也為0( 0.00%)了。」


========================================================

以下是另一個字串處理+網路爬蟲的例子

========================================================


這是一個古登堡計畫下的字庫網頁(A開頭):
http://www.mso.anu.edu.au/~ralph/OPTED/v003/wb1913_a.html


我們要嘗試著計算出A開頭字庫中各種詞性(part of speech)佔的數目,
原始碼大致上長這樣子:「

<P><B>Abacinate</B> (<I>v. t.</I>) To blind by a red-hot metal plate held before the eyes.</P>
<P><B>Abacination</B> (<I>n.</I>) The act of abacinating.</P>
 <P><B>Abstaining</B> (<I>p. pr. & vb. n.</I>) of Abstain</P>  」

單字被<B>標籤包住、詞性則被<I>標籤包住,
除此之外一個單字可能會有多個詞性(在<I>標籤裡面被&符號分開)。
(註:實作後才發現有極少數的多詞性會被“ /” 以及“ ,” 符號分開)

爬蟲的前置除了網址不一樣外,其它的與上篇文章都一樣,
以下是抓取詞性的code:「

圖1:
















圖2:



























圖3:





















理論上,運行完後我們得到的資料大概會長這樣(部份):

Part of Speech
numbers
prep.
70
n.
5444
a.
2861
v.t.
1088
adv.
574
pl.
239
p.p.
317
imp.
287
p.pr.
285
vb.n.
285
v.
67
v.i.
278
n.pl.
171
superl.
10
i.
44
p.a.
7
a
2
interj.
15
p.p.Adored(/);p.pr.
1
a.superl.
2
Aprefix.
3
conj.
26
網路爬蟲中,字串處理的部份大致上就是這個樣子。

以下是範例檔案(附code):


字串處理是一門相當重要的功夫,
無論是做資料分析、語意分析、或甚至要暴力破解某個密碼都會用到它,
而有些問題只有在實作後才會被發現,
建議大家多多找出生活、工作中可以被自動化的工作,試著動手開發。

有任何問題歡迎來信或者留言,
如果想自動化一件工作卻毫無頭緒也可以來信我們討論看看,



IT'S   ALL   FREE !!






2017年1月17日 星期二

輕鬆用VBA做網路爬蟲(上)

網路爬蟲(Web Crawler)簡單來說就是自動化的從網路上抓取我們要的資料,通常需要懂一些基礎的HTML語言以及還不賴的字串處理能力。


因為大部份網路爬蟲的相關來信都是想知道怎麼抓類/個股資料,

因此在這一系列的教學當中,我會從0到1教各位怎麼用VBA打造自己的股票資訊更新程式。

先介紹一下HTML,它的全名是Hyper Text Markup Language,
(註:本人極度不擅長HTML,若文章有錯請不吝嚴厲的來信或是在下面留言)
中國的翻譯是超文本標記語言,
在接下來的課程中我們會學著怎麼找到我們要的標記,然後用程式抓下來。
以下是一些標記(markup// tag)的例子:
标签描述
<!--...-->定义注释。
<!DOCTYPE>定义文档类型。
<a>定义锚。
<abbr>定义缩写。
<acronym>定义只取首字母的缩写。
<address>定义文档作者或拥有者的联系信息。
<applet>不赞成使用。定义嵌入的 applet。


因為Yahoo股市實在是太主流了,我決定用玩股網當做本系列的例子。
這是我們的目標網址:
在本篇文章中,我們會抓下這個頁面的:類股名稱、指數、漲跌、以及漲跌幅。


首先我們進到上述的網址,花個幾分鐘看看我們要的資料長什麼樣子,
再花一點時間看看網頁原始碼(source code)長什麼樣子(點右鍵通常就看得到這個功能了),
接著我們發現我們要的資料被一些東西包了起來,就像我的肝一樣。

==========================以玻璃作為例子==========================

<em class="qIdxName"><a href="/Stock/TWStock/ClassCont?id=^019">玻璃</a></em>
<p class="qIdx ig up">36.46<span class="qIdxChg">▲1.52<b>4.35%</b></span></p>

==========================以玻璃作為例子==========================

接下來很重要,我們要決定怎麼有效率的抽出(extract)我們要的資料,
以"玻璃"這個產業類別作為例子,
我們發現它被三個東西包住:<em>的標籤、qIdxName的類別名稱、以及<a>的標籤
但是綜觀整個source code,我們發現<a>標籤包含了太多我們不要的資訊了,
相對的<em>這個標籤只用來包住產業別而已,qIdxName這個名稱也是,
二選一,<em>比較短我就選它了;

然後我們發現指數、漲跌、漲跌幅通通混在一起分不開,
還好<p>標籤在整個原始碼當中幾乎只被用來記錄這些資訊,
所以我們就把這串東西一次抽出,之後再想辦法分開吧。



接下來該VBA上場了。

(註:本文最下方會附上範例資料)

設定完開發環境後,以下是加上附註的程式碼。
(不知道怎麼設定的朋友請看一下前文或是下載我的講義 https://goo.gl/9qtTiv)

圖片1:

圖片2:

















運行以上的程式碼後,我們應該可以在excel上看到下面的結果:
(如果沒有的話,建議objIE.visible改成True,看過程中是不是IE有什麼問題)
圖片3:
















為了拆開後面那一串東西,這裡介紹五個函式:『

第一個是inStr;inStr(起始位置,母字串,要找的字);
inStr(1, "My name is Tamio", "a")會產出5(空格也算一個字)。

第二個是inStrRev;inStrRev(母字串,要找的字);
inStrRev( "My name is Tamio", "a")會產出13(找後面數回去的第一個a)。

第三個是Left;Left(母字串,字數);
Left( "My name is Tamio", 6)會產出"My nam"。

第四個是Right;Right(母字串,字數);
Right( "My name is Tamio", 7)會產出"s Tamio"。

第五個是Mid;Mid(母字串,起始點,長度);
Mid( "My name is Tamio", 5, 5)會產出" ame i"。』

至於實務上要怎麼拆開那串東西,就留給大家做做看吧!
(文末我的範例檔案裡面有解法)

兩個提示:
1. 漲跌幅的格式幾乎都是x.xx%
2. 除了當日漲跌為0以外,都會有▲或是▼的符號,而指數一定落在這些符號之前


完成後應該長這樣子,
圖片4:















在下一篇文章中,
我會說明怎麼用VBA“點擊”產業類別的連結,
然後把裡面的資訊分門別類儲存起來。
圖片5:





















以下附上我的範例檔案:
https://goo.gl/D112gl

如果有問題歡迎留言或是在FB上msg我。



P.S. 搞不懂什麼時候要加Set、記不起來那麼多函式、
老是要google才知道一個功能該怎麼實現都是正常的,
寫這篇文章我也google的要死要活,請大家不要沮喪氣餒,
寫久了就會多記得一點點。

P.S.S. 寫這篇文章我參考了不少這系列影片的內容:
https://goo.gl/n4SeFS 」,英文不太好的人可以看看練習一下。

P.S.S.S. 我花了很多時間還是沒辦法把文章中的所有圖片大小變得一致,
不曉得跟陸客不來有沒有關係,請大家多多海涵~