1. 程式人生 > >Linux 抓取網頁例項(shell+awk)

Linux 抓取網頁例項(shell+awk)

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

上一篇部落格講了Linux抓取網頁的方式,有curl和wget兩種方式,這篇將重點講Linux抓取網頁的例項——抓取google play全球12國的遊戲TOP排名

要抓取google play

遊戲排名網頁,首先需要分析網頁的特點和規律:

1、google play遊戲排名網頁,是一個就“總-分”形式,即一頁網址顯示若干排名(如24個),有若干個這樣的網頁組成全部遊戲的總排名

2、每頁網址中,點選每個單獨的遊戲連線,可以檢視本遊戲的屬性資訊(如評價星級、釋出日期、版本號、SDK版本號、遊戲類別、下載量等)


需要解決的問題:

1、如何抓取全部遊戲總排名?

2、抓取到總排名後,如何拼接URL來抓取每個單獨的遊戲網頁?

3、抓取到每個單獨遊戲網頁後,如何提取網頁中游戲的屬性資訊(即評價星級、釋出日期。。。)?

4、提取到了每個單獨遊戲屬性資訊後,如何儲存(mysql)、生成每日報表(html)、傳送每日報表(email)?

5、根據抓取的遊戲屬性資訊資源,如何查詢自己公司的遊戲排名(JSP)、如何清晰的展現遊戲排名(JFreeChart圖表)?

6、更難的是,google play遊戲排名,並沒有全球統一的排名,google採用本地化策略,幾十個國家都有自己的一套排名演算法和規則,如何實現12國遊戲排名?


設計方案和技術選擇

分析完上述的這些問題需求後,如何逐一解決,各個擊破,便是需要我們思考、設計和解決的問題(模組流程和技術實現)?

基於上面分析提出的問題,下面將逐一進行模組設計、技術方案選擇:




1、為了抓取12國的遊戲排名,需要分別在12國租用代理伺服器,才能抓取各國的遊戲排名(12國遊戲排名演算法、語言都不同,有中文、英文、日語、俄語、西班牙語...)

2、抓取網頁,使用curl+proxy代理的方式;提取下載的網頁資訊,使用awk文字分析工具(需要對html語法tag、id等元素非常瞭解,才能準確利用awk提取遊戲屬性資訊)

3、由於IP代理篩選系統、抓取網頁程式、提取遊戲屬性資訊等模組全部都是利用指令碼完成,為了保持程式語言的一致性,資料庫的建立、記錄插入也都是用shell指令碼實現

4、抓取的每個遊戲屬性資訊,採用html+table以網頁的形式展現出來,清晰、直觀。其中使用到了shell指令碼來拼接html字串(table + tr + td + info)

5、生成的html網頁,每日以郵件形式定時發給產品總監、PM,以及RD和QA,瞭解公司釋出的遊戲排名情況,以及全球排名上升最快、最熱門的遊戲趨勢

6、開發一個JSP網頁查詢系統,根據輸入的遊戲名稱或遊戲包名兩種方式查詢一個遊戲的排名及趨勢,且在趨勢圖下面顯示該遊戲的詳細的全部屬性資訊


模組技術實現

1、IP代理篩選

費用考慮,每個國家租用一臺代理伺服器(VPN),按市場最低價1000元/月計,一年12000元,12國家總費用為12x12000=144000,即大約需要14萬/年的VPN租借費用

基於成本開銷的考慮,後來我通過深入調研代理伺服器和免費ip,提出了自己設計開發一套免費ip代理伺服器篩選系統,來分別抓取12國遊戲排名

免費代理IP主要來源於上一篇部落格中介紹的兩個網站:freeproxylists.net 和 xroxy.com,強烈推薦使用米撲代理:proxy.mimvp.com

米撲代理,每天提供20個免費代理使用,支援http、https、socks4、socks5等四種協議,覆蓋120多個國家,中國34個省市

米撲代理官網http://proxy.mimvp.com

IP代理篩選系統,由於文字預處理和篩選邏輯實現都較為複雜,將在下一篇部落格中單獨介紹


2、抓取排名網頁

仔細分析google play遊戲排名網頁,可以發現是有規律可循:

第一頁Top24網址:https://play.google.com/store/apps/category/GAME/collection/topselling_free

第二頁Top48網址:https://play.google.com/store/apps/category/GAME/collection/topselling_free?start=24&num=24

第三頁Top72網址:https://play.google.com/store/apps/category/GAME/collection/topselling_free?start=48&num=24

。。。

至此,觀察每頁網址最後的一段字串 ?start=24&num=24 ,已經發現規律了吧 ^_^  其實第一頁的網頁從start=0開始,也可以寫成:

第一頁Top24網址:https://play.google.com/store/apps/category/GAME/collection/topselling_free?start=0&num=24

根據上面的規律,就可以通過迴圈拼接字串,用curl+proxy來抓取排名網頁了(start = 'expr $start + 24')


3、提取遊戲連結

排名網頁,每頁包含24個遊戲網址超連結,如何提取到這24個遊戲網址超連結?

當時考慮過使用xml解析,因為html都是層級組織起來的類xml格式,但有些網頁也不全是標準的html格式(如左括號後沒有右括號閉包),這會導致xml無法正確解析

後來結合自己學過的html和js知識,分析抓取排名網頁的內容結構,發現每個遊戲連結前面都還有一個唯一的 class="title" 具體格式如下(Basketball Shoot 為例):

<a class="title" title="Basketball Shoot" data-a="1" data-c="1" href="/store/apps/details?id=com.game.basketballshoot&feature=apps_topselling_free">Basketball Shoot</a>

這樣,可以順利通過awk來提取 class="title" 附近的文字內容,具體實現如下:

# split url_24page_key='class="title"'page_output='output_page.log'page_output_url_start='https://play.google.com/store/apps/'page_output_url='output_top800_url.log'function page_split(){    grep $page_key $(ls $url_output* | sort -t "_" -k6 -n) > tmp_page_grepURL.log            # use $url_output    awk -F'[<>]' '{for(i=1;i<=NF;i++){if($i~/'$page_key'/){print $i}}}' tmp_page_grepURL.log > tmp_page_titleURL.log    awk -F'["""]' '{print $4 $10}' tmp_page_titleURL.log > $page_output            rm -rf tmp_page_grepURL.log    rm -rf tmp_page_titleURL.log    merge top800 url    rm -rf $page_output_url    touch $page_output_url    awk -F'["/"]' '{for(i=1;i<=NF;i++){if($i~/'details'/){print $i}}}' $page_output > tmp_top800_url.log        index=1    while read line    do        echo $line        echo $index        echo -e $page_output_url_start$line >> $page_output_url        index=`expr $index + 1`    done < tmp_top800_url.log    rm -rf tmp_top800_url.log}

指令碼功能說明:

grep,首先對下載的排名網頁檔案,按照編號從小到大排列,保證遊戲的排名順序;然後利用grep提取我們需要的某些行到臨時檔案,大大減少我們需要分析的檔案內容

awk,指定多個分隔符“<>”來格式化輸入的文字(awk -F'[<>]')為多個子字串陣列,通過迴圈判斷分割的子字串陣列中是否包含有$page_key字串(if($i~/'$page_key'/))。如果有,則把此子字串全部輸出到另一臨時檔案中tmp_page_titleURL.log中;如果沒有,則捨棄。

格式化後提取的遊戲超連結如下:


上圖,文字處理後包含遊戲的名稱(title)和遊戲的超連結(href),接下來就是提取遊戲名稱(title)和遊戲超連結(href),最後拼接href和域名組成一個完整的超連結


awk,指定分隔符““來格式化上圖的文字(awk -F'["""]')為多個子字串陣列,然後提取陣列的第4個和第10個欄位(awk分割的欄位以下標1開始),提取結果如下:


上圖,進一步文字處理後,提取出了遊戲名稱(title)和遊戲連結(href),接著再提取我們真正需要的連結資訊(details後的字串)


通過臨時檔案儲存了我們文字處理的中間結果,處理完後可以把建立的臨時檔案刪除(rm -rf  ***)

awk,指定分隔符”/“來格式化上圖的文字(awk -F'["/"]')為多個子字串陣列,通過迴圈判斷分割的子字串陣列中是否包含有'details'字串(if($i~/'details'/))。如果有,則把此子字串全部輸出到臨時檔案中tmp_top800_url.log中;如果沒有,則捨棄。

格式化後提取的遊戲超連結如下:



最後,while read line迴圈,新增域名頭($page_output_url_start),拼接出完整超連結地址(echo -e $page_output_url_start$line >> $page_output_url),拼接結果如下:


ok,通過awk強大的文字處理能力,遊戲網頁超連結處理完畢(千呼萬喚始出來呀~~)!下面就是利用 curl+proxy 抓取對應的遊戲網頁了。。。。 O(∩_∩)O


4、抓取遊戲網頁

根據模組3提取的遊戲超連結,利用上篇部落格介紹的curl+proxy方式抓取遊戲網頁,示例如下:

curl -x 125.69.132.100:8080 -o html_2 https://play.google.com/store/apps/details?id=com.game.basketballshoot&feature=apps_topselling_free

利用瀏覽器開啟抓取下來的網頁html_2,結果截圖如下:



ok,成功抓取到了遊戲網頁,下一步就是提取每個遊戲網頁總綠色框內的遊戲屬性資訊即可(提取方式與模組3提取遊戲連結方法類似,也是使用awk文字分析處理工具)

不過,這裡需要注意幾點:

  • 在我的指令碼程式中通過代理抓取網頁的語句,比上面給出的要複雜一些,主要是實際測試中考慮到了連線超時、網速快慢、ip代理突然失效等特殊情況,在此不貼具體程式碼,感興趣的同學可以自己研究一下
  • 在下載遊戲網頁的過程中,如果代理ip突然失效,導致無法繼續抓取網頁,這時該怎麼辦?(其實上面模組2抓取排名網頁,也會遇到此問題,這個問題具體的解決方案,在下篇部落格的ip免費代理系統中將做詳細介紹)
  • 抓取下來的遊戲網頁,如何確定他們的排名順序?(其實在模組3中,這個遊戲排名問題已經解決了,細心的童靴可以自己去上面模組3的指令碼中尋找答案。。。)


5、提取遊戲屬性

提取抓取遊戲網頁中的屬性資訊(即提取上面模組4的html_2中的綠色方框資訊),提取方式與模組3提取遊戲連結方法類似,也是使用awk文字分析處理工具

通過分析下載的網頁內容,找出唯一能夠表示屬性資訊的欄位(如id、class、tag等),具體實現程式碼請參考模組3給出的指令碼,在此不再貼出具體實現程式碼


6、儲存屬性到資料庫

  • 要儲存提取的遊戲屬性資訊,首先需要建立MySQL資料庫和表,shell建立資料庫指令碼如下:
# Author        : yanggang# Datetime      : 2011.10.24 21:10:28# ============================================================#!/bin/shlog='SQL_insert_one.sh.log'if [ ! -e $log ]; then    touch $logfidate=$(date "+%Y-%m-%d__%H:%M:%S")echo >> $logecho "=================  $date  ================" >> $log# mysql database and table to createHOST='localhost'PORT='3306'USER='root'PWD='xxxxxx'DBNAME='top800'TABLENAME='gametop800'mysql_login=''mysql_create_db=''mysql_create_table=''function mysql_create(){    echo "login mysql $HOST:$PORT ..." >> $log    mysql_login="mysql -h $HOST -P $PORT -u $USER -p$PWD"  # mysql -h host -P port -u root -p pwd    echo | ${mysql_login}    if [ $? -ne 0 ]; then        echo "login mysql ${HOST}:${PORT} failed.." >> $log        exit 1    else        echo "login mysql ${HOST}:${PORT} success!" >> $log    fi    echo "create database $DBNAME ..." >> $log    mysql_create_db="create database if not exists $DBNAME"    echo ${mysql_create_db} | ${mysql_login}    if [ $? -ne 0 ]; then        echo "create db ${DBNAME} failed.." >> $log    else        echo "create db ${DBNAME} success!" >> $log    fi    echo "create table $TABLENAME ..." >> $log    mysql_create_table="create table $TABLENAME(        id char(50) not null,        url char(255),        top int,        name char(100),        category char(50),        rating char(10),        ratingcount char(20),        download char(30),        price char(20),        publishdate char(20),        version char(40),        filesize char(40),        requireandroid char(40),        contentrating char(40),        country char(10) not null,        dtime date not null default \"2011-01-01\",        primary key(id, country, dtime)    )"    echo ${mysql_create_table} | ${mysql_login} ${DBNAME}     if [ $? -ne 0 ]; then        echo "create table ${TABLENAME} fail..." >> $log    else        echo "create table ${TABLENAME} success!" >> $log    fi}
指令碼功能說明: 首先,登陸mysql資料庫,判斷mysql伺服器、埠號、使用者名稱和密碼是否正確,如果不正確,則登陸失敗,退出(exit 1);如果正確,則登陸成功,繼續下一步 然後,建立資料庫名,判斷資料庫是否存在,如果不存在,則建立;如果存在,則繼續下一步(注:建立資料庫時,需要先驗證登陸資料庫是否成功,否則無法操作) 最後,建立資料庫表,先設計資料庫表的各個欄位,然後建立資料庫表,具體判斷方法同建立資料庫名

  • 遍歷遊戲屬性資訊的文字,全部插入到mysql資料庫中,進行統一儲存和管理
# Author        : yanggang# Datetime      : 2011.10.24 21:45:09# ============================================================#!/bin/sh# insert mysqlfile_input='output_top800_url_page'file_output='sql_output'HOST='localhost'PORT='3306'USER='root'PWD='xxxxxx'DBNAME='top800'TABLENAME='gametop800'col_id=''col_url=''col_top=1col_name=''col_category=''col_rating=''col_ratingcount=''col_download=''col_price=''col_publishdate=''col_version=''col_filesize=''col_requireandroid=''col_contentrating=''col_country=''col_dtime=''sql_insert='insert into gametop800 values("com.mobile.games", "url", 3, "minesweeping", "games", "4.8", "89789", "1000000-5000000000", "free", "2011-2-30", "1.2.1", "1.5M", "1.5 up", "middle", "china", "2011-10-10")'function mysql_insert(){    rm -rf $file_output    touch $file_output    DBNAME=$1    col_dtime=$2    col_country=$3    echo 'col_dtime========='$col_dtime    while read line    do        col_id=$(echo $line | cut -f 1 -d "%" | cut -f 1 -d "&" | cut -f 2 -d "=")        col_url=$(echo $line | cut -f 1 -d "%")        col_name=$(echo $line | cut -f 2 -d "%")        col_category=$(echo $line | cut -f 3 -d "%")        col_rating=$(echo $line | cut -f 4 -d "%")        col_ratingcount=$(echo $line | cut -f 5 -d "%")        col_download=$(echo $line | cut -f 6 -d "%")        col_price=$(echo $line | cut -f 7 -d "%")        col_publishdate=$(echo $line | cut -f 8 -d "%")        col_version=$(echo $line | cut -f 9 -d "%")        col_filesize=$(echo $line | cut -f 10 -d "%")        col_requireandroid=$(echo $line | cut -f 11 -d "%")        col_contentrating=$(echo $line | cut -f 12 -d "%")        sql_insert='insert into '$TABLENAME' values('"\"$col_id\", \"$col_url\", $col_top, \"$col_name\", \"$col_category\", \"$col_rating\", \"$col_ratingcount\", \"$col_download\", \"$col_price\", \"$col_publishdate\", \"$col_version\", \"$col_filesize\", \"$col_requireandroid\", \"$col_contentrating\", \"$col_country\", \"$col_dtime\""');'                echo $sql_insert >> $file_output        mysql -h $HOST -P $PORT -u $USER -p$PWD -e "use $DBNAME; $sql_insert"        col_top=`expr $col_top + 1`    done < $file_input}
指令碼功能說明: 插入資料庫指令碼比較簡單,主要實現了兩個功能:遊戲排名序號(col_top)和資料庫語句插入($sql_insert)
通過 while read line迴圈,讀取模組5提取的遊戲屬性資訊文字檔案,分割每行得到相應的欄位(cut -f 2 -d "%"),賦值到插入語句中(sql_insert) 最後,通過 mysql -h $HOST -P $PORT -u $USER -p$PWD -e "use $DBNAME; $sql_insert",登陸到mysql資料庫,執行插入語句$sql_insert


7、生成HTML報表

shell通過拼接字串table + tr + td + info的形式,生成html網頁報表,請詳見我先前寫的部落格:shell 實現txt轉換成html


8、郵件傳送報表

郵件傳送模組,主要採取/usr/bin/mutt方式,郵件正文顯示一張html報表(預設是美國),其它國家以附件形式傳送,請詳見我先前寫的部落格:linux shell 傳送email 附件

郵件定時傳送,採用了crontab命令,具體配置和使用方法,請詳見我先前寫的部落格:linux定時執行命令指令碼——crontab


9、網頁查詢報表

通過JSP提取儲存在MySQL的遊戲屬性資訊,迴圈遍歷生成遊戲排名的網頁資訊,請參考我先前寫的部落格:Linux JSP連線MySQL資料庫


10、排名趨勢圖

趨勢圖,採用了第三方的JFreeChart圖表生成工具,請詳見我先前的寫的部落格:JFreeChart學習示例

生成遊戲排名趨勢圖後,需要巢狀到JSP網頁中進行顯示,完整的排名趨勢圖,請詳見我先前寫的部落格:JFreeChart專案例項



自動化總控指令碼

12國遊戲排名系統,從免費ip代理篩選——》網頁抓取——》資料庫儲存——》生成排名報表——》定時傳送郵件報表——》遊戲排名查詢——》趨勢圖生成

全部都實現了總流程的自動化,下面是各個模組的指令碼實現和功能說明:


通過配置伺服器的crontab定時執行程序命令,在每天凌晨00:01:00時刻(凌晨零時1分零秒),將會自動啟動總控指令碼top10_all.sh


每日生成的日報,都是通過總控指令碼自動生成一個當天的資料夾,來儲存當天的抓取資料、分析資料、結果資料,如下圖所示:


注:以上資料夾資料是拷貝的去年測試資料,在我自己的筆記本上沒有抓取排名

因為通過遠端代理抓取12國排名的前TOP800,是比較耗費網路資源、記憶體資源和時間,嚴重影響我上網體驗  ~~~~(>_<)~~~~ 



架構設計與評析

抓取遊戲排名系統,設計之初並沒有想的這麼複雜,當時只用了一週時間搭建了抓取國內google play遊戲排名(使用curl抓取國內排名,不需用代理的)

後來,根據提出的各種需求,不斷新增、重構、完善的,有點像快速原型的開發流程吧~~  @[email protected]

整套系統,從需求到demo原型,再到郵件傳送、網頁檢視、趨勢圖查詢、免費ip代理設計與實現,前前後後大約花了近兩個月(期間還負責開發兩款遊戲。。。好忙滴~)


總體而言,我當時設計時主要遵循了兩個原則:

1、網頁抓取、文字處理、資料庫儲存等資料來源資訊,全部統一使用指令碼實現,開發語言保持純潔性

2、各個功能模組,劃分為子問題獨立實現,流程之間採用分層設計,用膠水語言搭積木的組合起來


後來實踐證明,這種設計方法和原則,是完全正確的

因為開始給的需求只是抓取10國遊戲排名,歐洲和印度兩國是後加的,記得當時抓取、測試、釋出這兩個新增的國家,大約只花了一個晚上兩三個小時就搞定!

基於上述的架構設計,新新增一個國家,只需要簡單幾步(以新增印度india為例):

a、去freeproxylists.net 查詢對應國家(印度)免費的ip代理,放到免費代理篩選系統(testProxy)相應目錄下,簡單新增上這個國家資訊即可(下一篇部落格詳細講解)

b、複製中國的指令碼為印度 cp top800_proxy_china.sh  top800_proxy_india.sh,並把 top800_proxy_india.sh 中全部的china修改為india,批量修改命令如下:

 sed  -i  "s/china/india/g"  top800_proxy_india.sh 

c、在12國總控指令碼(top800_proxy_all.sh)中,新增上印度的網頁抓取指令碼 top800_proxy_india.sh,並在郵件附加中,新增上印度的html附件

d、在資料庫指令碼(sql_insert_x_country.sh)中,新增上印度的抓取網頁資料夾,儲存印度的遊戲資訊到mysql;在JSP網頁和查詢選項中,都新增上印度一項即可

e、ok,新增完畢!



總體評析這套系統架構

優點:

1、功能模組相對獨立,便於功能擴充和維護

2、開發語言全採用shell+awk,模組流程之間便於呼叫和組合

3、新增新的國家排名,僅僅修改幾處配置即可,不需要了解模組內部實現過程

4、趨勢圖工具JFreeChart也是Java實現,便於JSP呼叫和巢狀,清晰的顯示遊戲排名趨勢

5、異地備份mysql資料庫,在自動化總控指令碼中採用了每天異地備份(scp),降低了歷史資料丟失的概率(異地備份需建立兩機的信任關係,詳見我先前的部落格


需要進一步完善:

1、抓取生成的12國遊戲排名報表,包含了近10種各國語言,有中文、英語、日語、俄語、西班牙語、韓語、法語、德語、義大利語。。。貌似八國聯軍。。。哈

後期可以考慮呼叫google的translate翻譯API介面,把報表的10種語言全部翻譯成中文或英文,方便檢視,不用再去手動一個一個遊戲查詞典了。。。

2、目前搭在一臺伺服器上,同時在後臺執行多個網頁抓取指令碼(./xxx.sh &),12國TOP800排名,抓取下載的資料量比較大時間較長,後期改進為多臺伺服器同時抓取

3、這套系統,雖然實現了全流程控制,我也寫了對應模組的功能說明文件(readme),但後期他人維護仍然時有問題,畢竟學習指令碼會有時間、精力成本,而且指令碼語言不夠直觀,命令引數語法簡潔的同時也有點苦澀,不是那麼好懂理解,後期看用什麼好的圖形介面(GUI)封裝起來,方便維護

4、現在android開發競爭很激烈,掌握遊戲排名特別是遊戲發展趨勢非常重要,後期看能不能把這套系統封裝起來,做成一個商業應用軟體 $^_^$



總結

這整套系統,全部是由我自己獨立設計、實現、測試、上線、維護、完成。


回頭看一看,這套系統涉及到的知識點和技術比較多,有好多我從前都沒接觸過,如awk、JSP、Tomcat、mutt、crontab、JFreeChart

但正是有這樣的機遇和挑戰,才更能考研一個人獨立思考、分析問題和解決問題的能力,特別是快速再學習的能力



下面談談我在設計和實現這套系統過程中,所遇到的困難、走過的彎路,以及解決問題的經驗心得體會:

遇到的困難

1、不清楚該選擇哪套實施方案

抓取網頁排名,開始不知道應該選擇應用程式實現,還是指令碼實現,因為創業團隊非常注重效率和成本,而且要求儘快看到原型和效果,顯然指令碼開發較快

2、抓取網頁後的內容提取

內容提取,到底是使用xml解析整套html檔案,還是有其它更好的替代方案。曾做過xml解析,開始我就選了xml方式分析提取,後來發現我錯了,因為某些html非標準結構

3、linux下的郵件傳送和定時執行程序,該怎麼實現呢?

請教技術高手,得到了肯定答覆:linux某些命令肯定是可以實現,於是自己去網上查詢、驗證,發現有成熟的方案(網上有些解決方法行不通,當時綜合了好幾種方法)

4、生成遊戲趨勢的圖表,是採用第三方開源引擎呢?還是直接使用Java自帶的圖形工具繪製?

從開發效率角度講,肯定首選開源或免費的第三方圖形工具,當時通過查資料調研發現:JChartJFreeChart都可以實現,且都是用Java編寫開發



經驗心得體會

1、知識面要非常廣

系統採用了多種不同的工具,如shell指令碼、代理伺服器、MySQL資料庫、HTML網頁、mutt郵件傳送、JSP網站及搭建、JFreeChart調研(詳見我的百度部落格

既有前端開發(HTML、JSP),又有後臺服務(Tomcat網站搭建、資料庫連線),還有指令碼語言(shell、awk)、圖形工具(JFreeChart),像開雜貨店鋪,存貨要多


2、快速再學習能力

當年在百度學了一些shell指令碼,但是設計開發全shell實現的排名系統,顯然還需要加強學習和積累,在專案實現的過程中我是需要什麼技術就立刻去學什麼技術

大學和研一,都做過網站開發,熟悉一些html/css、asp.net,去百度頭一個月也跟著師傅學了幾招js,於是拼接table、html不在話下,學習jsp也很輕鬆,畢竟有一些內功

mysql資料庫祕籍,都修煉了四五年,就不用說了,很簡單;搭建tomcat,在網上搜索了一篇教程,三加五除二就搞定,原理跟IIS和Apache都差不多,解析網頁的服務端

JChart和JFreeChart都是Java圖形生成工具,但需從費用、易學習、文件示例、通用性等多個角度綜合考量,最終選擇了JFreeChart圖形方案


3、虛心多學多積累

遇到技術方案選擇和知識盲區時,需要多去查閱資料,調研已有成熟的技術解決方案,拿來自己用;如果找不到,虛心多向技術大牛請教,大牛們一般都會很熱心點撥你

然後根據大牛們提示的思路,自己去尋找解決問題的途徑;問題解決後,需要多思考多總結,為什麼自己當時想不到呢。。。然後積累下來,久而久之,經驗沉澱就多了




致謝:

本文的代理,由米撲代理免費贊助,米撲代理每天提供20個免費代理

米撲代理官網http://proxy.mimvp.com




           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述