Skip to content

Instantly share code, notes, and snippets.

@takuya
Created May 29, 2017 07:20
Show Gist options
  • Save takuya/d37c8903c34a09c22f3c2d0b57f5bd80 to your computer and use it in GitHub Desktop.
Save takuya/d37c8903c34a09c22f3c2d0b57f5bd80 to your computer and use it in GitHub Desktop.
##
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