曾編了一個程式,應用於數學建模的資料提取階段。現歸納如下,思路寫得比較詳細,看起來像教程-_-。
目的是做一個BBS的流量統計,需要分析的資料是每一分鐘之內,有哪些ID線上,這些ID的IP是多少,並且要求ID與IP一一對應,不能有重複ID和重複IP,並要求每一分鐘產生一個矩陣,分別是ID IPA段 IPB段 IPC段 IPD段, 並存成文字檔, 檔案名稱為hh:mm格式. 然後把這些文字檔匯入MatLab進行分析處理,現討論前面的資料獲得階段的實現方法。
資料來源從http://bbs.pku.edu.cn/cgi-bin/bbsusr?to=*獲得(北大的伺服器比較爛,今天就上不去)
1,首先資料需要下載,這裡採用Msxml2.ServerXMLHTTP控制項來進行非同步下載獲得資料來源,之所以不用Microsoft.XMLHTTP是因為Msxml2.ServerXMLHTTP這個控制項可以設定逾時時間。這完全是開發SXNA過程中得到的啟發。由於資料來源的特點是資料量在隨時變化,不固定容量,所以有必要設定逾時。否則程式將不能正確執行容易導致死機。
2,其次需要每一分鐘自動下載一遍資料來源,並要求按時間精確儲存。也就是說必須每一分鐘自動驅動一遍下載程式,這就要求程式能夠實現自動重新整理功能。自動重新整理功能的實現有多種方法,最基礎的是使用meta標籤實現refresh,但是本程式要求精確控制時間下載,必須在每一分鐘內保證有一次下載,所以meta標籤不適用於此程式。其他的方法還有諸如javascript裡面的reload方法,window.location.href方法等等,考慮到相容性的問題選用window.location.href來實現自動驅動。SXNA中的資料更新也用的差不多這種方法。
3,為實現每一分鐘自動下載需要記錄下次下載的時間,存在application("mytime")裡面,然後用Javascript的Settimeout判斷這次的時間是否到達下次下載時間,並把當前剩餘時間顯示在螢幕上,如果達到了下載時間,則自動重新整理驅動程式。這裡面有一個問題,就是Javascript只認得RFC的時間,所以還要用一個ISOtoRFC的時間轉換子程式。當每一次驅動下載之前application("mytime")要自動加60秒,這樣靠application("mytime")來精確控制下載時間。
4,資料下回來之後,用http.ResponseText來提取資料來源資訊,由於得到的代碼為HTML代碼,所以這裡採用Regex來進行有效資料提取。首先分析ID的分布規律,注意到每一個ID都跟在"bbsqry?name="之後,所以搜尋代碼採用"bbsqry\?name=(\w*?)""",由於每一個id要重複兩次,所以下面進行VALUE遍曆提取的時候Matches.count要標註step 2。用同樣類似的方法也把ip提取出來,搜尋代碼採用">(\d+)\.(\d+)\.(\d+)\.(\d+)",這裡值得一提的是由於需要提取每一個IP段,所以要用到SubMatches,來擷取每一個子匹配的值。
5,提取完了資料還沒完事,由於要求不能出現重複的ID和IP所以我必須想辦法去掉重複的,還要保證一一對應,怎麼去掉我想了好幾種辦法,開始想用Regex,但考慮到這樣迴圈的次數太多,效率上根本划不來,搞不好還會死機。突然想到編SXNA的時候我把LINK作為資料庫的主鍵索引從而避免了重複LINK的出現,於是這次也打算照葫蘆畫瓢。首先開啟ACCESS建立資料表,把建立一個ID IP IPA段 IPB段 IPC段 IPD段 6列,ID,IP為有索引,無重複列.不建立自動編號列,是因為每一次驅動後都要刪除資料,為了保險刪除資料之後不壓縮資料庫,這樣編號會無止境增長,況且編號也沒用.
6,全部入庫完成之後資料已經去掉重複的了,現在就要把他們做成txt檔案,並以當前的時間作為文字檔的檔案名稱.這裡考慮到了單個數字時間的問題,前面要補零(突然想到了數字訊號處理裡面序列的補零問題-_-),具體這樣寫right("0"&minute(application("mytime2")),2),檔案裡面的內容就很簡單的把資料庫裡面的東西用ADODB.Stream寫進一個文字檔就可以了,剩下的就是資料庫基本操作了.
其實思路挺簡單的,但是做了3個小時-_-,其中主要把時間耗費在了時間問題上面,對於每一分鐘精確儲存一個檔案的問題我編了好幾種實現方案,最終都被我篩掉了,留下了一種最可靠的.
(轉載請註明出處:http://www.dc9.cn/post/ASPMathematicalModeling.asp)
上面的僅僅是最最基本的思路,就寫到這。下面是全部代碼。
<title>自動儲存/去掉重複ID和IP/準確按時儲存/按IP升序(Sipo made for xia)v1</title>
還有多長時間<INPUT TYPE="text" NAME="mytime" id="mytime" size="60" value="">
<br>
<%
'www.dc9.cn sipo QQ17862153
'這是去掉重複ID,IP版13:15
'如果想按照ID排序就把orderby 改為name
on error resume next
dim nowstr
const TimeInterval=60
'設定時間間隔
'如果下載時間很慢,就寫成120秒
Response.LCID=2052
const lResolve=6
'解析網域名稱逾時時間,秒
const lConnect=6
'串連網站逾時時間,秒
const lSend=6
'發送資料請求逾時時間,秒
const lReceive=40
'下載資料逾時時間,秒
const myURL="http://bbs.pku.edu.cn/cgi-bin/bbsusr?to=*"
'const myURL="http://localhost/test.htm"
If isempty(application("mytime2")) then
nowstr=now()
application.Lock
application("mytime")=DateToStr(nowstr,"w,d m y H:I:S")
application("mytime2")=nowstr
application.unLock
ElseIf DateDiff("s",application("mytime2"),now)>TimeInterval then
response.write "時間重設"
nowstr=now()
application.Lock
application("mytime")=DateToStr(nowstr,"w,d m y H:I:S")
application("mytime2")=nowstr
application.unLock
Else
If DateDiff("s",application("mytime2"),now)>=TimeInterval then
application.Lock
addstr=DateAdd("s",TimeInterval,application("mytime2"))
application("mytime")=DateToStr(addstr,"w,d m y H:I:S")
application("mytime2")=addstr
application.unLock
End If
End If
Response.write "上次儲存時間"&application("mytime2")
Response.write "<br>"
Response.write "下次儲存時間"&DateAdd("s",TimeInterval,application("mytime2"))
Response.write "<br>"
Function DateToStr(DateTime,ShowType)
Dim DateMonth,DateDay,DateHour,DateMinute,DateWeek,DateSecond
Dim FullWeekday,shortWeekday,Fullmonth,Shortmonth,TimeZone1,TimeZone2
TimeZone1="+0800"
TimeZone2="+08:00"
FullWeekday=Array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday")
shortWeekday=Array("Sun","Mon","Tue","Wed","Thu","Fri","Sat")
Fullmonth=Array("January","February","March","April","May","June","July","August","September","October","November","December")
Shortmonth=Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec")
DateMonth=Month(DateTime)
DateDay=Day(Date