﻿#!/usr/bin/env python
# coding: utf-8

from dateutil.relativedelta import relativedelta
import datetime
import time
import os
import csv

from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoSuchFrameException
from selenium.common.exceptions import NoSuchWindowException
from selenium.common.exceptions import NoSuchAttributeException
from selenium.common.exceptions import NoAlertPresentException
from selenium.common.exceptions import ElementNotVisibleException
from selenium.common.exceptions import ElementNotSelectableException
from selenium.common.exceptions import TimeoutException

from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from time import sleep
from random import randint

USER_AGENTS = [
 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
 "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
 "Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
 "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
 "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
 "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
 "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
 "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
 "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
 "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
 "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
 "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5",
 "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6",
 "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
 "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20",
 "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",
]
random_agent = USER_AGENTS[randint(0, len(USER_AGENTS)-1)]

MUFG_TOP_URL = 'https://entry11.bk.mufg.jp/ibg/dfw/APLIN/loginib/login?_TRANID=AA000_001'
#MUFG_TOP_URL = 'https://directg.s.bk.mufg.jp/APL/LGP_P_01/PU/LG_0001/LG_0001_PC01'

INFORMATION_TITLE = 'お知らせ - 三菱東京ＵＦＪ銀行'
# MUFG_ID&Pass
ACCOUNT_ID = os.environ['ACCOUNT_ID']
IB_PASSWORD = os.environ['IB_PASSWORD']
RUN_HOST = os.environ['RUNHOST']

caps = DesiredCapabilities.PHANTOMJS
caps["phantomjs.page.settings.userAgent"] = random_agent

##driver = webdriver.PhantomJS( executable_path='./phantomjs' , desired_capabilities=caps)

Options = webdriver.FirefoxOptions()
# ヘッドレス化
Options.headless = True
# 必須
Options.add_argument('--no-sandbox')
Options.add_argument('--disable-gpu')
# エラーの許容
Options.add_argument('--ignore-certificate-errors')
Options.add_argument('--allow-running-insecure-content')
#####Options.add_argument('--disable-web-security')
# headless では不要そうな機能を除外
#####Options.add_argument('--disable-desktop-notifications')
#####Options.add_argument("--disable-extensions")
# UA設定 （なくてもいい）
Options.add_argument('--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0')
# 言語 (なくてもいいが言語によって表示されるページが変わる可能性があるので念のため)
Options.add_argument('--lang=ja')
# 画像を読み込まないで軽くする
Options.add_argument('--blink-settings=imagesEnabled=false')

Options.binary_location = '/usr/bin/firefox-esr' 

log_path = os.path.join(os.path.dirname(__file__), 'geckodriver.log')
driver = webdriver.Firefox(  executable_path='geckodriver', options=Options, service_log_path=log_path)
driver.implicitly_wait(3)

def login(account_id: str, ib_password: str):
	global str_error
	str_error = None
	for x in range(0, 5):  # try 4 times
		try:
			error_num = 1000
			## r = 1/0
			##print("====10===")
			driver.get(MUFG_TOP_URL)
			sleep(3)
			##print("====11===")
			error_num = 2000
			#driver.find_element_by_id('tx-contract-number').send_keys(account_id)
			branch_input = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, "tx-branch-number")))
			branch_input.send_keys('')
			error_num = 3000
			#driver.find_element_by_id('tx-contract-number').send_keys(account_id)
			account_input = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, "tx-account-number")))
			account_input.send_keys('')
			error_num = 4000
			#driver.find_element_by_id('tx-contract-number').send_keys(account_id)
			number_input = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, "tx-contract-number")))
			number_input.send_keys(account_id)
			##print("====12===")
			error_num = 5000
			#driver.find_element_by_id('tx-ib-password').send_keys(ib_password)
			# 等待密码输入框可见并可交互
			password_input = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, "tx-ib-password")))
			password_input.send_keys(ib_password)
			##print("====13===")
			#driver.find_element_by_xpath('//img[@alt="ログイン"]').click()
			error_num = 6000
			## driver.find_element_by_xpath('//button[@class="gonext"]').click()
			element=WebDriverWait(driver,30).until(ec.element_to_be_clickable((By.XPATH,'//button[@class="gonext"]')))
			element.location_once_scrolled_into_view
			element.click()
			##print("====14===")
			error_num = 0
		except NoSuchElementException as ex:
			str_error  = ex
			error_num += 1
		except NoSuchFrameException as ex:
			str_error  = ex
			error_num += 2
		except NoSuchWindowException as ex:
			str_error  = ex
			error_num += 3
		except NoSuchAttributeException as ex:
			str_error  = ex
			error_num += 4
		except NoAlertPresentException as ex:
			str_error  = ex
			error_num += 5
		except ElementNotVisibleException as ex:
			str_error  = ex
			error_num += 6
		except ElementNotSelectableException as ex:
			str_error  = ex
			error_num += 7
		except TimeoutException as ex:
			str_error  = ex
			error_num += 8
		except Exception as ex:
			str_error  = ex
			error_num += 99
		if error_num>0:
			if x == 0:
				dataline = '------------------[{}][{}]----------------'.format(RUN_HOST,datetime.datetime.now().strftime('%Y-%m-%d  %H:%M:%S'))
				print(dataline)
			print("{}{}".format("login error_num=", error_num))
			##driver.navigate().refresh();
			sleep(2)  # wait for 2 seconds before trying to fetch the data again
			if x == 4:
				dataline = '------------------[{}][{}]----------------'.format(RUN_HOST,datetime.datetime.now().strftime('%Y-%m-%d  %H:%M:%S'))
				
				error_path ='{}/{}'.format( os.environ['BKLIST_PATH'], 'error.txt')
				fp_error= open(error_path, "w", encoding="utf-8")
				fp_error.write("{}:{};{}{}".format("login error_num", error_num,str_error,'\n'))
				###fp_error.write(str_error.message + ':'  + str_error.args + '\n')
				###fp_error.write( err.args + '\n')
				fp_error.write(dataline + '\n')
				fp_error.flush()
				fp_error.close()
				status_path ='{}/{}'.format( os.environ['BKLIST_PATH'], 'status.txt')
				status_book = open(status_path, "w", encoding="utf-8")
				status_book.write(dataline + '\n')
				status_book.write("ng" + '\n' )
				status_book.flush()
				status_book.close()
				exit()
		else:
			break


def logout():
	# <li class="logout"><a href="#" onClick="JavaScript:logoutFromAD001(); return false;">ログアウト</a></li>
	#driver.find_element_by_link_text('ログアウト').click()
	button = driver.find_element_by_xpath("//button[contains(text(), 'ログアウト')]")
	button.click()  # 执行按钮点击操作


def read_information():
	"""
	お知らせがある場合は既読にします
	:return:
	"""
	while True:
		if not driver.title == INFORMATION_TITLE:
			return
		information = driver.find_element_by_xpath(
			'//table[@class="data"]/tbody/tr')
		information.find_element_by_name('hyouzi').click()
		driver.find_element_by_xpath('//img[@alt="トップページへ"]').click()


def select_selectbox_value(element_name: str, value: str):
	"""
	セレクトボックスの値を選択します
	:param element_name:
	:param value:
	:return:
	"""
	selectbox = Select(driver.find_element_by_name(element_name))
	#print(str(value))
	selectbox.select_by_visible_text(str(value))


def select_time_period(_from: datetime, _to: datetime):
	"""
	指定した表示期間を選択します
	:param _from:
	:param _to:
	:return:
	"""

	wait = WebDriverWait(driver, 30)
	# wait.until(ec.presence_of_element_located((By.ID, 'sl-period')))
	# 等待 select 出现
	period_element = wait.until(
	    EC.presence_of_element_located((By.ID, "sl-period"))
	)
	# print("sl-period 找到了")
	
	# 选择 期間指定
	period = Select(period_element)
	period.select_by_value("5")
	
	# 检查实际选中的 value
	selected_value = period.first_selected_option.get_attribute("value")
	selected_text = period.first_selected_option.text

	# print("期間 value =", repr(selected_value))
	# print("期間 text  =", repr(selected_text))
	
	#driver.find_element_by_id('appoint').click()
	# driver.find_element_by_name('SHOUKAIKIKAN_RADIO').click()
	
	start_str = _from.strftime("%Y-%m-%d")
	end_str = _to.strftime("%Y-%m-%d")
	print("设定开始日期 =", start_str)
	print("设定结束日期 =", end_str)

	# 2. 開始日
	start_element = wait.until(
	    EC.presence_of_element_located((By.ID, "tx-start-date"))
	)
	start_element.clear()
	start_element.send_keys(start_str)

	# 3. 終了日
	end_element = wait.until(
	    EC.presence_of_element_located((By.ID, "tx-end-date"))
	)
	end_element.clear()
	end_element.send_keys(end_str)
	# 检查实际 value
	#  print("开始日期实际 value =", repr(
	#      start_element.get_attribute("value")
	#  ))

	#  print("结束日期实际 value =", repr(
	#      end_element.get_attribute("value")
	#  ))
	
	driver.find_element(By.ID, "tx-end-date").send_keys(end_str)
	
	# 4. 条件を変更
	button = wait.until(
	    EC.element_to_be_clickable((By.ID, "bt-inquiry"))
	)

	#  print("条件を変更按钮找到了")
	#  print("button text =", repr(button.text))
	#  print("button enabled =", button.is_enabled())
	#  print("button displayed =", button.is_displayed())

	button.click()

	#  print("条件を変更已经执行 click()")

	# 等待 5 秒
	time.sleep(5)

	# select_selectbox_value('SHOUKAIKIKAN_FROM_Y', str(_from.year))
	# select_selectbox_value('SHOUKAIKIKAN_FROM_M', str(_from.month))
	# select_selectbox_value('SHOUKAIKIKAN_FROM_D', str(_from.day))
	# select_selectbox_value('SHOUKAIKIKAN_TO_Y', str(_to.year))
	# select_selectbox_value('SHOUKAIKIKAN_TO_M', str(_to.month))
	# select_selectbox_value('SHOUKAIKIKAN_TO_D', str(_to.day))

def show_details(_fp_list, _fp_book, _last: str,  _dataline: str):
	#banking_list = driver.find_elements_by_xpath( '//table[@class="data memo yen_nyushutsukin_003"]/tbody/tr')
	banking_list = driver.find_elements_by_xpath( '//table[@class="add-tbl-01"]/tbody/tr')

	flg = 0
	lastflg = 0
	year=""
	for banking in banking_list:
		detail = banking.find_elements_by_tag_name('td')
		str_date=detail[0].text
		if str_date.endswith("年"):
			year = str_date[:4]
			#print('year:'+ year)
			#YYYY = datetime.datetime.strptime(str_date.replace('\n', ''), '%Y年')
			#year = str_date[:4]
		elif str_date.endswith("振替"):
			pass
		else:
			#payment = in_or_out_payment(detail[1].text, detail[2].text)
			# print('str_date:'+ str_date)
			_date= year + '-' + str_date.replace('\n', '').replace('/', '-')
			date=datetime.datetime.strptime(_date, '%Y-%m-%d')
			content = detail[3].text
			conlist = content.split("　")
			cont1=conlist[0]
			del conlist[0]
			cont2=''.join(conlist)
			total = to_number(detail[4].text)
			pay = to_number(detail[1].text)
			income = to_number(detail[2].text)
			line = '{}\t{}\t{}\t{}\t{}\t{}'.format(date.strftime('%Y-%m-%d'),cont1, cont2, pay, income , total )
			#line = '{}\t{}\t{}\t{}\t{}\t{}'.format(date,cont1, cont2, pay, income , total )
			_fp_list.write(line + '\n')
			print(line)
			
			if flg == 1:
				if lastflg == 0:
					#print(dataline)
					_fp_book.write(_dataline + '\n')
				_fp_book.write(line + '\n')
				lastflg = flg
			else:
				lastflg = flg
				if _last == '':
					flg=1
				if _last == line + '\n':
					flg=1
	
	try:
		driver.find_element_by_xpath('//a/img[@alt="新しい明細"]').click()
	except NoSuchElementException:
		return
	else:
		# 例外がない(=次のページがある)から次のページへ
		show_details()


def to_number(yen: str) -> int:
	"""
	xxx,xxx,xxx円からカンマと「円」を削除します
	:param yen:
	:return: int:
	"""
	if yen == '':
		return ''
	return int(yen.replace(',', '').replace('円', ''))


def in_or_out_payment(_out: str, _in: str) -> int:
	"""
	入出金の判定を行います
	:param _out:
	:param _in:
	:return:
	"""
	if not _out == '':
		# 出金
		return to_number(_out) * -1
	# 入金
	return to_number(_in)


def main(_from: datetime, _to: datetime):
	global str_error
	try:
		#account_id = os.environ['ACCOUNT_ID']
		#ib_password = os.environ['IB_PASSWORD']
		account_id = ACCOUNT_ID
		ib_password = IB_PASSWORD

		str_error = None
		login(account_id, ib_password)
		
		for x in range(0, 5):  # try 4 times
			try:
				
				error_num = 100
				##driver.find_element_by_link_text('入出金明細').click()
				##driver.find_element_by_xpath('//div[@class="detail ng-tns-c16-0"]').click()
				#  element=WebDriverWait(driver,30).until(ec.element_to_be_clickable((By.XPATH,'//div[@class="detail ng-tns-c16-0"]')))
				#  element=WebDriverWait(driver,30).until(ec.element_to_be_clickable((By.XPATH,'//div[@class="detail ng-tns-c1004983345-0"]')))
				#  element=WebDriverWait(driver,30).until(ec.element_to_be_clickable((By.XPATH,'//div[@class="detail ng-tns-c3483419345-0"]')))
				#  element=WebDriverWait(driver,30).until(ec.element_to_be_clickable((By.XPATH,'//div[@class="detail ng-tns-c4261188998-0"]')))
				#  element=WebDriverWait(driver,30).until(ec.element_to_be_clickable((By.XPATH,'//div[@class="detail ng-tns-c2084569698-0"]')))
				element=WebDriverWait(driver,30).until(ec.element_to_be_clickable((By.XPATH,'//img[@src="https://directg.s.bk.mufg.jp/refresh/UX/assets/images/icon_detail.svg"]')))
				element.location_once_scrolled_into_view
				## element.click()
				error_num = 200
				element2 = driver.find_element_by_xpath("//div[@class='navigation-nav nav-right']")
				driver.execute_script("arguments[0].style.visibility='hidden'", element2)
				try:
					error_num = 300
					element3 = driver.find_element_by_xpath("//div[@class='navigation']")
					driver.execute_script("arguments[0].style.visibility='hidden'", element3)
				except NoSuchElementException:
					str_error = None
				try:
					error_num = 400
					element4 = driver.find_element_by_xpath("//nav[@class='navigation with-logo container-wide']")
					driver.execute_script("arguments[0].style.visibility='hidden'", element4)
				except NoSuchElementException:
					str_error = None
				try:
					error_num = 500
					element5 = driver.find_element_by_xpath("//header")
					driver.execute_script("arguments[0].style.visibility='hidden'", element5)
				except NoSuchElementException:
					str_error = None
				# 定位到被遮挡的元素
				# 定位到被遮挡的元素
				error_num = 600
				element = driver.find_element_by_class_name("detail")
				element.click()


				# 模拟鼠标移动到元素上并点击
				#actions = ActionChains(driver)
				#actions.move_to_element(element).click().perform()
				str_error = None
				error_num = 0
			except NoSuchElementException as ex:
				str_error  = ex
				error_num += 1
			except NoSuchFrameException as ex:
				str_error  = ex
				error_num += 2
			except NoSuchWindowException as ex:
				str_error  = ex
				error_num += 3
			except NoSuchAttributeException as ex:
				str_error  = ex
				error_num += 4
			except NoAlertPresentException as ex:
				str_error  = ex
				error_num += 5
			except ElementNotVisibleException as ex:
				str_error  = ex
				error_num += 6
			except ElementNotSelectableException as ex:
				str_error  = ex
				error_num += 7
			except TimeoutException as ex:
				str_error  = ex
				error_num += 8
			except Exception as ex:
				str_error  = ex
				error_num += 99
				pass
			if error_num>0:
				print("{}{}".format("main error_num=", error_num))
				##driver.navigate().refresh();
				if x == 4:
					dataline = '------------------[{}][{}]----------------'.format(RUN_HOST,datetime.datetime.now().strftime('%Y-%m-%d  %H:%M:%S'))
					print(dataline)
					error_path ='{}/{}'.format( os.environ['BKLIST_PATH'], 'error.txt')
					fp_error= open(error_path, "w", encoding="utf-8")
					fp_error.write(dataline + '\n')
					fp_error.write("{}:{};{}{}".format("main error_num", error_num,str_error,'\n'))
					fp_error.flush()
					fp_error.close()
					status_path ='{}/{}'.format( os.environ['BKLIST_PATH'], 'status.txt')
					status_book = open(status_path, "w", encoding="utf-8")
					status_book.write(dataline + '\n')
					status_book.write("ng" + '\n' )
					status_book.flush()
					status_book.close()
					exit()
			else:
				break


		# お知らせ画面がある場合は既読にする
		read_information()
		
		## WebDriverWait(driver,30).until(ec.element_to_be_clickable((By.XPATH,'//div[@class="w40"]/p/fw-money/span[@class="plusClass"]')))	
		## WebDriverWait(driver,30).until(ec.element_to_be_clickable((By.XPATH,'//div[@class="main__content"]/div[@class="bg-gray"]/div[@class="add-lyt-01"]/div[@class="w40"]/p/fw-money/span[@class="plusClass"]')))	
		## WebDriverWait(driver,30).until(ec.element_to_be_clickable((By.XPATH,'//div[@class="main__content"]/div[@class="bg-gray"]')))	
		WebDriverWait(driver,30).until(ec.element_to_be_clickable((By.XPATH,'//div[@class="main__content"]/div[@class="bg-gray meigi-form flex-row-center"]')))	

		# 残高を取得
		#total = driver.find_element_by_id('setAmountDisplay')
		#total = driver.find_element_by_xpath('//td[@class="number"]/strong')
		#total = driver.find_element_by_xpath('//div[@class="w40"]/p/fw-money/span[@class="plusClass"]')
		##total = driver.find_element_by_xpath('//div[@class="main__content"]/div[@class="bg-gray"]/div[@class="add-lyt-01"]/div[@class="w40"]/p/fw-money/span[@class="plusClass"]')
		##total = driver.find_element_by_xpath('//div[@class="main__content"]/div[@class="bg-gray"]/div[@class="add-lyt-01"]/div[@class="w40"]/p/fw-money')
		total = driver.find_element_by_xpath('//div[@class="main__content"]/div[@class="bg-gray meigi-form flex-row-center"]/div[@class="flex-row-center"]/p/strong/fw-money')
		# total = driver.find_element_by_xpath('//fw-money/span[@class="plusClass"]')
		print(total.text )
		total_amount = to_number(total.text)
		##total = driver.find_element_by_id('account')
		##total_amount = to_number(total.text)

		print('{:,d}円'.format(total_amount))

		##driver.find_element_by_xpath('//img[@alt="入出金明細をみる"]').click()

		# 期間を指定する
		# select_time_period(_from, _to)

		# driver.find_element_by_xpath('//img[@alt="照会"]').click()
		flist_path ='{}/{}'.format( os.environ['BKLIST_PATH'], os.environ['BKLIST_NAME'])
		fbook_path ='{}/{}'.format( os.environ['BKLIST_PATH'], os.environ['BKBOOK_NAME'])
		
		targetLine = ""
		if os.path.isfile(fbook_path):
			fcheck = open(fbook_path, "r", encoding="utf-8")
			while 1:
				mLine = fcheck.readline();
				if not mLine:
					break;
				targetLine = mLine;
			fcheck.close()
		fp_list = open(flist_path, "a", encoding="utf-8")
		fp_book = open(fbook_path, "a", encoding="utf-8")
		
		dataline = '------------------[{}][{}]----------------'.format(RUN_HOST,datetime.datetime.now().strftime('%Y-%m-%d  %H:%M:%S'))
		print(dataline)
		fp_list.write(dataline + '\n' )
		show_details(fp_list, fp_book, targetLine, dataline)
		fp_book.flush()
		fp_book.close()
		
		fp_list.flush()
		fp_list.close()
		##driver.find_element_by_xpath('//img[@alt="明細をダウンロード"]').click()
		##
		##select_time_period(_from, _to)
		##driver.find_element_by_xpath('//img[@alt="ダウンロード（CSV形式）"]').click

		logout()
		status_path ='{}/{}'.format( os.environ['BKLIST_PATH'], 'status.txt')
		status_book = open(status_path, "w", encoding="utf-8")
		status_book.write(dataline + '\n')
		status_book.write("ok" + '\n' )
		status_book.flush()
		status_book.close()
	finally:
		driver.close()

if __name__ == '__main__':
	td_1m =relativedelta(months=5) 
	end = datetime.datetime.now()
	tmp_start = end - td_1m
	start = datetime.datetime(year=tmp_start.year, month=tmp_start.month, day=15)
	main(start, end)
