Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

298 lines
8.9KB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Threading;
  5. using System.IO;
  6. using System.IO.Compression;
  7. using OpenQA.Selenium;
  8. using OpenQA.Selenium.Chrome;
  9. using OpenQA.Selenium.Support.UI;
  10. using CSVDownloader.Code;
  11. using CSVDownloader.Store.CreditCSVData;
  12. using CSVDownloader.Store.QRCSVData;
  13. using ExpectedConditions = OpenQA.Selenium.Support.UI.ExpectedConditions;
  14. namespace CSVDownloader.Web {
  15. abstract class WebController {
  16. protected log4net.ILog logger_ = log4net.LogManager.GetLogger("");
  17. protected ChromeDriver driver_;
  18. protected WebDriverWait wait_;
  19. private const int interval_milisec_ = 1000;
  20. protected CreditAgent agent_;
  21. /// <summary>
  22. /// 駐車場名とSpotIDのマッピング
  23. /// </summary>
  24. protected IDictionary<String, String> dic_;
  25. public WebController(ChromeDriver driver) {
  26. driver_ = driver;
  27. wait_ = new WebDriverWait(driver_, TimeSpan.FromSeconds(10));
  28. }
  29. public virtual void SetParkingDic(IDictionary<String, String> dic) {
  30. dic_ = dic;
  31. }
  32. public CreditAgent GetCreditAgent() {
  33. return agent_;
  34. }
  35. abstract public ResultCode Login(LoginInfo login_info);
  36. abstract public ResultCode Download(DateTime from, DateTime to);
  37. abstract public ResultCode Logout();
  38. public ResultCode Archive(String archive_filename) {
  39. logger_.Info("アーカイブ開始");
  40. var dir_name = "archive";
  41. if (!Directory.Exists(dir_name)) {
  42. Directory.CreateDirectory(dir_name);
  43. }
  44. String target = @$"{dir_name}\{archive_filename}";
  45. logger_.Info($"{target}");
  46. if (System.IO.File.Exists(target)) {
  47. logger_.Info($"上書き:{target}");
  48. System.IO.File.Delete(target);
  49. }
  50. ZipFile.CreateFromDirectory("download", target);
  51. logger_.Info("アーカイブ終了");
  52. return ResultCode.OK;
  53. }
  54. public virtual List<CreditCSVData> GetCreditCSVDataList() {
  55. return new List<CreditCSVData>();
  56. }
  57. public virtual List<QRCSVData> GetQRCSVDataList() {
  58. return new List<QRCSVData>();
  59. }
  60. protected void Click(String xpath, bool wait = true) {
  61. if (wait) {
  62. var ele = wait_.Until(ExpectedConditions.ElementToBeClickable(By.XPath(xpath)));
  63. ele.Click();
  64. } else {
  65. var ele = driver_.FindElementByXPath(xpath);
  66. ele.Click();
  67. }
  68. Console.WriteLine($"Click {xpath}");
  69. Wait(interval_milisec_);
  70. }
  71. protected void Click(IWebElement ele) {
  72. ele.Click();
  73. Wait(interval_milisec_);
  74. }
  75. protected void Send(String xpath, String value, bool enter = false) {
  76. var ele = wait_.Until(ExpectedConditions.ElementIsVisible(By.XPath(xpath)));
  77. ele.SendKeys(value);
  78. if (enter) {
  79. ele.SendKeys(OpenQA.Selenium.Keys.Enter);
  80. }
  81. Wait(interval_milisec_);
  82. }
  83. protected void Select(String xpath, String value) {
  84. try {
  85. var ele = wait_.Until(ExpectedConditions.ElementIsVisible(By.XPath(xpath)));
  86. var select = new SelectElement(ele);
  87. var options = select.Options;
  88. select.SelectByValue(value);
  89. Wait(interval_milisec_);
  90. } catch (Exception e) {
  91. Console.WriteLine($" Select failed xpath:{xpath} value:{value}");
  92. throw e;
  93. }
  94. }
  95. /// <summary>
  96. /// ダウンロードを開始したファイルを完了まで監視する
  97. /// 完了後はダウンロード完了ディレクトリに移動する
  98. /// </summary>
  99. /// <returns></returns>
  100. protected void WaitForDownload(String filename) {
  101. String tmpdownload_dir = DriverFactory.GetTmpDownloadDir();
  102. String download_dir = DriverFactory.GetDownloadDir();
  103. int limit_start = 0;
  104. long last_size = 0;
  105. String complete_filename = "";
  106. while (true) {
  107. var dir = new DirectoryInfo(tmpdownload_dir);
  108. var files = dir.GetFiles();
  109. if (files.Length != 0) {
  110. var file = files[0];
  111. if (file.Name.Contains(".crdownload")) {
  112. // ダウンロード継続
  113. last_size = file.Length;
  114. logger_.Info($"ダウンロード監視中:{file.Name} size:{file.Length}");
  115. } else if (file.Length == last_size) {
  116. // ダウンロード完了
  117. logger_.Info($"ダウンロード完了:{file.Name} size:{file.Length}");
  118. complete_filename = file.Name;
  119. break;
  120. } else {
  121. // ダウンロード継続
  122. last_size = file.Length;
  123. logger_.Info($"ダウンロード監視中:{file.Name} size:{file.Length}");
  124. }
  125. } else {
  126. // ファイルが存在しない場合は、一定回数リトライし
  127. // 規定回数存在しない場合は失敗とする。
  128. if (10 < limit_start) {
  129. throw new Exception("ダウンロード開始失敗");
  130. }
  131. logger_.Info($"ダウンロード開始待ち");
  132. limit_start++;
  133. }
  134. Wait(500);
  135. }
  136. // ファイルの移動
  137. String source_filename = $@"{tmpdownload_dir}\{complete_filename}";
  138. String dest_filename = $@"{download_dir}\{filename}";
  139. System.IO.File.Move(source_filename, dest_filename, true);
  140. }
  141. protected void Wait(int milisec) {
  142. Thread.Sleep(milisec);
  143. }
  144. protected String GetSpotID(String parking_name) {
  145. if (!dic_.ContainsKey(parking_name)) {
  146. throw new ArgumentException();
  147. }
  148. return dic_[parking_name];
  149. }
  150. protected class CSVConfig {
  151. public bool header = false;
  152. public List<String> remove_char = new List<string>();
  153. }
  154. protected List<String[]> ReadCsv(String csvpath, CSVConfig config, Encoding enc) {
  155. var list = new List<String[]>();
  156. var fs = new FileStream(csvpath, FileMode.Open);
  157. var data = new byte[fs.Length];
  158. fs.Read(data, 0, data.Length);
  159. fs.Close();
  160. var content = enc.GetString(data);
  161. var lines = content.Split("\n");
  162. bool header_skip = config.header;
  163. foreach (var line in lines) {
  164. var tmpline = line;
  165. line.Trim();
  166. // 空の行はスキップ
  167. if (line.Length == 0) {
  168. continue;
  169. }
  170. // ヘッダー行のスキップ制御
  171. if (header_skip) {
  172. header_skip = false;
  173. continue;
  174. }
  175. // 囲み文字の削除
  176. if (config.remove_char != null) {
  177. foreach (var remove_char in config.remove_char) {
  178. tmpline = tmpline.Replace(remove_char, "");
  179. }
  180. }
  181. var values = tmpline.Split(",");
  182. var elements = new String[values.Length];
  183. int index = 0;
  184. foreach (var ele in values) {
  185. elements[index++] = ele.Trim();
  186. }
  187. list.Add(elements);
  188. }
  189. return list;
  190. }
  191. /// <summary>
  192. /// デフォルトのフレームにもどる
  193. /// </summary>
  194. protected void SwitchToFrame() {
  195. driver_.SwitchTo().DefaultContent();
  196. }
  197. /// <summary>
  198. /// フレームを切り替える。
  199. /// </summary>
  200. /// <param name="xpath"></param>
  201. protected void SwitchToFrame(String xpath) {
  202. var frame = wait_.Until(ExpectedConditions.ElementExists(By.XPath(xpath)));
  203. driver_.SwitchTo().Frame(frame);
  204. }
  205. /// <summary>
  206. /// 空の可能性があるソースをDateTimeへ変換する際、Null許容型として変換する。
  207. /// </summary>
  208. /// <param name="source"></param>
  209. /// <returns></returns>
  210. protected DateTime? GetDateTime(String source) {
  211. if (source != null && 0 < source.Length) {
  212. return DateTime.Parse(source);
  213. } else {
  214. return null;
  215. }
  216. }
  217. }
  218. }