HeNan22X5Job.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Text.RegularExpressions;
  6. using CP.Model;
  7. using HtmlAgilityPack;
  8. using Newtonsoft.Json;
  9. using Quartz;
  10. using SCC.Common;
  11. using SCC.Crawler.Tools;
  12. using SCC.Interface;
  13. using SCC.Models;
  14. namespace SCC.Crawler.DT
  15. {
  16. /// <summary>
  17. /// 河南22选5
  18. /// </summary>
  19. [DisallowConcurrentExecution]
  20. [PersistJobDataAfterExecution]
  21. public class HeNan22X5Job : IJob
  22. {
  23. /// <summary>
  24. /// 初始化函数
  25. /// </summary>
  26. public HeNan22X5Job()
  27. {
  28. log = new LogHelper();
  29. email = IOC.Resolve<IEmail>();
  30. }
  31. /// <summary>
  32. /// 作业执行入口
  33. /// </summary>
  34. /// <param name="context">作业执行上下文</param>
  35. public void Execute(IJobExecutionContext context)
  36. {
  37. Config = CommonHelper.GetConfigFromDataMap(context.JobDetail.JobDataMap);
  38. //预设节假日不开奖
  39. if (Config.SkipDate.Contains(CommonHelper.SCCSysDateTime.ToString("yyyyMMdd"))) return;
  40. LatestItem = context.JobDetail.JobDataMap["LatestItem"] as Fchn22x5LongInfo;
  41. try
  42. {
  43. //服务启动时配置初始数据
  44. if (LatestItem == null)
  45. {
  46. LatestItem = new Fchn22x5LongInfo
  47. {
  48. qi = CommonHelper.GenerateQiHaoYYYYQQQ(0),
  49. date = new DateTime(CommonHelper.SCCSysDateTime.Year, 1, 1)
  50. };
  51. }
  52. //当今日开奖并且当前时间是晚上8点过后开始抓取
  53. if (CommonHelper.CheckTodayIsOpenDay(Config) && CommonHelper.SCCSysDateTime.Hour > 0)
  54. {
  55. DoTodayJobByMainUrl();
  56. DoTodayJobByBackUrl();
  57. }
  58. }
  59. catch (Exception ex)
  60. {
  61. log.Error(GetType(), string.Format("【{0}】抓取时发生错误,错误信息【{1}】", Config.Area + currentLottery, ex.Message));
  62. }
  63. //保存最新期号
  64. context.JobDetail.JobDataMap["LatestItem"] = LatestItem;
  65. }
  66. /// <summary>
  67. /// 通过主站点爬取开奖数据
  68. /// (河南福彩网)
  69. /// </summary>
  70. private void DoTodayJobByMainUrl()
  71. {
  72. if (!string.IsNullOrEmpty(Config.MainUrl))
  73. {
  74. var openList = GetOpenListFromMainUrl(Config.MainUrl);
  75. if (openList == null || openList.Count == 0) return; //无抓取数据
  76. //抓取到的最新期数
  77. var newestQiHao = Convert.ToInt32(openList.OrderByDescending(m => m.qi).First().qi.ToString());
  78. //数据库里面最新期数
  79. LatestItem = Fchn22x5Data.GetLastOne();
  80. var startQiNum = Convert.ToInt32(LatestItem.qi.ToString());
  81. if (startQiNum > newestQiHao) return; //无最新数据
  82. //处理最新开奖数据
  83. Fchn22x5LongInfo matchItem = null;
  84. for (var i = startQiNum; i <= newestQiHao; i++)
  85. {
  86. matchItem = openList.Where(R => R.qi.ToString() == i.ToString()).FirstOrDefault();
  87. if (matchItem != null)
  88. {
  89. //add db
  90. matchItem.addtime = DateTime.Now;
  91. Fchn22x5Data.Add(matchItem);
  92. //Do Success Log
  93. log.Info(GetType(), CommonHelper.GetJobMainLogInfo(Config, i.ToString()));
  94. LatestItem = matchItem;
  95. isGetData = true;
  96. }
  97. }
  98. }
  99. }
  100. /// <summary>
  101. /// 获取主站开奖列表数据
  102. /// </summary>
  103. /// <param name="mainUrl">主站地址</param>
  104. /// <returns></returns>
  105. private List<Fchn22x5LongInfo> GetOpenListFromMainUrl(string mainUrl)
  106. {
  107. var result = new List<Fchn22x5LongInfo>();
  108. try
  109. {
  110. var url = new Uri(mainUrl);
  111. var htmlResource = NetHelper.GetUrlResponse(url.AbsoluteUri);
  112. if (htmlResource == null) return result;
  113. var doc = new HtmlDocument();
  114. doc.LoadHtml(htmlResource);
  115. var table = doc.DocumentNode.SelectSingleNode("//table");
  116. if (table == null) return result;
  117. var trs = table.ChildNodes.Where(S => S.Name.ToLower() == "tr").ToList();
  118. List<HtmlNode> tds = null;
  119. string term = string.Empty, openCodeString = string.Empty, optimizeUrl = string.Empty;
  120. decimal sales = 0, pool = 0;
  121. Fchn22x5LongInfo model = null;
  122. HtmlNode nodeA = null;
  123. for (var i = 1; i < trs.Count; i++)
  124. {
  125. tds = trs[i].ChildNodes.Where(S => S.Name.ToLower() == "td").ToList();
  126. if (tds.Count < 8) continue;
  127. model = new Fchn22x5LongInfo();
  128. term = tds[0].InnerText.Trim();
  129. if (term.StartsWith((CommonHelper.SCCSysDateTime.Year - 1).ToString())) break;
  130. model.qi = Convert.ToInt32(tds[0].InnerText.Trim());
  131. openCodeString = tds[1].InnerText.Trim();
  132. model.n1 = Convert.ToInt32(openCodeString.Substring(0, 2));
  133. model.n2 = Convert.ToInt32(openCodeString.Substring(2, 2));
  134. model.n3 = Convert.ToInt32(openCodeString.Substring(4, 2));
  135. model.n4 = Convert.ToInt32(openCodeString.Substring(6, 2));
  136. model.n5 = Convert.ToInt32(openCodeString.Substring(8, 2));
  137. model.date = Convert.ToDateTime(tds[6].InnerText.Trim());
  138. sales = Convert.ToDecimal(tds[2].InnerText.Trim());
  139. pool = Convert.ToDecimal(tds[5].InnerText.Trim());
  140. //model.Spare = sales + "|" + pool;
  141. model.tzmoney = sales.ToString();
  142. model.nextmoney = pool.ToString();
  143. nodeA = tds[7].ChildNodes.Where(N => N.Name.ToLower() == "a").FirstOrDefault();
  144. if (nodeA == null) continue;
  145. optimizeUrl = nodeA.Attributes["href"].Value;
  146. string detailUrl = new Uri(url, optimizeUrl).AbsoluteUri;
  147. OptimizeMainModel(ref model, detailUrl);
  148. result.Add(model);
  149. }
  150. //var checkDataHelper = new CheckDataHelper();
  151. //var dbdata = services.GetListS<OpenCode5DTModel>(currentLottery)
  152. // .ToDictionary(w => w.Term.ToString(), w => w.GetCodeStr());
  153. //checkDataHelper.CheckData(dbdata, result.ToDictionary(w => w.Term.ToString(), w => w.GetCodeStr()),
  154. // Config.Area, currentLottery);
  155. }
  156. catch (Exception ex)
  157. {
  158. log.Error(GetType(),
  159. string.Format("【{0}】通过主站点抓取开奖列表时发生错误,错误信息【{1}】", Config.Area + currentLottery, ex.Message));
  160. }
  161. return result;
  162. }
  163. /// <summary>
  164. /// 完善主站江苏体彩7位数开奖详情信息
  165. /// </summary>
  166. /// <param name="model"></param>
  167. private bool OptimizeMainModel(ref Fchn22x5LongInfo model,string detailUrl)
  168. {
  169. try
  170. {
  171. var htmlResource = NetHelper.GetUrlResponse(detailUrl);
  172. if (string.IsNullOrWhiteSpace(htmlResource)) return false;
  173. var doc = new HtmlDocument();
  174. doc.LoadHtml(htmlResource);
  175. var table = doc.DocumentNode.SelectSingleNode("//table");
  176. if (table == null) return false;
  177. var trs = table.ChildNodes.Where(C => C.Name == "tr").ToList();
  178. List<HtmlNode> tds = null;
  179. foreach (var tr in trs)
  180. {
  181. tds = tr.ChildNodes.Where(S => S.Name.ToLower() == "td").ToList();
  182. if (tds.Count < 3) continue;
  183. if (tds[0].InnerText == "一等奖")
  184. {
  185. //一等奖
  186. model.zj1 = tds[1].InnerText.Replace("注", "");
  187. model.jo1 = tds[2].InnerText.Replace("元", "");
  188. }
  189. else if (tds[0].InnerText == "二等奖")
  190. {
  191. //二等奖
  192. model.zj2 = tds[1].InnerText.Replace("注", "");
  193. model.jo2 = tds[2].InnerText.Replace("元", "");
  194. }
  195. else if (tds[0].InnerText == "三等奖")
  196. {
  197. //三等奖
  198. model.zj3 = tds[1].InnerText.Replace("注", "");
  199. model.jo3 = tds[2].InnerText.Replace("元", "");
  200. }
  201. else if (tds[0].InnerText == "好运二")
  202. {
  203. //好运二
  204. model.hj2 = tds[1].InnerText.Replace("注", "");
  205. model.ho2 = tds[2].InnerText.Replace("元", "");
  206. }
  207. else if (tds[0].InnerText == "好运三")
  208. {
  209. //好运三
  210. model.hj3 = tds[1].InnerText.Replace("注", "");
  211. model.ho3 = tds[2].InnerText.Replace("元", "");
  212. }
  213. else if (tds[0].InnerText == "好运四")
  214. {
  215. //好运四
  216. model.hj4 = tds[1].InnerText.Replace("注", "");
  217. model.ho4 = tds[2].InnerText.Replace("元", "");
  218. }
  219. var list = new List<Winbonus>();
  220. list.Add(new Winbonus()
  221. {
  222. item = "一等奖",
  223. wincount = model.zj1,
  224. winmoney = model.jo1
  225. });
  226. list.Add(new Winbonus()
  227. {
  228. item = "二等奖",
  229. wincount = model.zj2,
  230. winmoney = model.jo2
  231. });
  232. list.Add(new Winbonus()
  233. {
  234. item = "三等奖",
  235. wincount = model.zj3,
  236. winmoney = model.jo3
  237. });
  238. list.Add(new Winbonus()
  239. {
  240. item = "好运二",
  241. wincount = model.hj2,
  242. winmoney = model.ho2
  243. });
  244. list.Add(new Winbonus()
  245. {
  246. item = "好运三",
  247. wincount = model.hj3,
  248. winmoney = model.ho3
  249. });
  250. list.Add(new Winbonus()
  251. {
  252. item = "好运四",
  253. wincount = model.hj4,
  254. winmoney = model.ho4
  255. });
  256. model.winbonus = JsonConvert.SerializeObject(list);
  257. }
  258. return true;
  259. }
  260. catch (Exception ex)
  261. {
  262. log.Error(GetType(),
  263. string.Format("【{0}】通过主站点完善抓取开奖列表时发生错误,错误信息【{1}】", Config.Area + currentLottery, ex.Message));
  264. }
  265. return false;
  266. }
  267. /// <summary>
  268. /// 通过备用站点抓取开奖数据
  269. /// (彩票两元网)
  270. /// </summary>
  271. private void DoTodayJobByBackUrl()
  272. {
  273. if (!string.IsNullOrEmpty(Config.BackUrl))
  274. {
  275. var openList = GetOpenListFromBackUrl();
  276. if (openList == null || openList.Count == 0) return; //无抓取数据
  277. //抓取到的最新期数
  278. var newestQiHao = Convert.ToInt32(openList.OrderByDescending(m => m.qi).First().qi.ToString());
  279. //数据库里面最新期数
  280. //LatestItem = Fchn22x5Data.GetLastOne();
  281. var startQiNum = Convert.ToInt32(LatestItem.qi.ToString());
  282. if (startQiNum > newestQiHao) return; //无最新数据
  283. //处理最新开奖数据
  284. Fchn22x5LongInfo matchItem = null;
  285. for (var i = startQiNum; i <= newestQiHao; i++)
  286. {
  287. matchItem = openList.Where(R => R.qi.ToString() == i.ToString()).FirstOrDefault();
  288. if (matchItem != null)
  289. {
  290. //add db
  291. matchItem.addtime = DateTime.Now;
  292. Fchn22x5Data.Add(matchItem);
  293. //Do Success Log
  294. log.Info(GetType(), CommonHelper.GetJobBackLogInfo(Config, i.ToString()));
  295. LatestItem = matchItem;
  296. isGetData = true;
  297. }
  298. }
  299. }
  300. }
  301. /// <summary>
  302. /// 获取备用站点开奖列表数据
  303. /// </summary>
  304. /// <returns></returns>
  305. private List<Fchn22x5LongInfo> GetOpenListFromBackUrl()
  306. {
  307. var result = new List<Fchn22x5LongInfo>();
  308. try
  309. {
  310. var url = new Uri(Config.BackUrl);
  311. var htmlResource = NetHelper.GetUrlResponse(Config.BackUrl, Encoding.GetEncoding("gb2312"));
  312. if (htmlResource == null) return result;
  313. var doc = new HtmlDocument();
  314. doc.LoadHtml(htmlResource);
  315. var table = doc.DocumentNode.SelectSingleNode("//table");
  316. if (table == null) return result;
  317. var trs = table.ChildNodes.Where(node => node.Name == "tr").ToList();
  318. Fchn22x5LongInfo model = null;
  319. HtmlNode nodeA = null;
  320. var optimizeUrl = string.Empty;
  321. for (var i = 2; i < trs.Count; i++) //第一二行为表头
  322. {
  323. var trstyle = trs[i].Attributes["style"];
  324. if (trstyle != null && trstyle.Value == "display:none") continue;
  325. var tds = trs[i].ChildNodes.Where(node => node.Name == "td").ToList();
  326. if (tds.Count < 10) continue;
  327. model = new Fchn22x5LongInfo();
  328. nodeA = tds[0].ChildNodes.Where(n => n.Name == "a").FirstOrDefault();
  329. if (nodeA == null) continue;
  330. model.qi = Convert.ToInt32(nodeA.InnerText.Trim());
  331. optimizeUrl = nodeA.Attributes["href"].Value;
  332. string detailUrl = new Uri(url, optimizeUrl).AbsoluteUri;
  333. model.date = Convert.ToDateTime(tds[9].InnerText);
  334. if (tds[1].ChildNodes.Count == 0) continue;
  335. var opencodeNode = tds[1].ChildNodes.Where(n => n.Name.ToLower() == "i").ToList();
  336. if (opencodeNode.Count < 5) continue;
  337. model.n1 = Convert.ToInt32(opencodeNode[0].InnerText.Trim());
  338. model.n2 = Convert.ToInt32(opencodeNode[1].InnerText.Trim());
  339. model.n3 = Convert.ToInt32(opencodeNode[2].InnerText.Trim());
  340. model.n4 = Convert.ToInt32(opencodeNode[3].InnerText.Trim());
  341. model.n5 = Convert.ToInt32(opencodeNode[4].InnerText.Trim());
  342. OptimizeBackModel(ref model, detailUrl);
  343. result.Add(model);
  344. }
  345. //var checkDataHelper = new CheckDataHelper();
  346. //var dbdata = services.GetListS<OpenCode5DTModel>(currentLottery)
  347. // .ToDictionary(w => w.Term.ToString(), w => w.GetCodeStr());
  348. //checkDataHelper.CheckData(dbdata, result.ToDictionary(w => w.Term.ToString(), w => w.GetCodeStr()),
  349. // Config.Area, currentLottery);
  350. //result = result.OrderByDescending(S => S.Term).ToList();
  351. }
  352. catch (Exception ex)
  353. {
  354. log.Error(GetType(),
  355. string.Format("【{0}】通过备用站点抓取开奖列表时发生错误,错误信息【{1}】", Config.Area + currentLottery, ex.Message));
  356. }
  357. return result;
  358. }
  359. /// <summary>
  360. /// 完善备用站点江苏体彩7位数开奖实体信息
  361. /// </summary>
  362. /// <param name="model"></param>
  363. private bool OptimizeBackModel(ref Fchn22x5LongInfo model,string detailUrl)
  364. {
  365. try
  366. {
  367. var htmlResource = NetHelper.GetUrlResponse(detailUrl, Encoding.GetEncoding("gb2312"));
  368. if (string.IsNullOrWhiteSpace(htmlResource)) return false;
  369. var doc = new HtmlDocument();
  370. doc.LoadHtml(htmlResource);
  371. var table = doc.DocumentNode.SelectSingleNode("//table");
  372. if (table == null) return false;
  373. var trs = table.ChildNodes.Where(N => N.Name.ToLower() == "tr").ToList();
  374. List<HtmlNode> tds = null;
  375. for (var i = 1; i < trs.Count; i++) //第一行为表头
  376. {
  377. tds = trs[i].ChildNodes.Where(N => N.Name.ToLower() == "td").ToList();
  378. if (tds.Count < 5) continue;
  379. if (tds[1].InnerText == "一等奖")
  380. {
  381. //一等奖
  382. model.zj1 = tds[2].InnerText;
  383. model.jo1 = tds[3].InnerText;
  384. }
  385. if (tds[1].InnerText == "二等奖")
  386. {
  387. //二等奖
  388. model.zj2 = tds[2].InnerText;
  389. model.jo2 = tds[3].InnerText;
  390. }
  391. if (tds[1].InnerText == "三等奖")
  392. {
  393. //三等奖
  394. model.zj3 = tds[2].InnerText;
  395. model.jo3 = tds[3].InnerText;
  396. }
  397. if (tds[1].InnerText == "好运二")
  398. {
  399. //好运二
  400. model.hj2 = tds[2].InnerText;
  401. model.ho2 = tds[3].InnerText;
  402. }
  403. if (tds[1].InnerText == "好运三")
  404. {
  405. //好运三
  406. model.hj3 = tds[2].InnerText;
  407. model.ho3 = tds[3].InnerText;
  408. }
  409. if (tds[1].InnerText == "好运四")
  410. {
  411. //好运四
  412. model.hj4 = tds[2].InnerText;
  413. model.ho4 = tds[3].InnerText;
  414. }
  415. var list = new List<Winbonus>();
  416. list.Add(new Winbonus()
  417. {
  418. item = "一等奖",
  419. wincount = model.zj1,
  420. winmoney = model.jo1
  421. });
  422. list.Add(new Winbonus()
  423. {
  424. item = "二等奖",
  425. wincount = model.zj2,
  426. winmoney = model.jo2
  427. });
  428. list.Add(new Winbonus()
  429. {
  430. item = "三等奖",
  431. wincount = model.zj3,
  432. winmoney = model.jo3
  433. });
  434. list.Add(new Winbonus()
  435. {
  436. item = "好运二",
  437. wincount = model.hj2,
  438. winmoney = model.ho2
  439. });
  440. list.Add(new Winbonus()
  441. {
  442. item = "好运三",
  443. wincount = model.hj3,
  444. winmoney = model.ho3
  445. });
  446. list.Add(new Winbonus()
  447. {
  448. item = "好运四",
  449. wincount = model.hj4,
  450. winmoney = model.ho4
  451. });
  452. model.winbonus = JsonConvert.SerializeObject(list);
  453. }
  454. var reg = new Regex(@"本期投注总额:([\d.,]*?)元");
  455. var match = reg.Match(htmlResource);
  456. if (match.Success) model.tzmoney = match.Result("$1").Replace(",", string.Empty);
  457. reg = new Regex(@"奖池资金累计金额:([\d.,]*?)元");
  458. match = reg.Match(htmlResource);
  459. if (match.Success) model.nextmoney = match.Result("$1").Replace(",", string.Empty);
  460. return true;
  461. }
  462. catch (Exception ex)
  463. {
  464. log.Error(GetType(),
  465. string.Format("【{0}】通过备用站点优化开奖列表时发生错误,错误信息【{1}】", Config.Area + currentLottery, ex.Message));
  466. }
  467. return false;
  468. }
  469. #region Attribute
  470. /// <summary>
  471. /// 配置信息
  472. /// </summary>
  473. private SCCConfig Config;
  474. /// <summary>
  475. /// 当天抓取的最新一期开奖记录
  476. /// </summary>
  477. private Fchn22x5LongInfo LatestItem;
  478. #pragma warning disable CS0169 // 从不使用字段“HeNan22X5Job.FailedQiHaoList”
  479. /// <summary>
  480. /// 当天抓取失败列表
  481. /// </summary>
  482. private List<string> FailedQiHaoList;
  483. #pragma warning restore CS0169 // 从不使用字段“HeNan22X5Job.FailedQiHaoList”
  484. /// <summary>
  485. /// 日志对象
  486. /// </summary>
  487. private readonly LogHelper log;
  488. /// <summary>
  489. /// 当前彩种
  490. /// </summary>
  491. private SCCLottery currentLottery => SCCLottery.HeNan22X5;
  492. /// <summary>
  493. /// 邮件接口
  494. /// </summary>
  495. private readonly IEmail email;
  496. #pragma warning disable CS0414 // 字段“HeNan22X5Job.isGetData”已被赋值,但从未使用过它的值
  497. /// <summary>
  498. /// 是否本次运行抓取到开奖数据
  499. /// </summary>
  500. private bool isGetData;
  501. #pragma warning restore CS0414 // 字段“HeNan22X5Job.isGetData”已被赋值,但从未使用过它的值
  502. #endregion
  503. }
  504. }