张喜红
(亳州职业技术学院智能工程系,安徽亳州 236800)
伴随着大数据时代的快速到来,人们越来越倾向于借助数据揭示事物内在规律,进而指导决策[1-2].因此,如何利用大数据做好中药材价格走势的及时预测,为中药材市场运营决策提供支撑,促进市场有序运营,极具研究意义.目前对于价格推测、分析的方法主要有两类,其一是基于影响价格变化因素采用特定的技术方法进行推理;其二是基于历史数据的推理法.因素法由于影响因子多维善变、因子权重难于确定等原因,难于建模;时间序列分析是一种基于历史价格数据的变化规律预测未来价格走势的方法,是当前价格预测的主流方法之一.时间序列分析法实施的难点在于如何获取足够多且相对完整的历史价格数据[3].
互联网技术自诞生以来,在各行业得到了广泛的应用,互联网在中医、中药领域的应用也达到了前所未有的广度,积累了相当丰厚的网络数据资源.如中药材天地网就积累了相当数量的中药材价格信息,为时间序列分析法提供了强有力的数据支撑.然而,如何从网络上快速、高效的收集这些数据,并将其整理为便于分析的结构化数据,是极为关键的一步.网络爬虫是收集、提取网络数据的主流技术手段[4-5].
基于上述背景,为了满足基于时间序列分析法开展中药材价格预测研究的数据需求,鉴于Python语言在爬虫设计方面具有程序简洁、资源丰富、便于实现等优点,本文以中药材天地网为目标网站,基于Python语言设计了一款用于中药材价格信息收集的网络爬虫,采用Requests模块实现网页的Http请求,采用Beautifulsoup实现了目标信息的过滤、解析、提取,最终将目标数据保存为便于分析的结构化文本文件数据,同时就爬虫的定时启动、抓取进行了介绍.
从互联网获取相关信息,最直接的方法是通过浏览器输入URL向服务器发起Http请求,请求成功后服务器返回一个包含目标网页内容的Response,经浏览器解析后呈现给用户.如果用户想统计、收集某个网站成千上万条的信息记录条,若以浏览器人工访问网页的方式进行,不仅效率低下且易出错[6].基于此,爬虫的概念便诞生了,爬虫通俗来讲是一段实现自动访问网页,并自动定向提取网页中目标信息的程序.网络爬虫典型的工作流程大致包含如下几个步骤:①模拟或自动调用网页浏览器发送请求并获取网页源码;如在Python中可使用Request库的相关方法向服务器发起模拟请求,待响应成功后,将返回一个包含多种媒体格式的Response.②过滤、提取网页源码中包含的目标信息;即从网页源码中通过XPath、正则表达式或Beautifulsoup等模块的相应方法,定位、提取目标信息.③将提取的目标信息存储;保存形式多样化,可以保存成文本,也可以保存至数据库,或者保存成特定格式的文件.
中药材天地网自建站以来,其市场价格栏目每天实时公布亳州、安国、玉林及荷花池4个药市数百种中药材的规格与价格信息,且其公布的中药材价格数据真实可靠,为中药材价格走势的预测提供了真实、可靠的源数据.在网页浏览器中输入药材价格栏目的首页URL地址:http://www.zyctd.com/jiage/1-0-0.html,可得到图1所示的页面,在页面的价格信息区按品名、规格、市场、当前价格等题头逐行呈现中药材的价格信息,且分多页显示,在页面的底部给出了分页链接信息.根据上述分析可知,在爬虫的设计过程中,需要解决如下问题:①获取各个分页的URL链接地址;②提取各分页信息记录条的目标信息.
如前面所述爬虫要想从网页中提取信息,首先需将网页源码下载到本地,网页源码的下载通过Http请求实现,Requests模块是Python语言开发的Http库,其功能强大,实现简单[7-9].对于采用GET方式打开的网页,可采用语句requests.get(“URL地址参数”).text方法模拟请求,得到网页源后将其存储为文本格式.同时BeautifulSoup是基于Python语言开发的一个用于解析html对象的第三方库.对于结构化网页信息的提取,与正则表达式相比更具优势.其提供的find()与find_all()方法使信息定位、过滤、提取的实现更加简单[10-13].同时考虑到中药材天地网结构规范,且要提取的目标信息都是文本字段,最终决定采用Requests模块进行模拟Http请求下载目标网页源码,采用BeautifulSoup模块过滤、解析、提取目标信息.
借助浏览器的审查元素工具,分析各页中的源码架构,如图2所示,每页中的每条信息记录条处于同一
def get_page_values(self, now_url): # 其中now_url参数为网页的URL地址
now_html = requests.get(now_url).text # 下载网页源码,并以文本方式储存
now_Soup = BeautifulSoup(now_html, 'lxml')# 以网页文档解析源码
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')
#提取“规格”
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地址加一个“-”与分页号构成,如:首页的URL地址为:http://www.zyctd.com/jiage/1-0-0.html,第201页的URL地址为:http://www.zyctd.com/jiage/1-0-0-201.html.如图1(b)所示,首页底部的分页链接按钮给出了分页面的总数,如当前一共有201个页面.通过审查元素工具,可知分页总数位于
def get_all_page_values(self):#获取所有分页面中记录条信息
# 下载首页源码
html = requests.get('http://www.zyctd.com/jiage/1-0-0.html').text
# 以网页解析文档
Soup = BeautifulSoup(html, 'lxml')
# 定位到最后一页的页码值对应的标签区
all_li = Soup.find('div', class_='pageBreak').find_all('a')
# 提取最后一页的页码值,#获取最大页码值,即页面总数
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:
# 字串拼接构造分页URL地址
temp_url = 'http://www.zyctd.com/jiage/1-0-0-' + str(i) + '.html'
# 调用页面目标信息提取函数,获取当前分页中所有记录条的品名、规格、市场、价格等目标信息
now_page = self.get_values(temp_url)
all_page_value.extend(now_page)
result_df = pd.DataFrame(all_page_value)
returnresult_df
鉴于文本文件的通用性较好,且便于后期的跨平台分析,文中将提取到的目标数据采用文本文件进行存储.为了便于后期按分隔符导入表格文件,在写入文本文件时,一条记录条的品名、规格、市场及价格之间采用逗号分隔,各条记录条间采用回车进行分隔.同时考虑到中药材天地网的价格信息是按天发布,为了避免信息的重复,在每天爬取数据时,以当前系统日期为文件名创建文件,当前系统日期的获取通过Python的datetime模块中的datetime.now().date().isoformat()实现.详细实现代码如下:
def write_txt(self,name,guige,shichang,price):
#以当前系统日期为文件名创建本次存储文件
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)#规格
f.write(',')#逗号分隔
f.write(shichang)#市场
f.write(',')#逗号分隔
f.write(price)#价格
f.write(' ')#不同记录条间“回车”分隔
中药材天地网按天更新各药材价格信息,因此需每天运行爬虫,对更新的价格进行采集,如果爬虫每天的启动工作由用户人工完成,事必增加了用户的工作事项,多有不便.倘若有一天用户忘记了此项任务,将会导致当天信息缺失.考虑到当前用户电脑以windows系统为主流,同时windows系统自带任务计划程序安排功能,因此采用windows自带的任务计划来实现爬虫的定时启动.以Win7系统为例,具体的部署方法是:①创建bat批处理文件,在文件中书写如:“python 爬虫文件名.py”格式的命令;②依次进入系统“控制面板”/“管理工具”/“任务计划程序”/“创建任务”栏目,创建一个每天指定时间启动①中批处理文件的新任务;③在“任务计划程序”任务安排列表中选中②中创建的新任务,并点选“运行”按钮启动.
将所设计的爬虫按照上述方法,部署到CPU型号为Intel(R) Core(TM) i3-4160 3.6GHz,内存为4GB,操作系统为Win7-64位的平台上,对目标网页进行信息爬取,得到如图3所示的目标信息,此次测试运行共计收集201页20051条记录,用时约1026毫秒.经人工与网页实际数据对比,信息记录条数一致,无重复,无缺项.进一步证实,所设计的爬虫运行效率较高,准确无误,可用于中药材价格数据的收集.
图3 目标信息片断
本文以中药材价格预测的研究为背景,为了收集大量的中药材价格数据,瞄准互联网上的数据资源,以中药材天地网为目标网站,在深入分析其网页布局结构及信息发布规则的基础上,基于Python语言的Requests、Beautifulsoup等模块,设计了一款中药材价格信息爬虫,同时就爬虫在windows系统如何实现定时自动运行的部署进行了介绍.经实验测试,所设计的爬虫运行可靠、效率较高,所得数据与网页公布一致无误,为从互联网收集中药材相关信息提供了参考方法.虽然所设计的爬虫能够准确无误的获取中药材价格信息,但是为了拓宽其使用人群范围,需在后续的研究中解决其跨平台部署不便的问题,让其能脱离Python环境运行.