使⽤浏览器模拟器获取动态⽹站数据
虽然python中的urllib模块中有相应的函数来处理这类动态页⾯,但过于⿇烦,这⾥我们选⽤⼀个简便的⽅法,使⽤浏览器模拟器。
在⽹上下载⽆界⾯浏览器PhantomJS,利⽤pip下载模块selenium(这⾥推荐版本2.53.6,⽽不是最新版本,最新版本的selenium不⽀持PhantomJS),建⽴main.py,编写涉及和使⽤到的类与⽅法,代码如下:
1from selenium import webdriver
2from selenium.webdriver.support.select import Select
3from myLog import MyLog
4import time
python在线模拟器5import xlwt
6
7class Item(object):
8    shengfen = None        #省份
9    xiangmubianhao = None  #项⽬编号
10    xiangmumingcheng = None #项⽬名称
11    xiangmuneihan = None    #项⽬内涵
12    chuwaineirong = None    #除外内容
13    danwei = None          #单位
14    jiage = None            #价格
15    shuoming = None        #说明
16    wenhao = None          #⽂号
17    zhixingriqi = None      #执⾏⽇期
18
19class Get_medicalprice(object):
20def__init__(self):
21        self.hospitalPriceurl = 'jgw/front/cn/hospitalPrice'
22        self.log = MyLog()
23        self.filename = u'医疗服务价格.xls'.encode('GBK')
24        self.namelist = ame('')
25        self.hospitallist = hospitalprice(self.hospitalPriceurl,self.namelist)
26        self.savefiletoxls(self.filename,self.hospitallist)
27
28def getname(self,filename):
29        namelist = []
30        with open(filename,'r') as fp:
31            s = fp.read()
32for name in s.split():
33                namelist.append(name)
34        self.log.info('open namelist success , the length of list is %d' % len(namelist))
35return namelist
36
37def gethospitalprice(self,url,namelist):
37def gethospitalprice(self,url,namelist):
38        list_hospitalprice = []
39return list_hospitalprice
40
41def savefiletoxls(self,filename,hospitallist):
42        self.log.info('save data to excel')
43        book = xlwt.Workbook(encoding = 'utf8',style_compression=0)
44        sheet = book.add_sheet(u'医疗服务项⽬收费')
45        sheet.write(0,0,u'省份'.encode('utf8'))
46        sheet.write(0,1,u'项⽬编号'.encode('utf8'))
47        sheet.write(0,2,u'项⽬名称'.encode('utf8'))
48        sheet.write(0,3,u'项⽬内涵'.encode('utf8'))
49        sheet.write(0,4,u'除外内容'.encode('utf8'))
50        sheet.write(0,5,u'单位'.encode('utf8'))
51        sheet.write(0,6,u'价格'.encode('utf8'))
52        sheet.write(0,7,u'说明'.encode('utf8'))
53        sheet.write(0,8,u'⽂号'.encode('utf8'))
54        sheet.write(0,9,u'执⾏⽇期'.encode('utf8'))
55for i in range(1,len(hospitallist)+1):
56            item = hospitallist[i-1]
57            sheet.write(i,0,item.shengfen)
58            sheet.write(i,1,item.xiangmubianhao)
59            sheet.write(i,2,item.xiangmumingcheng)
60            sheet.write(i,3,item.xiangmuneihan)
61            sheet.write(i,4,item.chuwaineirong)
62            sheet.write(i,5,item.danwei)
63            sheet.write(i,6,item.jiage)
64            sheet.write(i,7,item.shuoming)
65            sheet.write(i,8,item.wenhao)
66            sheet.write(i,9,item.zhixingriqi)
67        book.save(filename)
68        self.log.info('save excel success')
69
70
71if__name__ == '__main__':
72    Get_medicalprice()
其中,类Item定义了我们需要从⽹页获取到的所有信息;类Get_medicalprice为爬⾍主程序;⽅法__init__定义了整个爬⾍的⼯作流程;⽅法getname从“”中获取需要查的医疗服务项⽬名称,返回名称列表;⽅法gethospitalprice 为爬⾍的关键,负责根据getname返回的名称列表在页⾯中查对应的信息并保存;⽅法savefiletoxls负责将gethospitalprice获取到的所有信息保存到电⼦表中。
我们现在开始来补充⽅法gethospitalprice中的代码。
使⽤selenium模拟调⽤浏览器PhantomJS,⾸先⽤“#”注释掉__init__中
的“self.savefiletoxls(self.filename,self.hospitallist)”,出于测试⽬的,这⾥只让浏览器截图查看模拟效果⽽不进⼀步抓取数据。在gethospitalprice中增加代码如下:
1def gethospitalprice(self,url,namelist):
2    browser = webdriver.PhantomJS()
3    list_hospitalprice = []
4    (url)
5#browser.implicitly_wait(10)
6for name in namelist:
7        textelement = browser.find_element_by_id('projectname')
8        textelement.clear()                #清除text中已输⼊的项⽬
9try:
10            textelement.send_keys(name.decode('GBK'))  #text中填⼊项⽬名称
11except:
12            ('get data %s error ' % name)
13continue
14else:
15            self.log.info('get data %s \n' % name.decode('GBK'))
16        selectelement = browser.find_element_by_id('provName')
17        Select(selectelement).select_by_value(u'河南省')  #使⽤select控件选择河南省
18        submitelement = browser.find_element_by_class_name('l-btn-left')
19        submitelement.click() #点击查询按钮
20        time.sleep(10)
21        _screenshot_as_file('%s.png' % name) #进⾏查询后让浏览器截图,以查看程序是否运⾏正常
在这⾥,模块selenium本⾝⾃带的implicitly_wait效果⽐time⾥的sleep要好,所以平时尽量优先使⽤implicitly_wait,⽽这⾥依旧使⽤time.sleep是为防⽌被服务器拦截⽽强制让程序降速。根据页⾯源代码,到相应控件的id,如这⾥
的“projectname”、“provName”,利⽤find_element_by_id来定位。其中⽤于选择省份的控件是个select,需要⽤到selenium.webdriver.support.select中的Select。通过send_keys来向“provName”的⽂本框控件中发送项⽬名称时,特别需要注意的是汉字编码,因为是在windows下创建的,编码⽤的是"GBK'',所以这⾥需要先⽤
decode("GBK")把项⽬名称进⾏反编码。
但有个问题是“查”按钮不好定位,没有明显的id和class。右键点击“查”按钮,选择“审查元素”,这⾥可以看到该控件的class为“l-btn-left”(虽然那个“清空”按钮的class也是“l-btn-left”,但并没太⼤的影响,“查”⽐“清空”位置靠前,find_element_by_class_name返回的是检索到的第⼀个符合条件的控件),利⽤
find_element_by_class_name('l-btn-left')来定位。
在最后增加⼀条语句 _screenshot_as_file('%s.png' % name) 来让浏览器⾃动截图并保存成“项⽬名
称.png”的图⽚,以便⽅便查看确定程序是否在正常运⾏。
点击run运⾏程序,在⽬录下随便打开⼀张png图⽚,如下图:
爬⾍程序已经成功选择了设定的“省份”,填⼊了读取到的项⽬名称,并成功点击了“查”按钮,⽽且成功地获取到了我们需要的信息。
好了,下⾯我们就开始和以前⼀样抓取页⾯上的信息。
查看页⾯源代码,可以看到存放数据的位置在标签tbody下,但tbody不唯⼀,⽽上层的标签table,class值
为“xxbTable”,通过搜索后发现是唯⼀的。所以这⾥我们先定位class值为“xxbTable”的标签table,随后再依次定位tbody,tr,td。
1 resultelement = browser.find_element_by_class_name('xxbTable')
2#
3 elements=resultelement.find_elements_by_xpath('./tbody[2]/tr/td')
4 item = Item()
5if len(elements)==0:
6    self.log.info('%s has no data' % name.decode('GBK'))
7else:
8    self.log.info('save data %s to list' % name.decode('GBK'))
9    item.shengfen = elements[1].text
10    item.xiangmubianhao = elements[2].text
11    item.xiangmumingcheng = elements[3].text
12    item.xiangmuneihan = elements[4].text
13    item.chuwaineirong = elements[5].text
14    item.danwei = elements[6].text
15    item.jiage = elements[7].text
16    item.shuoming = elements[8].text
17    item.wenhao = elements[9].text
18    item.zhixingriqi = elements[10].text
19    list_hospitalprice.append(item)
tbody不是唯⼀的,所以在确定需求的是哪⼀部分的时候,可以先⽤定位到tbody处,使⽤for循环打印下此处的⽂本,代码如下:
1 resultelement = browser.find_element_by_class_name('xxbTable')
2#
3 elements=resultelement.find_elements_by_xpath('./tbody')
4for i in elements:
运⾏结果如下:
tbody[0]为空,tbody[1]是列名,tbody[2]才是我们需要的数据。
最终运⾏后,⽣成的结果被⽅法savefiletoxls保存到电⼦表'医疗服务价格.xls'中
以下为“main.py”⽂件的完整代码:
1from selenium import webdriver
2from selenium.webdriver.support.select import Select
3from myLog import MyLog
4import time
5import xlwt
6
7class Item(object):
8    shengfen = None
9    xiangmubianhao = None
10    xiangmumingcheng = None
11    xiangmuneihan = None
12    chuwaineirong = None
13    danwei = None
14    jiage = None
15    shuoming = None
16    wenhao = None
17    zhixingriqi = None
18
19class Get_medicalprice(object):
20def__init__(self):
21        self.hospitalPriceurl = 'jgw/front/cn/hospitalPrice'
22        self.log = MyLog()
23        self.filename = u'医疗服务价格.xls'.encode('GBK')
24        self.namelist = ame('')
25        self.hospitallist = hospitalprice(self.hospitalPriceurl,self.namelist)
26        self.savefiletoxls(self.filename,self.hospitallist)
27
28def getname(self,filename):
29        namelist = []
30        with open(filename,'r') as fp:
31            s = fp.read()
32for name in s.split():
33                namelist.append(name)
34        self.log.info('open namelist success , the length of list is %d' % len(namelist))
35return namelist

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。