張喜紅
(亳州職業(yè)技術(shù)學院智能工程系,安徽亳州 236800)
伴隨著大數(shù)據(jù)時代的快速到來,人們越來越傾向于借助數(shù)據(jù)揭示事物內(nèi)在規(guī)律,進而指導決策[1-2].因此,如何利用大數(shù)據(jù)做好中藥材價格走勢的及時預測,為中藥材市場運營決策提供支撐,促進市場有序運營,極具研究意義.目前對于價格推測、分析的方法主要有兩類,其一是基于影響價格變化因素采用特定的技術(shù)方法進行推理;其二是基于歷史數(shù)據(jù)的推理法.因素法由于影響因子多維善變、因子權(quán)重難于確定等原因,難于建模;時間序列分析是一種基于歷史價格數(shù)據(jù)的變化規(guī)律預測未來價格走勢的方法,是當前價格預測的主流方法之一.時間序列分析法實施的難點在于如何獲取足夠多且相對完整的歷史價格數(shù)據(jù)[3].
互聯(lián)網(wǎng)技術(shù)自誕生以來,在各行業(yè)得到了廣泛的應(yīng)用,互聯(lián)網(wǎng)在中醫(yī)、中藥領(lǐng)域的應(yīng)用也達到了前所未有的廣度,積累了相當豐厚的網(wǎng)絡(luò)數(shù)據(jù)資源.如中藥材天地網(wǎng)就積累了相當數(shù)量的中藥材價格信息,為時間序列分析法提供了強有力的數(shù)據(jù)支撐.然而,如何從網(wǎng)絡(luò)上快速、高效的收集這些數(shù)據(jù),并將其整理為便于分析的結(jié)構(gòu)化數(shù)據(jù),是極為關(guān)鍵的一步.網(wǎng)絡(luò)爬蟲是收集、提取網(wǎng)絡(luò)數(shù)據(jù)的主流技術(shù)手段[4-5].
基于上述背景,為了滿足基于時間序列分析法開展中藥材價格預測研究的數(shù)據(jù)需求,鑒于Python語言在爬蟲設(shè)計方面具有程序簡潔、資源豐富、便于實現(xiàn)等優(yōu)點,本文以中藥材天地網(wǎng)為目標網(wǎng)站,基于Python語言設(shè)計了一款用于中藥材價格信息收集的網(wǎng)絡(luò)爬蟲,采用Requests模塊實現(xiàn)網(wǎng)頁的Http請求,采用Beautifulsoup實現(xiàn)了目標信息的過濾、解析、提取,最終將目標數(shù)據(jù)保存為便于分析的結(jié)構(gòu)化文本文件數(shù)據(jù),同時就爬蟲的定時啟動、抓取進行了介紹.
從互聯(lián)網(wǎng)獲取相關(guān)信息,最直接的方法是通過瀏覽器輸入URL向服務(wù)器發(fā)起Http請求,請求成功后服務(wù)器返回一個包含目標網(wǎng)頁內(nèi)容的Response,經(jīng)瀏覽器解析后呈現(xiàn)給用戶.如果用戶想統(tǒng)計、收集某個網(wǎng)站成千上萬條的信息記錄條,若以瀏覽器人工訪問網(wǎng)頁的方式進行,不僅效率低下且易出錯[6].基于此,爬蟲的概念便誕生了,爬蟲通俗來講是一段實現(xiàn)自動訪問網(wǎng)頁,并自動定向提取網(wǎng)頁中目標信息的程序.網(wǎng)絡(luò)爬蟲典型的工作流程大致包含如下幾個步驟:①模擬或自動調(diào)用網(wǎng)頁瀏覽器發(fā)送請求并獲取網(wǎng)頁源碼;如在Python中可使用Request庫的相關(guān)方法向服務(wù)器發(fā)起模擬請求,待響應(yīng)成功后,將返回一個包含多種媒體格式的Response.②過濾、提取網(wǎng)頁源碼中包含的目標信息;即從網(wǎng)頁源碼中通過XPath、正則表達式或Beautifulsoup等模塊的相應(yīng)方法,定位、提取目標信息.③將提取的目標信息存儲;保存形式多樣化,可以保存成文本,也可以保存至數(shù)據(jù)庫,或者保存成特定格式的文件.
中藥材天地網(wǎng)自建站以來,其市場價格欄目每天實時公布亳州、安國、玉林及荷花池4個藥市數(shù)百種中藥材的規(guī)格與價格信息,且其公布的中藥材價格數(shù)據(jù)真實可靠,為中藥材價格走勢的預測提供了真實、可靠的源數(shù)據(jù).在網(wǎng)頁瀏覽器中輸入藥材價格欄目的首頁URL地址:http://www.zyctd.com/jiage/1-0-0.html,可得到圖1所示的頁面,在頁面的價格信息區(qū)按品名、規(guī)格、市場、當前價格等題頭逐行呈現(xiàn)中藥材的價格信息,且分多頁顯示,在頁面的底部給出了分頁鏈接信息.根據(jù)上述分析可知,在爬蟲的設(shè)計過程中,需要解決如下問題:①獲取各個分頁的URL鏈接地址;②提取各分頁信息記錄條的目標信息.
如前面所述爬蟲要想從網(wǎng)頁中提取信息,首先需將網(wǎng)頁源碼下載到本地,網(wǎng)頁源碼的下載通過Http請求實現(xiàn),Requests模塊是Python語言開發(fā)的Http庫,其功能強大,實現(xiàn)簡單[7-9].對于采用GET方式打開的網(wǎng)頁,可采用語句requests.get(“URL地址參數(shù)”).text方法模擬請求,得到網(wǎng)頁源后將其存儲為文本格式.同時BeautifulSoup是基于Python語言開發(fā)的一個用于解析html對象的第三方庫.對于結(jié)構(gòu)化網(wǎng)頁信息的提取,與正則表達式相比更具優(yōu)勢.其提供的find()與find_all()方法使信息定位、過濾、提取的實現(xiàn)更加簡單[10-13].同時考慮到中藥材天地網(wǎng)結(jié)構(gòu)規(guī)范,且要提取的目標信息都是文本字段,最終決定采用Requests模塊進行模擬Http請求下載目標網(wǎng)頁源碼,采用BeautifulSoup模塊過濾、解析、提取目標信息.
借助瀏覽器的審查元素工具,分析各頁中的源碼架構(gòu),如圖2所示,每頁中的每條信息記錄條處于同一
def get_page_values(self, now_url): # 其中now_url參數(shù)為網(wǎng)頁的URL地址
now_html = requests.get(now_url).text # 下載網(wǎng)頁源碼,并以文本方式儲存
now_Soup = BeautifulSoup(now_html, 'lxml')# 以網(wǎng)頁文檔解析源碼
all_value_li = now_Soup.find('div', class_='priceTable').find_all('li')#定位所有
for tag in all_value_li:#遍歷所有
name = tag.find('span', class_='w1').get_text().encode('utf-8')
#提取“品名”
guige = tag.find('span', class_='w2').get_text().encode('utf-8')
#提取“規(guī)格”
shichang = tag.find('span', class_='w9').get_text().encode('utf-8')
#提取“市場”
price = tag.find('span', class_='w3').get_text().encode('utf-8')
#提取“價格”
self.write_txt(name, guige, shichang, price)#將目標信息存入文件
通過瀏覽器查看各個分頁的URL地址可知:各分頁的URL地址是由首頁URL地址加一個“-”與分頁號構(gòu)成,如:首頁的URL地址為:http://www.zyctd.com/jiage/1-0-0.html,第201頁的URL地址為:http://www.zyctd.com/jiage/1-0-0-201.html.如圖1(b)所示,首頁底部的分頁鏈接按鈕給出了分頁面的總數(shù),如當前一共有201個頁面.通過審查元素工具,可知分頁總數(shù)位于
def get_all_page_values(self):#獲取所有分頁面中記錄條信息
# 下載首頁源碼
html = requests.get('http://www.zyctd.com/jiage/1-0-0.html').text
# 以網(wǎng)頁解析文檔
Soup = BeautifulSoup(html, 'lxml')
# 定位到最后一頁的頁碼值對應(yīng)的標簽區(qū)
all_li = Soup.find('div', class_='pageBreak').find_all('a')
# 提取最后一頁的頁碼值,#獲取最大頁碼值,即頁面總數(shù)
Page_max = int(all_li[4].get_text())
all_page_value = []
for i in range(1, Page_max + 1):
if i == 1:
# 為1時是首頁,URL地址較特殊
temp_url = 'http://www.zyctd.com/jiage/1-0-0.html' else:
# 字串拼接構(gòu)造分頁URL地址
temp_url = 'http://www.zyctd.com/jiage/1-0-0-' + str(i) + '.html'
# 調(diào)用頁面目標信息提取函數(shù),獲取當前分頁中所有記錄條的品名、規(guī)格、市場、價格等目標信息
now_page = self.get_values(temp_url)
all_page_value.extend(now_page)
result_df = pd.DataFrame(all_page_value)
returnresult_df
鑒于文本文件的通用性較好,且便于后期的跨平臺分析,文中將提取到的目標數(shù)據(jù)采用文本文件進行存儲.為了便于后期按分隔符導入表格文件,在寫入文本文件時,一條記錄條的品名、規(guī)格、市場及價格之間采用逗號分隔,各條記錄條間采用回車進行分隔.同時考慮到中藥材天地網(wǎng)的價格信息是按天發(fā)布,為了避免信息的重復,在每天爬取數(shù)據(jù)時,以當前系統(tǒng)日期為文件名創(chuàng)建文件,當前系統(tǒng)日期的獲取通過Python的datetime模塊中的datetime.now().date().isoformat()實現(xiàn).詳細實現(xiàn)代碼如下:
def write_txt(self,name,guige,shichang,price):
#以當前系統(tǒng)日期為文件名創(chuàng)建本次存儲文件
file_name=str(self.path_)+'/'+datetime.now().date().isoformat()+'.txt'
with open(file_name, 'a') as f:
f.write(name)#品名
f.write(',')#逗號分隔
f.write(guige)#規(guī)格
f.write(',')#逗號分隔
f.write(shichang)#市場
f.write(',')#逗號分隔
f.write(price)#價格
f.write(' ')#不同記錄條間“回車”分隔
中藥材天地網(wǎng)按天更新各藥材價格信息,因此需每天運行爬蟲,對更新的價格進行采集,如果爬蟲每天的啟動工作由用戶人工完成,事必增加了用戶的工作事項,多有不便.倘若有一天用戶忘記了此項任務(wù),將會導致當天信息缺失.考慮到當前用戶電腦以windows系統(tǒng)為主流,同時windows系統(tǒng)自帶任務(wù)計劃程序安排功能,因此采用windows自帶的任務(wù)計劃來實現(xiàn)爬蟲的定時啟動.以Win7系統(tǒng)為例,具體的部署方法是:①創(chuàng)建bat批處理文件,在文件中書寫如:“python 爬蟲文件名.py”格式的命令;②依次進入系統(tǒng)“控制面板”/“管理工具”/“任務(wù)計劃程序”/“創(chuàng)建任務(wù)”欄目,創(chuàng)建一個每天指定時間啟動①中批處理文件的新任務(wù);③在“任務(wù)計劃程序”任務(wù)安排列表中選中②中創(chuàng)建的新任務(wù),并點選“運行”按鈕啟動.
將所設(shè)計的爬蟲按照上述方法,部署到CPU型號為Intel(R) Core(TM) i3-4160 3.6GHz,內(nèi)存為4GB,操作系統(tǒng)為Win7-64位的平臺上,對目標網(wǎng)頁進行信息爬取,得到如圖3所示的目標信息,此次測試運行共計收集201頁20051條記錄,用時約1026毫秒.經(jīng)人工與網(wǎng)頁實際數(shù)據(jù)對比,信息記錄條數(shù)一致,無重復,無缺項.進一步證實,所設(shè)計的爬蟲運行效率較高,準確無誤,可用于中藥材價格數(shù)據(jù)的收集.
圖3 目標信息片斷
本文以中藥材價格預測的研究為背景,為了收集大量的中藥材價格數(shù)據(jù),瞄準互聯(lián)網(wǎng)上的數(shù)據(jù)資源,以中藥材天地網(wǎng)為目標網(wǎng)站,在深入分析其網(wǎng)頁布局結(jié)構(gòu)及信息發(fā)布規(guī)則的基礎(chǔ)上,基于Python語言的Requests、Beautifulsoup等模塊,設(shè)計了一款中藥材價格信息爬蟲,同時就爬蟲在windows系統(tǒng)如何實現(xiàn)定時自動運行的部署進行了介紹.經(jīng)實驗測試,所設(shè)計的爬蟲運行可靠、效率較高,所得數(shù)據(jù)與網(wǎng)頁公布一致無誤,為從互聯(lián)網(wǎng)收集中藥材相關(guān)信息提供了參考方法.雖然所設(shè)計的爬蟲能夠準確無誤的獲取中藥材價格信息,但是為了拓寬其使用人群范圍,需在后續(xù)的研究中解決其跨平臺部署不便的問題,讓其能脫離Python環(huán)境運行.