Created
May 29, 2017 07:20
-
-
Save takuya/d37c8903c34a09c22f3c2d0b57f5bd80 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## | |
require 'selenium' | |
require 'selenium-webdriver' | |
require 'pry' | |
class Selenium::WebDriver::Driver | |
def exists? (query, opts = {} ) | |
opts[:search_method] ||= :xpath | |
opts[:wait_timeout] ||= 3 | |
ret = self.send(opts[:search_method], query) | |
return false unless ret | |
return true if ret | |
end | |
def xpath( query) | |
ret = self.find_elements( xpath: query ) | |
return ret[0] if ret.size==1 | |
return nil if ret.size==0 | |
return ret | |
end | |
def css( query) | |
ret = self.find_elements( css: query ) | |
return ret[0] if ret.size==1 | |
return nil if ret.size==0 | |
return ret | |
end | |
def goto ( url ) | |
self.navigate.to url | |
self.wait_to_js("return document.readyState", 'complete') | |
end | |
def select( query, value , opts={} ) | |
opts[:search_method] ||= :xpath | |
opts[:wait_timeout] ||= 3 | |
opts[:type] ||= 'text' | |
self.click( query, **opts) | |
select_element = self.send(opts[:search_method], query) | |
select = Selenium::WebDriver::Support::Select.new(select_element) | |
case opts[:type] | |
when 'text' | |
select.options.find{|e| e.text =~ value }.click | |
when 'index' | |
select.options[value].click | |
end | |
end | |
def click( query, opts={} ) | |
begin | |
opts[:search_method] ||= :xpath | |
opts[:wait_timeout] ||= 10 | |
self.wait_to_displayed(query,**opts) | |
element = self.send(opts[:search_method], query) | |
raise "要素が見つからない" unless element | |
element.click | |
self.wait_to_js("return document.readyState", 'complete') | |
# rescue Selenium::WebDriver::Error::UnknownError => e | |
rescue => e | |
if e.message =~ /not clickable at point/ then | |
# Chrome driver は要素がスクロールで隠れてたらクリックさせてくれない | |
# スクロールして再挑戦 | |
# | |
self.send("scrollToElement", query) | |
retry | |
end | |
end | |
end | |
def submit( query, opts={} ) | |
opts[:search_method] ||= :xpath | |
opts[:wait_timeout] ||= 3 | |
self.wait_to_displayed(query,**opts) | |
self.send(opts[:search_method], query).submit | |
self.wait_to_js("return document.readyState", 'complete') | |
end | |
def enter_text( query, text, opts={} ) | |
opts[:search_method] ||= :xpath | |
opts[:wait_timeout] ||= 3 | |
self.wait_to_displayed(query,**opts) | |
self.send( opts[:search_method],query).send_keys(text) | |
sleep rand(10)/100 | |
end | |
def wait_to_displayed( query , opts={}) | |
opts[:wait_timeout] ||= 10 | |
opts[:search_method] ||= :xpath | |
wait_obj = Selenium::WebDriver::Wait.new(:timeout => opts[:wait_timeout] ) # second | |
wait_obj.until { | |
ret = self.send(opts[:search_method], query) | |
return false unless ret | |
if ret.is_a?(Enumerable) then | |
return true if ret.all{|e|e.displayed? } | |
else | |
return ret.displayed? | |
end | |
} | |
end | |
def wait_to_disappeared( query, opts={} ) | |
opts[:wait_timeout] ||= 3 | |
opts[:search_method] ||= :xpath | |
wait_obj = Selenium::WebDriver::Wait.new(:timeout => opts[:wait_timeout] ) # second | |
wait_obj.until { | |
ret = self.send(opts[:search_method], query) | |
return false unless ret | |
if ret.is_a?(Enumerable) then | |
return self.send(opts[:search_method], query).all{|e|e.displayed? } == false | |
else | |
return self.send(opts[:search_method], query).displayed? == false | |
end | |
} | |
end | |
def wait_to_js( js, value=true , opts={} ) | |
opts[:wait_timeout] ||= 3 | |
wait_obj = Selenium::WebDriver::Wait.new(:timeout => opts[:wait_timeout] ) # second | |
wait_obj.until{ self.execute_script(js) == value } | |
end | |
def exec_js( js, opts={} ) | |
self.execute_script(js) | |
end | |
def scrollToElement( query , opts = {} ) | |
opts[:search_method] ||= :xpath | |
opts[:wait_timeout] ||= 3 | |
element = self.send(opts[:search_method], query) | |
self.scrollTo( element.location.x.to_i , element.location.y.to_i ) | |
end | |
def wait_for_scroll( timeout = 3 ) | |
x=self.execute_script("return window.pageXOffset;") | |
y=self.execute_script("return window.pageYOffset;") | |
wait_obj = Selenium::WebDriver::Wait.new(timeout:10, interval:1 ) | |
wait_obj.until{ | |
x1 = self.execute_script("return window.pageXOffset;") | |
y1 = self.execute_script("return window.pageYOffset;") | |
if x1==x && y1 ==y then | |
return true | |
else | |
x=x1 | |
y=y1 | |
return false | |
end | |
} | |
end | |
def scrollTo( x, y, opts={} ) | |
x = x.to_i | |
y = y.to_i | |
begin | |
opts[:wait_timeout] ||= 3 | |
self.execute_script("window.scrollTo(#{x}, #{y})"); | |
self.wait_for_scroll() | |
rescue => e | |
raise e | |
end | |
end | |
end | |
class Docomo | |
attr_accessor :driver | |
def initialize( driver ) | |
self.driver = driver | |
end | |
def get_pdf | |
pdf_body = nil | |
## ダウンロードディレクトリで作業する。 | |
Dir.chdir(download_dir){|dir| | |
sleep 2 while( Dir.glob("./*part").size > 0 ) # Firefoxダウンロード待ち, | |
sleep 2 while( Dir.glob("./*download").size > 0 ) # chromeダウンロード待ち, | |
sleep 2 # ファイルを消すのを待つ | |
list = Dir.glob("./*") | |
raise "ダウンロード失敗" if list.size == 0 | |
pdf_body = open(list[0]).read | |
Dir.glob("./*").each{|e| File.unlink(e)} | |
} | |
FileUtils.remove_entry_secure @download_dir if Dir.exists? @download_dir | |
return {:file_name => f_name, :body=> pdf_body } | |
end | |
def docomo_home | |
driver. goto "https://www.nttdocomo.co.jp/" | |
end | |
def login | |
## ページロードを待つ | |
## フォーム送信をするには send_keysを使う | |
driver.enter_text('//*[@id="Di_Uid"]', UID) if driver.exists?('//*[@id="Di_Uid"]') | |
driver.enter_text('//*[@id="Di_Pass"]', PASS ) | |
driver.click('//*[@id="persistent"]') if driver.exists?('//*[@id="persistent"]') | |
driver.submit('//*[@id="DiForm"]/input[3]') | |
driver.wait_to_js("return document.readyState", 'complete') | |
end | |
def download_latest_meisei() | |
self.docomo_home | |
## 移動 | |
driver.click('//*[@id="gnavMydocomo"]/a') | |
self.login if driver.current_url =~ /auth/ | |
## | |
driver.wait_to_disappeared( '(//img[@alt="ローディング中です。しばらくお待ちください。"])[1]' ) | |
driver.wait_to_displayed('//a[contains(./text(),"ご利用料金の確認")]', wait_timeout:10 ) | |
sleep 1.0 | |
driver.click('//a[contains(./text(),"ご利用料金の確認")]', wait_timeout:10 ) | |
self.login if driver.current_url =~ /auth/ | |
## | |
driver.click('(//input[contains(@title,"利用内訳")])[2]', wait_timeout:10) | |
## | |
driver.scrollTo(0,0) | |
driver.wait_for_scroll() | |
driver.click('//input[contains(@title,"PDFデータ保存")]') | |
## | |
driver.click('//a[ ./*[@title="上記の注意事項に同意してダウンロード"] ]') | |
end | |
## 代表番号の場合 | |
def daihyo_meisai() | |
self.docomo_home | |
## 移動 | |
driver.click('//*[@id="gnavMydocomo"]/a') | |
self.login if driver.current_url =~ /auth/ | |
## | |
driver.wait_to_disappeared( '(//img[@alt="ローディング中です。しばらくお待ちください。"])[1]' ) | |
driver.wait_to_displayed('//a[contains(./text(),"ご利用料金の確認")]', wait_timeout:10 ) | |
sleep 1.0 | |
driver.click('//a[contains(./text(),"ご利用料金の確認")]', wait_timeout:10 ) | |
self.login if driver.current_url =~ /auth/ | |
## | |
driver.click('(//input[contains(@title,"利用内訳")])[2]', wait_timeout:10) | |
self.login if driver.current_url =~ /auth/ | |
## | |
driver.select("//td[ .//p[contains(./text(),'電話番号を選択')]]//select", /一括/ ) | |
## | |
driver.click('(//input[contains(@title,"利用内訳")])[2]', wait_timeout:10) | |
self.login if driver.current_url =~ /auth/ | |
driver.wait_for_scroll() | |
## | |
driver.click('//input[contains(@title,"PDFデータ保存")]') | |
## | |
driver.click('//a[ ./*[@title="上記の注意事項に同意してダウンロード"] ]') | |
end | |
def daihyo_oshirase() | |
self.docomo_home | |
## 移動 | |
driver.click('//*[@id="gnavMydocomo"]/a') | |
self.login if driver.current_url =~ /auth/ | |
## | |
driver.wait_to_disappeared( '(//img[@alt="ローディング中です。しばらくお待ちください。"])[1]' ) | |
driver.wait_to_displayed('//a[contains(./text(),"ご利用料金の確認")]', wait_timeout:10 ) | |
sleep 1.0 | |
driver.click('//a[contains(./text(),"ご利用料金の確認")]', wait_timeout:10 ) | |
self.login if driver.current_url =~ /auth/ | |
## | |
driver.click('(//input[contains(@title,"お知らせ")])[2]', wait_timeout:10) | |
self.login if driver.current_url =~ /auth/ | |
## | |
driver.select("//td[ .//p[contains(./text(),'電話番号を選択')]]//select", /一括/ ) | |
## | |
driver.click('(//input[contains(@title,"お知らせ")])[2]', wait_timeout:10) | |
self.login if driver.current_url =~ /auth/ | |
driver.wait_for_scroll() | |
## | |
driver.click('//input[contains(@title,"PDFデータ保存")]') | |
## | |
driver.click('//a[ ./*[@title="上記の注意事項に同意してダウンロード"] ]') | |
end | |
end | |
def main | |
UID = "takuya***" | |
PASS = '***********************************' | |
DOWNLOAD_DIR = "/Users/takuya/Desktop/" | |
caps = Selenium::WebDriver::Remote::Capabilities.chrome( | |
"chromeOptions" => { | |
"args" => [ | |
# "--user-data-dir=/Users/takuya/Desktop/sample-profile", | |
# "--headless" | |
], | |
"prefs" => { | |
'download'=>{ | |
'default_directory' => DOWNLOAD_DIR | |
} | |
} | |
}) | |
driver = Selenium::WebDriver.for :chrome , :desired_capabilities => caps | |
docomo = Docomo.new driver | |
## 代表番号が一括で全部の明細をとる | |
docomo.daihyo_meisai | |
## 代表番号のの請求書の表紙とお知らせ | |
docomo.daihyo_oshirase | |
## 1回戦のみの場合 | |
# docomo.download_latest_meisei | |
end | |
if $0 == __FILE__ then | |
main | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment