随之基于Ruby的watir-webdriver自动化测试方案和履行(二)
人生苦短,我因此Python && C#。
http://www.cnblogs.com/Javame/p/4159468.html
继续 … …
1.引言
最近初学Python,写爬虫上瘾。爬了豆瓣练手,又爬了信用社之论坛生成词云分析年度重大词。最近刻着2017还要单纯剩少月了,我的年度重要词是甚?
所以当想到爬取下自己之微信朋友围,来单词频分析,生成属于自己之东主要词词云。
对象围的爬取是充分有难度之,因为微信向没暴露API入口去爬取数据。
唯独她山之石,可以攻玉。
透过各种搜索发现,已经发第三正工具得以好朋友围的导出。其中微信公众号【出书啦】虽提供了这般平等栽服务,支持对象圈导出,并排版生成微信书。
要针对性情侣围的爬取就是基于【出书啊】爬取朋友围后变卦网页后底次次爬取。
微爬虫经验的,只要以到导出朋友围的URL,后面的爬虫就不足吗道了。但针对分享同小结的动感,还是跟豪门不断道来。
=文中干个人隐私内容做了奇特处理=
2.取朋友围数据输入
上面已经介绍过了恋人围的数目爬取是基于【出写啊】微信公众号转的在线微信书数据的第二不成爬取。
具体步骤很简单:
- 关心【出写啊】微信公众号
- 点击【创作书籍】–>【微信书】–>【开始制作】–>【添加随意分配的产生写啊小编为好友即可】
- 稍等片刻,微信书制作完,会接小编发送的音讯提醒,如下图所显示。
点击上图的链接,我们就可以看到比如月重新排版的爱侣围数据,如下图所示:
至此,我们用到对象围的多寡输入——【出书啊】排版生成的微信书链接。
写了爬虫的,后面就可以一直略过了。
当,没写过爬虫也非思着手的,也得管【出写啊】生成的微信书链接留言或私信给自家,我帮忙您收获年度重要词。
编辑脚论首先要学会捕获元素,接下去便使上学页面元素的捕获。
3.环境准备
正文所写爬虫基于python2.7 + scrapy + jieba + wordcloud,使用VS Code IDE。
- Scrapy也Python中于盛行的爬虫框架。
- Jieba凡是比好用的华语分词模块。
- Wordcloud 用于生成词云。
页面元素
4.生变为爬虫项目
先是步:命令执行执行scrapy startproject weixin_moment
,生成Scrapy爬虫项目。
次步:进入创建的weixin_moment目录,执行scrapy genspider 'moment' 'chushu.la'
创朋友围爬虫。
尽以上两步后底文书夹结构如下:
attribute_value
得当前控件的性质
Value = ie.link(:id=>'xxx’).attribute_value("href")
5.剖析数据源
多少的确切抓到手,需要针对数据源进行标准分析。这无异于步我们即将来分析【出写啊】生成的微信书链接的数加载方式。老规矩,F12开发者工具用起来。
打高达图我们可看这是一个get请求,返回的json类型格式数据。
点击Preview页签可以望如下图所出示之数据:
从今图被可以看出返回的目录导航数据包,其数额是随月度开展加载的。当点击导航按钮,其加载对应月份的恋人围数据。
我们点击【2014-3】再观察网络要,发现如下请求:
自打以上数量我们好明细来看,其采用的凡用json传参的post的方式求数据包。点击Preview页签,看到返回的分页JSON数据包。
进展某个节点,我们得窥见朋友围数据藏在data/paras节点下。
由来,我们做到数据的源于解析。
rand_select
擅自挑选select list中之某一样码
ie.select_list(:name=>’’).rand_select
6.蜘蛛来也
好了数据源分析,我们才需要构造数据请求,并进行对的多少解析,即可将到我们想只要的数量!
popupwin
点击弹窗上之‘确定’按钮
ie.popupwin.button(:name=>"确定").click
6.1.伸手导航数据包
修改moment.py定义start_requests
方法:
bookid = '12345678' #请填写【出书啦】返回链接中的数字部分
def start_requests(self):
"""
使用get方式请求导航数据包
"""
url = 'http://chushu.la/api/book/chushula-{0}?isAjax=1'.format(self.bookid) #获取目录的url
yield scrapy.Request(url, callback=self.parse)
重载parse
主意,解析获取到的领航数据包:
def parse(self, response):
"""
处理获取到的导航数据包
"""
json_body = json.loads(response.body) #加载json数据包
catalogs = json_body['book']['catalogs'] #获取json中的目录数据包
sikuli_image
点击图片控件
ie.sikuli_image(:image=>"1.png").click
ie.sikuli_image(:image=>"1.png;2.png").click#可以指定多张图片来识别
6.2. 发送导航请求,抓取朋友围数据
冲上面跟踪至产生之http导航请求,要想抓到手到对象围数据,我们用依据发之呼吁参数构造参数。
从今上图可知,主要包含五只参数:
- type:”year_month”为默认值
- year: 年份
- month: 月份
- index: 第几页
- value : 由岁月拼接的字符串
继承修改我们的parse
术,遍历我们率先步抓到手到的领航数据包构造请求参数:
def parse(self, response):
"""
处理获取到的导航数据包
"""
json_body = json.loads(response.body) #加载json数据包
catalogs = json_body['book']['catalogs'] #获取json中的目录数据包
url = 'http://chushu.la/api/book/wx/chushula-{0}/pages?isAjax=1'.format(self.bookid) #分页数据url
start_page = int(catalogs[0]['month']) #获取起始月份作为index传值
for catalog in catalogs:
year = catalog['year']
month = catalog['month']
formdata = {
"type": 'year_month',
"year": year,
"month": month,
"index": str(start_page),
"value": 'v_{0}{1}'.format(year, month)
}
start_page += 1
以起我们跟至的http请求来拘禁是冲json传参的post请求:
之所以我们如果这样发起呼吁:
yield scrapy.Request(
url,
method='POST',
body=json.dumps(formdata),
headers={'Content-Type': 'application/json'},
callback=self.parse_moment)
无异于我们需要定义一个回调函数用来处理回来的对象围数据。定义parse_moment
方,根据返回的json数据包进行数量提取:
def parse_moment(self, response):
"""
朋友圈数据处理
"""
json_body = json.loads(response.body)
pages = json_body['pages']
pattern = re.compile(u"[\u4e00-\u9fa5]+") #匹配中文
item = WeixinMomentItem()
for page in pages:
if (page['type'] == "weixin_moment_page"):# 仅抓取朋友圈分页数据
paras = page['data']['paras']
if paras:
moment = ''
for content in paras[0]['rows']:
result = re.findall(pattern,
content['data']) #使用正则匹配所有中文朋友圈
moment += ''.join(result)
item['moment'] = moment
item['date'] = page['data']['dateText']#获取时间
yield item
以上用到了概念之WeixinMomentItem
。修改items.py,做如下修改:
class WeixinMomentItem(scrapy.Item):
"""
朋友圈Item
"""
# define the fields for your item here like:
# name = scrapy.Field()
date = scrapy.Field() #日期
moment = scrapy.Field() #朋友圈文字
至此我们好爬虫的修。是未是着急跑一下。
double_click
双击事件
ie .sikuli_image(:image=>"1.png").double_click
6.3. 蜘蛛爬起来
命执行执行scrapy crawl moment -o moment.json
,稍等片刻,热乎的朋友围数据就是变化到moment.json文件中了。
right_click
右击事件
7. 分词处理
jieba中文分词提供了有利于之接口用于分词和词频统计。我们直接调用jieba.cut
措施即可获得分词结果。在此之前我们得加载我们爬取的情侣围数据,即保存至moment.json文件被之多少,并拼接所有朋友圈文本传参至jieba.cut
即可。
新加加一个analyse.py
文件,定义analyse_words
方法:
# -*- coding: utf-8 -*-
"""分析导出的朋友圈数据"""
import json
import os
import jieba
from wordcloud import WordCloud
def analyse_words():
"""
分析抓取到的朋友圈数据,使用jieba进行分词,使用wordcloud生成词云
"""
curr_path = os.path.dirname(__file__) # 当前文件文件夹所在目录
parent_path = os.path.dirname(curr_path) # 上层目录
file_path = os.path.join(parent_path, 'moment.json')
font_path = os.path.join(parent_path, "simhei.ttf")
if not os.path.isfile(file_path):
return
with open(file_path) as moment_file:
data = json.load(moment_file) # 使用json加载文件
moments = [item.get('moment', '') for item in data] # 获取朋友圈文字数组
contents = ' '.join(moments) # 拼接为长文本
cut_texts = ' '.join(jieba.cut(contents)) # 使用结巴分词进行中文分词
exist?
看清用户元素是否在
edit = ie.text_field(:name,"username")
if edit.exist?()
#The highlighted
edit.flash
ie.text_field(:name, "password").set(pwd)
ie.button(:class, "x-login-submit").click
end
end
8. 生成为要词词云
词云需要根据上同一步的分词结果生成词云。代码也酷粗略:
cloud = WordCloud(font_path=font_path)
wordcloud = cloud.generate(cut_texts) #生成词云
wordcloud.to_file('keys.png') #保存图片
image = wordcloud.to_image() # 转化为图片
image.show() # 展示图片
最后以文件末尾调用analyse_words()
,命令执行执行python analyse.py
即可生成首要词!
乃可能嫌弃以上生成的词说于丑,没干,你得行使wordart做出各种酷炫的成效。
Text Fields
require 'watir-webdriver'
b = Watir::Browser.start 'bit.ly/watir-webdriver-demo'
t = b.text_field :id => 'entry_0'
t.exists?
t.set 'your name'
t.value
9. 最后
为【出写啊】未到反爬机制,所以爬虫写下去为尚无啊难度,所以谢兴趣之不妨尽早动手试一尝试。本文由学习分享,无恶意窃取数据的了,也求读者不要用来他途!
Select Lists – Combos
require 'watir-webdriver'
b = Watir::Browser.start 'bit.ly/watir-webdriver-demo'
s = b.select_list :id => 'entry_1'
s.select 'Ruby'
s.selected_options
# 返回选中的选项
puts b.select(:name, 'sex').selected_options
Radios
require 'watir-webdriver'
b = Watir::Browser.start 'bit.ly/watir-webdriver-demo'
r = b.label(:text => 'What is ruby?').parent.radio :value => 'A gem'
r.exists?
r.set
r.set?
Checkboxes
require 'watir-webdriver'
b = Watir::Browser.start 'bit.ly/watir-webdriver-demo'
c = b.label(:text => 'What versions of ruby?').parent.checkbox :value => '1.9.2'
c.exists?
c.set
c.set?
# 选择checkbox
b.checkbox(:name, 'check_me').set true
# 清除选择
b.checkbox(:name, 'check_me').set false
Buttons
require 'watir-webdriver'
b = Watir::Browser.start 'bit.ly/watir-webdriver-demo'
btn = b.button :value, 'Submit'
btn.exists?
btn.click
Links
require 'watir-webdriver'
b = Watir::Browser.start 'bit.ly/watir-webdriver-demo'
l = b.link :text => 'Google Docs'
l.exists?
l.click
Divs & Spans
require 'watir-webdriver'
b = Watir::Browser.start 'bit.ly/watir-webdriver-demo'
d = b.div :class => 'ss-form-desc ss-no-ignore-whitespace'
d.exists?
d.text
s = b.span :class => 'ss-powered-by'
s.exists?
s.text
实例
按钮
? ie.button(:name=>””,:id=>””,:index=>n,:type=>””).click
? ie.button(:name=>””,:id=>””,:index=>n,:type=>””).doclick
输入框
? ie.text_field(:name=>””).set “变量”
? ie.text_field(:name=>””).value
取text_field值未是为此text而是value!
下拉框
? ie.select_list(:name=>””).select “下拉框值”
? ie.select_list(:name=>””).select “#1” #意味着第一项内容
? ie.select_list(:name=>””).rand_select
?
ie.select_list(:name=>””).getSelectedItems|getAllContents->返回Array
单选框
? ie.radio(:id=>””,:name=>””,:index=>n).set(选中当前radio)
?
ie.radio(:id=>””,:name=>””,:index=>n).clear(取消选中当前radio)
ie.div(:class=>”iradio_minimal-blue checked”).radios[1]
复选框
?
ie.check_box(:id=>””,:name=>””,:index=>n).set(true|false)(true表示当选,false表示未选中)
?
ie.check_box(:id=>””,:name=>””,:index=>n).clear(取消选中当前checkbox)
链接
? ie.link(:text=>””).click/doclick
? ie.link(:text=>””).href(返回时link指向的链接)
cell (TD标签,用时一般要先找到上层控件如table、div等)
?
ie.table(:class=>””,:index=>n).cell(:class=>””,:index=>n).text
? ie.table(:index=>n).rows 行 列 .text (行、列从1开始)
?
ie.div(:class=>””,:index=>n).cell(:class=>””,:index=>n).text
span
? ie.table(:id=>””).span(:class=>””).text
弹出框
? ie.popupwin.get_static_text (返回时提醒框的文件)
? ie.popupwin.button(:name=>”确定”).click/doclick
(前一个点击按钮必须用doclick)
? ie.file_dialog(:index=>1/2).set_file(file_path_download,true)
(保存文件的弹奏有窗口)
alert
if b.alert.exists?
puts "ok"
else
puts "no"
end
puts b.alert.text
#b.alert.ok
b.alert.close
b.close
图片
? ie.image(:src=>/word3a_nor.gif/).click/doclick
back
后退
ie.back
forward
前进
ie.forward
refresh
刷新页面
ie.refresh
当Watir-WebDriver中拍卖frame是非常简单的,就跟处理外页面元素一样:
b.frame(:id => "content_ifr").send_keys "hello world"
文件的下载
最为简便易行不过好的拍卖公事下充斥对话框的办法就是了的避免对话框弹出。
可以当代码里告诉浏览器自动的将文件下充斥至指定目录,然后于测试用例中做客该目录进行说明。
Firefox
download_directory = "#{Dir.pwd}/downloads"
download_directory.gsub!("/", "\\") if Selenium::WebDriver::Platform.windows?
profile = Selenium::WebDriver::Firefox::Profile.new
profile['browser.download.folderList'] = 2 # custom location
profile['browser.download.dir'] = download_directory
profile['browser.helperApps.neverAsk.saveToDisk'] = "text/csv,application/pdf"
b = Watir::Browser.new :firefox, :profile => profile
有关Firefox的拥有配置起好经过以地点栏中输入’about:config’进行查。
If you want to know a way to work out the file types (eg.
application/pdf) then you can read the following blog post for an step
by step guide. 如果您想掌握怎样处理特定类型的文件,请看这篇博文。
Chrome
download_directory = "#{Dir.pwd}/downloads"
download_directory.gsub!("/", "\\") if Selenium::WebDriver::Platform.windows?
profile = Selenium::WebDriver::Chrome::Profile.new
profile['download.prompt_for_download'] = false
profile['download.default_directory'] = download_directory
b = Watir::Browser.new :chrome, :profile => profile
浏览器新窗口
当一个初的浏览器窗口打开时,你得运用’use’方法来处理这个新窗口。
browser.window(:title => "annoying popup").use do
browser.button(:id => "close").click
end
JS弹出框
于web应用中,JavaScript对话框是格外广大的。
Watir-WebDriver内建造了拍卖这些对话框的计,并且可以回来对话框中显得的始末。首先,加载是扩展:
View Code
可选方法
若是你用方面的方法时相遇了累,你得活动覆盖JavaScript
functions,这样一来原来该显示的对话框就得于触发时匪显了。
# 使alert方法返回空
browser.execute_script(“window.alert = function() {}”)
# 使prompt返回特定的字符串,用来学用户之输入
browser.execute_script(“window.prompt = function() {return ‘my name’}”)
# 使prompt方法返回null用来拟用户点击了Cancel(取消)按钮
browser.execute_script(“window.prompt = function() {return null}”)
# 使confirm方法返回true用来模拟用户点击了OK(确定)按钮
browser.execute_script(“window.confirm = function() {return true}”)
# 使confirm方法返回false用来套用户点击了Cancel(取消)按钮
browser.execute_script(“window.confirm = function() {return false}”)
页面性能
Watir-WebDriver-Performance gem
提供在访问页面的又进行页面性能度量的效益,其采用的凡W3C页面性能度量指标。这是一个宏观的抓获响应性能指标的解决方案,其以方法充分直观和省略,不过当下单支持Chrome和IE9l浏览器。
require 'watir-webdriver'
require 'watir-webdriver-performance'
b = Watir::Browser.new :chrome
10.times do
b.goto 'http://17test.info'
load_secs = b.performance.summary[:response_time]/1000
puts "Load Time: #{load_secs} seconds."
end
其统计结果如下:
Load Time: 3.701 seconds.
截屏
Watir-WebDriver内建的截图功能非常赞赏吧很好用。
browser.driver.save_screenshot 'screenshot.png'
The great thing about this is it gives you a screen shot of the entire
page, not just above the fold.
截图功能最好巧的地方在于它能够捕获到全体页面,而不是屏幕及显得的那么有。
而你正在下Cucumber,那么您得省略的用下面的代码添加到env.rb文件吃,这样您可以以html的告知遭遇插截图:
After do |scenario|
browser.driver.save_screenshot 'screenshot.png'
embed 'screenshot.png', 'image/png'
end
拟特殊按键
使用.send_keys方法可以套特殊的键盘按键(比如shift),其参数是公所欲效法的按键的记号表示(symbolic)。
b.send_keys :enter
否得这样做:
b.element.send_keys [:control, 'a'], :backspace
若还可修改click方法的行事,使得点击可以匹配按键一起进行:
b.element.click(:shift, :control)
支撑之照键键名列表如下:
View Code
财大气粗文本编辑器
发生一定量种植方式好由此Watir-WebDriver向所见即所得编辑器(应该借助的是方便文本编辑器)中输入文字:
一贯编辑器所当的iFrame,然后使用.send_keys方法(缺点是浏览器必须在前台运行)
在浏览器上实施javascript,通过js脚本去装编辑器的价值
CKEditor
require 'watir-webdriver'
b = Watir::Browser.new :firefox
b.goto 'http://ckeditor.com/demo'
b.execute_script("CKEDITOR.instances['editor1'].setData('hello world');")
b.frame(:title => 'Rich text editor, editor1, press ALT 0 for help.').send_keys 'hello world again'
TinyMCE Editor
require 'watir-webdriver'
b = Watir::Browser.new
b.goto 'http://tinymce.moxiecode.com/tryit/full.php'
b.execute_script("tinyMCE.get('content').execCommand('mceSetContent',false, 'hello world' );")
b.frame(:id => "content_ifr").send_keys 'hello world again'
QA