1030 lines
31 KiB
C#
1030 lines
31 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
|
|
namespace NewsCrawler
|
|
{
|
|
public partial class NewsForm : Form
|
|
{
|
|
class PRICE_CHECK_DATA
|
|
{
|
|
public int m_iID;
|
|
public CodeList.CODE_VALUE m_Code;
|
|
public int m_iPriceStart = 0;
|
|
public int m_iPriceLow = 0;
|
|
public int m_iPriceHigh = 0;
|
|
public DateTime m_StartTime;
|
|
}
|
|
|
|
|
|
CybosHelper m_CybosHelper = null;
|
|
CodeList m_CodeList = null;
|
|
TextCondition m_Condition = null;
|
|
ConfigForm m_ConfigForm = null;
|
|
|
|
System.Timers.Timer m_CrawlTimer = new System.Timers.Timer();
|
|
int m_iCrawlInterval = 500;
|
|
bool m_bBrowserReload = false;
|
|
bool m_bBuy = false;
|
|
|
|
ConcurrentQueue<PRICE_CHECK_DATA> m_PriceCheckList = new ConcurrentQueue<PRICE_CHECK_DATA>();
|
|
System.Timers.Timer m_PriceCheckTimer = new System.Timers.Timer();
|
|
|
|
public NewsForm()
|
|
{
|
|
InitializeComponent();
|
|
|
|
Config.Init();
|
|
Util.SetLogView(tbLog);
|
|
m_CodeList = new CodeList();
|
|
m_Condition = new TextCondition();
|
|
m_CybosHelper = new CybosHelper(this);
|
|
|
|
MessageBox.Show("Keywords : \n\n" + m_Condition.GetKeywordsCnt());
|
|
|
|
|
|
wbView.ScriptErrorsSuppressed = false;
|
|
|
|
ReadKIND(true);
|
|
ReadDart(true);
|
|
ReadEtoday(true);
|
|
ReadEToday2(true);
|
|
ReadAsiaE(true);
|
|
ReadEdaily(true);
|
|
ReadMoneyToday(true);
|
|
ReadFinacialNews(true);
|
|
|
|
|
|
lvList.ListViewItemSorter = new ListViewItemComparer(chId.Index, SortOrder.Ascending);
|
|
lvList.Sorting = SortOrder.Ascending;
|
|
lvList.Sort();
|
|
|
|
if(lvList.Items.Count > 0)
|
|
{
|
|
lvList.Items[lvList.Items.Count - 1].Selected = true;
|
|
lvList.Select();
|
|
if(lvList.SelectedItems.Count > 0)
|
|
lvList.SelectedItems[0].EnsureVisible();
|
|
}
|
|
lvList.Columns[chTime.Index].TextAlign = HorizontalAlignment.Right;
|
|
lvList.Columns[chResponseT.Index].TextAlign = HorizontalAlignment.Right;
|
|
lvList.Columns[chResT.Index].TextAlign = HorizontalAlignment.Right;
|
|
lvList.Columns[chId.Index].TextAlign = HorizontalAlignment.Right;
|
|
lvList.Columns[chPriceS.Index].TextAlign = HorizontalAlignment.Right;
|
|
lvList.Columns[chPriceLow.Index].TextAlign = HorizontalAlignment.Right;
|
|
lvList.Columns[chPriceHigh.Index].TextAlign = HorizontalAlignment.Right;
|
|
|
|
m_CrawlTimer.Elapsed+=CrawlTimer_Tick;
|
|
m_CrawlTimer.Interval=m_iCrawlInterval;
|
|
m_CrawlTimer.Start();
|
|
|
|
m_PriceCheckTimer.Interval = 5000;
|
|
m_PriceCheckTimer.Elapsed += PriceCheckTimer_Elapsed;
|
|
m_PriceCheckTimer.Start();
|
|
|
|
Test();
|
|
}
|
|
|
|
void Test()
|
|
{
|
|
if(Util.IsDebugging() == false)
|
|
return;
|
|
|
|
InsertItem("[test] 덕산하이메탈, 덕산네오룩스 66만여주 취득14:38", "", "", new DateTime(2016, 11, 30, 00, 00, 00), DateTime.Now, "http://www.asiae.co.kr/news/sokbo/sokbo_view.htm?idxno=2016112914371817318", "asiae", 0, false);
|
|
InsertItem("[test] 자연과환경, 12월15일~22일 주주명부폐쇄14:19", "", "", new DateTime(2016, 11, 30, 00, 00, 00), DateTime.Now, "http://www.asiae.co.kr/news/sokbo/sokbo_view.htm?idxno=2016112914193170301", "asiae", 0, false);
|
|
InsertItem("[test] 이엠코리아, 한국항공우주산업과 3억원 규모 공급계약14:06", "", "", new DateTime(2016, 11, 30, 00, 00, 00), DateTime.Now, "http://www.asiae.co.kr/news/sokbo/sokbo_view.htm?idxno=2016112914055964082", "asiae", 0, false);
|
|
InsertItem("[test] [특징주] 진원생명과학, 국외 AI 인체감염증...", "", "", new DateTime(2016, 11, 30, 00, 00, 00), DateTime.Now, "http://www.etoday.co.kr/news/sokbo/sokbo_view.htm?idxno=2016112914055964082", "이투데이", 0, false);
|
|
}
|
|
|
|
private void BuyItem(CodeList.CODE_VALUE Code)
|
|
{
|
|
if(m_bBuy == false)
|
|
return;
|
|
|
|
if((Code.m_enType & CodeList.CODE_TYPE.DENIAL) == CodeList.CODE_TYPE.DENIAL)
|
|
{
|
|
Util.Log(Util.LOG_TYPE.DENIAL, string.Format("거부종목 ({0})", Code));
|
|
return;
|
|
}
|
|
|
|
if((Code.m_enType & CodeList.CODE_TYPE.DUPLICATED) == CodeList.CODE_TYPE.DUPLICATED)
|
|
{
|
|
Util.Log(Util.LOG_TYPE.DUPLICATED, string.Format("중복종목 ({0})", Code));
|
|
return;
|
|
}
|
|
|
|
m_CybosHelper.Buy(Code, Config.GetBuyPrice());
|
|
m_CodeList.AddDuplicatedList(Code.m_strCode, Code.m_strName);
|
|
}
|
|
|
|
public void OnManualItemBuy(CodeList.CODE_VALUE Code)
|
|
{
|
|
BuyItem(Code);
|
|
}
|
|
|
|
void CheckPrice(int iID, CodeList.CODE_VALUE Code)
|
|
{
|
|
PRICE_CHECK_DATA CheckData = new PRICE_CHECK_DATA();
|
|
CheckData.m_iID = iID;
|
|
CheckData.m_Code = Code;
|
|
CheckData.m_StartTime = DateTime.Now;
|
|
m_PriceCheckList.Enqueue(CheckData);
|
|
}
|
|
|
|
void ProcessSearchAndBuy(string strTitle, string strName, string strCode, string strRef, int iID)
|
|
{
|
|
CodeList.CODE_VALUE Code;
|
|
if(strCode == "")
|
|
Code = m_CodeList.SearchCode(strTitle);
|
|
else
|
|
Code = m_CodeList.GetCode(strCode);
|
|
|
|
if(Code != null)
|
|
{
|
|
TextCondition.RESULT MatchResult = m_Condition.Match(strTitle);
|
|
switch(MatchResult.m_enType)
|
|
{
|
|
case TextCondition.TYPE.NEGATIVE:
|
|
Util.Log(Util.LOG_TYPE.NEGATIVE, string.Format("[{0}] {1} (keyword:{2}, code:{3})", strRef, strTitle, MatchResult.m_strKeyword, Code.ToString()));
|
|
break;
|
|
|
|
case TextCondition.TYPE.POSITIVE:
|
|
if((Code.m_enType&CodeList.CODE_TYPE.DENIAL) == CodeList.CODE_TYPE.DENIAL)
|
|
Util.Log(Util.LOG_TYPE.DENIAL, string.Format("[{0}] {1} (keyword:{2}, code:{3})", strRef, strTitle, MatchResult.m_strKeyword, Code.ToString()));
|
|
else if((Code.m_enType&CodeList.CODE_TYPE.DENIAL) == CodeList.CODE_TYPE.DUPLICATED)
|
|
Util.Log(Util.LOG_TYPE.DUPLICATED, string.Format("[{0}] {1} (keyword:{2}, code:{3})", strRef, strTitle, MatchResult.m_strKeyword, Code.ToString()));
|
|
else if((Code.m_enType&CodeList.CODE_TYPE.DENIAL) == CodeList.CODE_TYPE.MANUAL)
|
|
Util.Log(Util.LOG_TYPE.MANUAL_CODE, string.Format("[{0}] {1} (keyword:{2}, code:{3})", strRef, strTitle, MatchResult.m_strKeyword, Code.ToString()));
|
|
else
|
|
{
|
|
Util.Log(Util.LOG_TYPE.POSITIVE, string.Format("[{0}] {1} (keyword:{2}, code:{3})", strRef, strTitle, MatchResult.m_strKeyword, Code.ToString()));
|
|
BuyItem(Code);
|
|
}
|
|
|
|
m_CodeList.AddDuplicatedList(Code.m_strCode, Code.m_strName);
|
|
break;
|
|
|
|
case TextCondition.TYPE.MANUAL:
|
|
Util.Log(Util.LOG_TYPE.MANUAL_KEYWORD, string.Format("[{0}] {1} (keyword:{2}, code:{3})", strRef, strTitle, MatchResult.m_strKeyword, Code.ToString()));
|
|
|
|
if(m_bBuy == true)
|
|
{
|
|
ModelessPopup ManualPopup = new ModelessPopup(this);
|
|
ManualPopup.SetMessage(string.Format("{0}\n[{1}] {2}\n(keyword:{3}, code:{4})\n\n매수하시겠습니까?",
|
|
DateTime.Now.ToString("[hh:mm:ss]"),
|
|
strRef, strTitle, MatchResult.m_strKeyword, Code), Code);
|
|
ManualPopup.TopMost = true;
|
|
ManualPopup.Show();
|
|
}
|
|
|
|
m_CodeList.AddDuplicatedList(Code.m_strCode, Code.m_strName);
|
|
break;
|
|
|
|
case TextCondition.TYPE.NOT_MATCHED:
|
|
Util.Log(Util.LOG_TYPE.DEBUG, string.Format("[NOT_MATCHED] [{0}] {1}({2})", strRef, strTitle, Code.ToString()));
|
|
break;
|
|
}
|
|
|
|
if(cbPriceCheck.Checked == true)
|
|
CheckPrice(iID, Code);
|
|
}
|
|
}
|
|
|
|
delegate void InsertListView(string strTitle, string strName, string strCode, DateTime time, DateTime ResTime, string strURL, string strRef, double responseT, bool bInitial);
|
|
public void InsertItem(string strTitle, string strName, string strCode, DateTime time, DateTime ResTime, string strURL, string strRef, double responseT, bool bInitial)
|
|
{
|
|
try
|
|
{
|
|
if(this.InvokeRequired)
|
|
{
|
|
this.Invoke(new InsertListView(InsertItem), strTitle, strName, strCode, time, ResTime, strURL, strRef, responseT, bInitial);
|
|
}
|
|
else
|
|
{
|
|
if(strURL != "" && lvList.Items.Cast<ListViewItem>().Any(s => s.SubItems[chLink.Index].Text == strURL))
|
|
return;
|
|
|
|
int iID = lvList.Items.Count+1;
|
|
|
|
lvList.Items.Add(new ListViewItem(new string[] {
|
|
iID.ToString(),
|
|
time.ToString("HH:mm:ss"),
|
|
ResTime.ToString("HH:mm:ss:fff"),
|
|
strRef,
|
|
strTitle,
|
|
string.Format("{0:0.0000} ms", responseT),
|
|
"",
|
|
"",
|
|
"",
|
|
strURL }));
|
|
|
|
if(bInitial == false && chAutoSelect.Checked == true)
|
|
{
|
|
m_bBrowserReload = true;
|
|
}
|
|
|
|
if(bInitial == false)
|
|
{
|
|
foreach(ColumnHeader col in lvList.Columns)
|
|
{
|
|
if(!(col == chPriceS || col == chPriceLow || col == chPriceHigh))
|
|
col.Width = -2;
|
|
}
|
|
}
|
|
|
|
if(bInitial == false)
|
|
{
|
|
lvList.Sort();
|
|
ProcessSearchAndBuy(strTitle, strName, strCode, strRef, iID);
|
|
}
|
|
}
|
|
}
|
|
catch(Exception ex)
|
|
{
|
|
Util.Log(Util.LOG_TYPE.ERROR, ex.Message);
|
|
}
|
|
}
|
|
|
|
bool ReadAsiaE(bool bInitial = false)
|
|
{
|
|
bool bHasNew = false;
|
|
|
|
try
|
|
{
|
|
string strServerURL = "http://www.asiae.co.kr";
|
|
WebRequest request = WebRequest.Create("http://www.asiae.co.kr/news/sokbo/sokbo_left.htm");
|
|
request.Credentials=CredentialCache.DefaultCredentials;
|
|
request.Timeout=2000;
|
|
|
|
System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
|
|
timer.Start();
|
|
using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
|
|
{
|
|
timer.Stop();
|
|
|
|
using(Stream dataStream = response.GetResponseStream())
|
|
{
|
|
using(StreamReader reader = new StreamReader(dataStream, Encoding.GetEncoding("EUC-KR")))
|
|
{
|
|
string responseFromServer = WebUtility.HtmlDecode(reader.ReadToEnd());
|
|
responseFromServer = responseFromServer.Replace("\"\"", "\"");
|
|
|
|
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
|
|
doc.LoadHtml(responseFromServer);
|
|
string strXPath = "//div[contains(@class, 'txtform')]/ul/li";
|
|
var lists = doc.DocumentNode.SelectNodes(strXPath);
|
|
foreach(var item in lists)
|
|
{
|
|
string strTitle1 = item.SelectSingleNode(".//a").GetAttributeValue("title", "");
|
|
string strTitle2 = item.SelectSingleNode(".//a").FirstChild.InnerText;
|
|
string strTitle = (strTitle1.Length > strTitle2.Length ? strTitle1 : strTitle2);
|
|
string strTime = item.SelectSingleNode(".//span").InnerText;
|
|
string strURL = strServerURL+item.SelectSingleNode(".//a").GetAttributeValue("href", "");
|
|
|
|
|
|
if(Regex.IsMatch(strTime, @"\d+/\d+")==true)
|
|
{
|
|
//Console.WriteLine("어제 기사 : " + item.InnerHtml);
|
|
continue;
|
|
}
|
|
|
|
InsertItem(strTitle, "", "",
|
|
DateTime.ParseExact(strTime, "HH:mm", CultureInfo.CurrentCulture),
|
|
DateTime.Now,
|
|
strURL, "아시아경제", timer.Elapsed.TotalMilliseconds, bInitial);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
Console.WriteLine(e.ToString());
|
|
}
|
|
|
|
return bHasNew;
|
|
}
|
|
|
|
bool ReadEtoday(bool bInitial = false)
|
|
{
|
|
bool bHasNew = false;
|
|
|
|
try
|
|
{
|
|
//string strServerURL = "http://www.etoday.co.kr";
|
|
WebRequest request = WebRequest.Create("http://www.etoday.co.kr/news/flash/flash_list.php?tab=1");
|
|
request.Credentials=CredentialCache.DefaultCredentials;
|
|
request.Timeout=2000;
|
|
|
|
System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
|
|
timer.Start();
|
|
using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
|
|
{
|
|
timer.Stop();
|
|
|
|
using(Stream dataStream = response.GetResponseStream())
|
|
{
|
|
using(StreamReader reader = new StreamReader(dataStream, Encoding.GetEncoding("utf-8")))
|
|
{
|
|
string responseFromServer = WebUtility.HtmlDecode(reader.ReadToEnd());
|
|
|
|
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
|
|
doc.LoadHtml(responseFromServer);
|
|
string strXPath = "//div[contains(@class, 'flash_tab_lst')]/ul/li";
|
|
var lists = doc.DocumentNode.SelectNodes(strXPath);
|
|
foreach(var item in lists)
|
|
{
|
|
string strTitle = item.SelectSingleNode(".//a").InnerText;
|
|
string strTime = item.SelectSingleNode(".//span[contains(@class, 'flash_press')]").InnerText;
|
|
string strURL = item.SelectSingleNode(".//a").GetAttributeValue("href", "");
|
|
strURL="http://www.etoday.co.kr/news/section/newsview.php?idxno="+Regex.Replace(strURL, @"\D", "");
|
|
|
|
if(Regex.IsMatch(strTime, @"\d+/\d+")==true)
|
|
{
|
|
//Console.WriteLine("어제 기사 : " + item.InnerHtml);
|
|
continue;
|
|
}
|
|
|
|
InsertItem(strTitle, "", "",
|
|
DateTime.ParseExact(strTime, "HH:mm", CultureInfo.CurrentCulture),
|
|
DateTime.Now,
|
|
strURL, "이투데이", timer.Elapsed.TotalMilliseconds, bInitial);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
Console.WriteLine(e.ToString());
|
|
}
|
|
|
|
return bHasNew;
|
|
}
|
|
|
|
bool ReadEToday2(bool bInitial = false)
|
|
{
|
|
bool bHasNew = false;
|
|
|
|
try
|
|
{
|
|
WebRequest request = WebRequest.Create("http://rss.etoday.co.kr/etoday/etoday_news_all.xml");
|
|
request.Credentials=CredentialCache.DefaultCredentials;
|
|
request.Timeout=2000;
|
|
int iCDATALen = "<![CDATA[".Length;
|
|
DateTime today = DateTime.Now;
|
|
|
|
System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
|
|
timer.Start();
|
|
|
|
using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
|
|
{
|
|
timer.Stop();
|
|
|
|
using(Stream dataStream = response.GetResponseStream())
|
|
{
|
|
using(StreamReader reader = new StreamReader(dataStream, Encoding.GetEncoding("utf-8")))
|
|
{
|
|
string responseFromServer = WebUtility.HtmlDecode(reader.ReadToEnd());
|
|
|
|
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
|
|
doc.LoadHtml(responseFromServer);
|
|
|
|
string strXPath = "//item";
|
|
var lists = doc.DocumentNode.SelectNodes(strXPath);
|
|
if(lists == null)
|
|
return false;
|
|
|
|
foreach(var item in lists)
|
|
{
|
|
string strTitle = item.SelectSingleNode(".//title").InnerText;
|
|
strTitle = strTitle.Substring(iCDATALen, strTitle.Length-iCDATALen-3);
|
|
string strTime = item.ChildNodes["pubDate"].InnerText;
|
|
DateTime time = Convert.ToDateTime(strTime);
|
|
strTime = time.ToString("HH:mm:ss");
|
|
string strURL = "[rss] " + item.ChildNodes["link"].NextSibling.InnerText;
|
|
|
|
if(time.Day != today.Day)
|
|
{
|
|
//Console.WriteLine("어제 기사 : " + item.InnerHtml);
|
|
continue;
|
|
}
|
|
|
|
InsertItem(strTitle, "", "",
|
|
DateTime.ParseExact(strTime, "HH:mm:ss", CultureInfo.CurrentCulture),
|
|
DateTime.Now,
|
|
strURL, "이투데이 rss", timer.Elapsed.TotalMilliseconds, bInitial);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
Console.WriteLine(e.ToString());
|
|
}
|
|
|
|
return bHasNew;
|
|
}
|
|
|
|
bool ReadDart(bool bInitial = false)
|
|
{
|
|
bool bHasNew = false;
|
|
|
|
try
|
|
{
|
|
string strServerURL = "https://dart.fss.or.kr";
|
|
WebRequest request = WebRequest.Create("https://dart.fss.or.kr/dsac001/mainAll.do");
|
|
request.Credentials=CredentialCache.DefaultCredentials;
|
|
request.Timeout=2000;
|
|
|
|
System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
|
|
timer.Start();
|
|
using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
|
|
{
|
|
timer.Stop();
|
|
|
|
using(Stream dataStream = response.GetResponseStream())
|
|
{
|
|
using(StreamReader reader = new StreamReader(dataStream, Encoding.GetEncoding("utf-8")))
|
|
{
|
|
string responseFromServer = WebUtility.HtmlDecode(reader.ReadToEnd());
|
|
|
|
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
|
|
doc.LoadHtml(responseFromServer);
|
|
|
|
string strXPath = "//div[@id='listContents']/div[contains(@class, 'table_list')]/table/tr";
|
|
var lists = doc.DocumentNode.SelectNodes(strXPath);
|
|
foreach(var item in lists)
|
|
{
|
|
var rows = item.SelectNodes(".//td");
|
|
if(rows.Count < 3)
|
|
continue;
|
|
|
|
string strTitle = rows[2].InnerText;
|
|
strTitle=strTitle.Trim();
|
|
string strTime = item.SelectSingleNode(".//td[contains(@class, 'cen_txt')]").InnerText;
|
|
strTime=strTime.Trim();
|
|
string strURL = rows[2].SelectSingleNode(".//a").GetAttributeValue("href", "");
|
|
strURL=strURL.Trim();
|
|
strURL =strServerURL+strURL;
|
|
|
|
if(Regex.IsMatch(strTime, @"\d+/\d+")==true)
|
|
{
|
|
//Console.WriteLine("어제 기사 : " + item.InnerHtml);
|
|
continue;
|
|
}
|
|
|
|
InsertItem(strTitle, "", "",
|
|
DateTime.ParseExact(strTime, "HH:mm", CultureInfo.CurrentCulture),
|
|
DateTime.Now,
|
|
strURL, "DART", timer.Elapsed.TotalMilliseconds, bInitial);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
Console.WriteLine(e.ToString());
|
|
}
|
|
|
|
return bHasNew;
|
|
}
|
|
|
|
bool ReadKIND(bool bInitial = false)
|
|
{
|
|
bool bHasNew = false;
|
|
|
|
try
|
|
{
|
|
//string strServerURL = "https://dart.fss.or.kr";
|
|
WebRequest request = WebRequest.Create("http://kind.krx.co.kr/disclosure/rsstodaydistribute.do?method=searchRssTodayDistribute&repIsuSrtCd=&mktTpCd=0&searchCorpName=¤tPageSize=1000");
|
|
request.Credentials=CredentialCache.DefaultCredentials;
|
|
request.Timeout=2000;
|
|
int iCDATALen = "<![CDATA[".Length;
|
|
|
|
System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
|
|
timer.Start();
|
|
|
|
using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
|
|
{
|
|
timer.Stop();
|
|
|
|
using(Stream dataStream = response.GetResponseStream())
|
|
{
|
|
using(StreamReader reader = new StreamReader(dataStream, Encoding.GetEncoding("utf-8")))
|
|
{
|
|
string responseFromServer = WebUtility.HtmlDecode(reader.ReadToEnd());
|
|
|
|
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
|
|
doc.LoadHtml(responseFromServer);
|
|
|
|
string strXPath = "//item";
|
|
var lists = doc.DocumentNode.SelectNodes(strXPath);
|
|
if(lists == null)
|
|
return false;
|
|
|
|
foreach(var item in lists)
|
|
{
|
|
string strTitle = item.SelectSingleNode(".//title").InnerText;
|
|
strTitle = strTitle.Substring(iCDATALen, strTitle.Length-iCDATALen-3);
|
|
string strTime = item.ChildNodes["pubDate"].InnerText;
|
|
DateTime time = Convert.ToDateTime(strTime);
|
|
strTime = time.ToString("HH:mm:ss");
|
|
string strURL = item.ChildNodes["link"].NextSibling.InnerText;
|
|
strURL = strURL.Substring(iCDATALen, strURL.Length-iCDATALen-3);
|
|
|
|
if(Regex.IsMatch(strTime, @"\d+/\d+")==true)
|
|
{
|
|
//Console.WriteLine("어제 기사 : " + item.InnerHtml);
|
|
continue;
|
|
}
|
|
|
|
InsertItem(strTitle, "", "",
|
|
DateTime.ParseExact(strTime, "HH:mm:ss", CultureInfo.CurrentCulture),
|
|
DateTime.Now,
|
|
strURL, "KIND", timer.Elapsed.TotalMilliseconds, bInitial);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
Console.WriteLine(e.ToString());
|
|
}
|
|
|
|
return bHasNew;
|
|
}
|
|
|
|
bool ReadEdaily(bool bInitial = false)
|
|
{
|
|
bool bHasNew = false;
|
|
|
|
try
|
|
{
|
|
string strServerURL = "http://www.edaily.co.kr/news/realtime/realtime_NewsRead.asp";
|
|
WebRequest request = WebRequest.Create("http://www.edaily.co.kr/news/realtime/realtime_NewsList_1.asp");
|
|
request.Credentials=CredentialCache.DefaultCredentials;
|
|
request.Timeout=2000;
|
|
|
|
DateTime PrevTime = DateTime.Now;
|
|
|
|
System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
|
|
timer.Start();
|
|
using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
|
|
{
|
|
timer.Stop();
|
|
using(Stream dataStream = response.GetResponseStream())
|
|
{
|
|
using(StreamReader reader = new StreamReader(dataStream, Encoding.GetEncoding("EUC-KR")))
|
|
{
|
|
string responseFromServer = WebUtility.HtmlDecode(reader.ReadToEnd());
|
|
|
|
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
|
|
doc.LoadHtml(responseFromServer);
|
|
string strXPath = "//li[contains(@id, 'NewsIcon')]";
|
|
var lists = doc.DocumentNode.SelectNodes(strXPath);
|
|
foreach(var item in lists)
|
|
{
|
|
string strTitle = item.SelectSingleNode(".//a").GetAttributeValue("title", "");
|
|
string strTime = item.SelectSingleNode(".//span").InnerText;
|
|
|
|
string strID = item.GetAttributeValue("id", "");
|
|
strID = strID.Substring("NewsIcon_".Length);
|
|
string strURL = strServerURL+"?newsid="+strID;
|
|
|
|
DateTime Time;
|
|
DateTime.TryParseExact(strTime, "HH:mm", CultureInfo.CurrentCulture, DateTimeStyles.None, out Time);
|
|
if(Time > PrevTime)
|
|
break;
|
|
PrevTime = Time;
|
|
|
|
InsertItem(strTitle, "", "", Time, DateTime.Now, strURL, "이데일리", timer.Elapsed.TotalMilliseconds, bInitial);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
Console.WriteLine(e.ToString());
|
|
}
|
|
|
|
return bHasNew;
|
|
}
|
|
|
|
bool ReadMoneyToday(bool bInitial = false)
|
|
{
|
|
bool bHasNew = false;
|
|
|
|
try
|
|
{
|
|
string strServerURL = "http://news.mt.co.kr/mtview.php?no=";
|
|
WebRequest request = WebRequest.Create("http://news.mt.co.kr/newsflash/newsflash.html");
|
|
request.Credentials=CredentialCache.DefaultCredentials;
|
|
request.Timeout=2000;
|
|
|
|
DateTime PrevTime = DateTime.Now;
|
|
|
|
System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
|
|
timer.Start();
|
|
|
|
using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
|
|
{
|
|
timer.Stop();
|
|
|
|
using(Stream dataStream = response.GetResponseStream())
|
|
{
|
|
using(StreamReader reader = new StreamReader(dataStream, Encoding.GetEncoding("EUC-KR")))
|
|
{
|
|
string responseFromServer = WebUtility.HtmlDecode(reader.ReadToEnd());
|
|
|
|
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
|
|
doc.LoadHtml(responseFromServer);
|
|
string strXPath = "//div[@id='articleList']//li[@class='bundle']";
|
|
|
|
var lists = doc.DocumentNode.SelectNodes(strXPath);
|
|
foreach(var item in lists)
|
|
{
|
|
string strTitle = item.SelectSingleNode(".//a").InnerText;
|
|
string strTime = item.SelectSingleNode(".//span").InnerText;
|
|
|
|
string strID = item.SelectSingleNode(".//a").GetAttributeValue("href", "");
|
|
int iStart = strID.IndexOf('\'', 0);
|
|
iStart = strID.IndexOf('\'', iStart+1);
|
|
iStart = strID.IndexOf('\'', iStart+1);
|
|
int iEnd = strID.IndexOf('\'', iStart+1);
|
|
strID = strID.Substring(iStart+1, iEnd-iStart+1);
|
|
string strURL = strServerURL+strID;
|
|
|
|
DateTime Time;
|
|
DateTime.TryParseExact(strTime, "HH:mm", CultureInfo.CurrentCulture, DateTimeStyles.None, out Time);
|
|
if(Time > PrevTime)
|
|
break;
|
|
PrevTime = Time;
|
|
|
|
InsertItem(strTitle, "", "", Time, DateTime.Now, strURL, "머니투데이", timer.Elapsed.TotalMilliseconds, bInitial);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
Console.WriteLine(e.ToString());
|
|
}
|
|
|
|
return bHasNew;
|
|
}
|
|
|
|
bool ReadFinacialNews(bool bInitial = false)
|
|
{
|
|
bool bHasNew = false;
|
|
|
|
try
|
|
{
|
|
string strServerURL = "http://www.fnnews.com/news/";
|
|
WebRequest request = WebRequest.Create("http://www.fnnews.com/newsflash/today/data?type=json");
|
|
request.Credentials=CredentialCache.DefaultCredentials;
|
|
request.Timeout=2000;
|
|
|
|
DateTime Today = DateTime.Now;
|
|
|
|
System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
|
|
timer.Start();
|
|
|
|
using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
|
|
{
|
|
timer.Stop();
|
|
|
|
using(Stream dataStream = response.GetResponseStream())
|
|
{
|
|
using(StreamReader reader = new StreamReader(dataStream, Encoding.GetEncoding("UTF-8")))
|
|
{
|
|
string responseFromServer = WebUtility.HtmlDecode(reader.ReadToEnd());
|
|
|
|
dynamic jObj = Newtonsoft.Json.JsonConvert.DeserializeObject(responseFromServer);
|
|
foreach(var data in jObj)
|
|
{
|
|
string strTitle = data["title"];
|
|
string strTime = data["date"];
|
|
DateTime Time;
|
|
DateTime.TryParseExact(strTime, "yyyy.MM.dd HH:mm", CultureInfo.CurrentCulture, DateTimeStyles.None, out Time);
|
|
|
|
string strCode = data["code"];
|
|
string strURL = strServerURL+strCode;
|
|
|
|
if(Time.DayOfYear == Today.DayOfYear)
|
|
InsertItem(strTitle, "", "", Time, DateTime.Now, strURL, "파이낸셜뉴스", timer.Elapsed.TotalMilliseconds, bInitial);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
Console.WriteLine(e.ToString());
|
|
}
|
|
|
|
return bHasNew;
|
|
}
|
|
|
|
private void UpdateBrowser()
|
|
{
|
|
if(lvList.InvokeRequired == true)
|
|
{
|
|
lvList.Invoke(new Action(UpdateBrowser));
|
|
}
|
|
else
|
|
{
|
|
if(chAutoSelect.Checked == true && m_bBrowserReload == true)
|
|
{
|
|
if(lvList.SelectedItems.Count == 0 || lvList.SelectedItems[0].Index != lvList.Items.Count-1)
|
|
{
|
|
lvList.Items[lvList.Items.Count - 1].Selected = true;
|
|
lvList.Select();
|
|
if(lvList.SelectedItems.Count > 0)
|
|
lvList.SelectedItems[0].EnsureVisible();
|
|
}
|
|
|
|
m_bBrowserReload = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CrawlTimer_Tick(object sender, EventArgs e)
|
|
{
|
|
m_CrawlTimer.Enabled = false;
|
|
|
|
//Console.WriteLine(string.Format("timer thread {0}", System.Threading.Thread.CurrentThread.ManagedThreadId.ToString()));
|
|
|
|
if(chAutoReload.Checked == true)
|
|
{
|
|
ReadKIND();
|
|
ReadDart();
|
|
ReadAsiaE();
|
|
ReadEtoday();
|
|
ReadEToday2();
|
|
ReadEdaily();
|
|
ReadMoneyToday();
|
|
ReadFinacialNews();
|
|
}
|
|
|
|
UpdateBrowser();
|
|
|
|
m_CrawlTimer.Interval = m_iCrawlInterval;
|
|
m_CrawlTimer.Enabled = true;
|
|
}
|
|
|
|
private void UpdateStartPrice(int iID, int iPrice)
|
|
{
|
|
if(lvList.InvokeRequired)
|
|
{
|
|
lvList.BeginInvoke((MethodInvoker)delegate ()
|
|
{
|
|
ListViewItem item = lvList.Items.Cast<ListViewItem>().FirstOrDefault(s => s.SubItems[chId.Index].Text == iID.ToString());
|
|
item.SubItems[chPriceS.Index].Text = iPrice.ToString("n0");
|
|
});
|
|
}
|
|
else
|
|
{
|
|
ListViewItem item = lvList.Items.Cast<ListViewItem>().FirstOrDefault(s => s.SubItems[chId.Index].Text == iID.ToString());
|
|
item.SubItems[chPriceS.Index].Text = iPrice.ToString("n0");
|
|
}
|
|
}
|
|
|
|
private void UpdateLowHighPrice(int iID, int iPriceStart, int iPriceLow, int iPriceHigh)
|
|
{
|
|
if(lvList.InvokeRequired)
|
|
{
|
|
lvList.BeginInvoke((MethodInvoker)delegate ()
|
|
{
|
|
ListViewItem item = lvList.Items.Cast<ListViewItem>().FirstOrDefault(s => s.SubItems[chId.Index].Text == iID.ToString());
|
|
item.SubItems[chPriceLow.Index].Text = string.Format("{0:n0}({1:n}%)", iPriceLow, iPriceLow/(float)iPriceStart);
|
|
item.SubItems[chPriceHigh.Index].Text = string.Format("{0:0}({1:n}%)", iPriceHigh, iPriceHigh/(float)iPriceStart);
|
|
});
|
|
}
|
|
else
|
|
{
|
|
ListViewItem item = lvList.Items.Cast<ListViewItem>().FirstOrDefault(s => s.SubItems[chId.Index].Text == iID.ToString());
|
|
item.SubItems[chPriceLow.Index].Text = string.Format("{0:n0}({1:n}%)", iPriceLow, iPriceLow/(float)iPriceStart);
|
|
item.SubItems[chPriceHigh.Index].Text = string.Format("{0:0}({1:n}%)", iPriceHigh, iPriceHigh/(float)iPriceStart);
|
|
}
|
|
}
|
|
|
|
private void PriceCheckTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
|
|
{
|
|
m_PriceCheckTimer.Enabled = false;
|
|
|
|
DateTime CurTime = DateTime.Now;
|
|
foreach(PRICE_CHECK_DATA data in m_PriceCheckList)
|
|
{
|
|
if(data.m_iPriceStart == 0)
|
|
{
|
|
data.m_iPriceStart = m_CybosHelper.GetCurPrice(data.m_Code);
|
|
UpdateStartPrice(data.m_iID, data.m_iPriceStart);
|
|
}
|
|
else if(data.m_iPriceHigh == 0 && (CurTime - data.m_StartTime).Minutes >= 1)
|
|
{
|
|
m_CybosHelper.GetLowHighPrice(data.m_Code, data.m_StartTime, 5, out data.m_iPriceLow, out data.m_iPriceHigh);
|
|
if(data.m_iPriceHigh > 0)
|
|
UpdateLowHighPrice(data.m_iID, data.m_iPriceStart, data.m_iPriceLow, data.m_iPriceHigh);
|
|
}
|
|
}
|
|
|
|
while(m_PriceCheckList.Count > 0)
|
|
{
|
|
PRICE_CHECK_DATA data;
|
|
if(m_PriceCheckList.TryPeek(out data) == false)
|
|
break;
|
|
|
|
if(data.m_iPriceHigh == 0)
|
|
break;
|
|
|
|
m_PriceCheckList.TryDequeue(out data);
|
|
}
|
|
|
|
|
|
m_PriceCheckTimer.Enabled = true;
|
|
}
|
|
|
|
private void lvList_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
if(lvList.SelectedItems.Count <= 0)
|
|
return;
|
|
|
|
string strURL = lvList.SelectedItems[0].SubItems[chLink.Index].Text;
|
|
wbView.ScriptErrorsSuppressed = true;
|
|
//wbView.Navigate(strURL);
|
|
}
|
|
|
|
private void tbInterval_KeyPress(object sender, KeyPressEventArgs e)
|
|
{
|
|
if(e.KeyChar == Convert.ToChar(Keys.Enter))
|
|
{
|
|
m_iCrawlInterval = (int)(float.Parse(Regex.Replace(tbInterval.Text, @"\D\.", "")) * 1000);
|
|
if(m_iCrawlInterval < 1)
|
|
m_iCrawlInterval = 500;
|
|
|
|
tbInterval.Text = (m_iCrawlInterval / (float)1000).ToString("##0.0") + "초";
|
|
}
|
|
}
|
|
|
|
private void lvList_ColumnClick(object sender, ColumnClickEventArgs e)
|
|
{
|
|
SortOrder Order = (lvList.Sorting == SortOrder.Descending || lvList.Sorting == SortOrder.None) ? SortOrder.Ascending : SortOrder.Descending;
|
|
|
|
lvList.ListViewItemSorter = new ListViewItemComparer(e.Column, Order);
|
|
lvList.Sorting = Order;
|
|
lvList.Sort();
|
|
}
|
|
|
|
private void btnConfig_Click(object sender, EventArgs e)
|
|
{
|
|
if(m_ConfigForm == null)
|
|
m_ConfigForm = new ConfigForm(this);
|
|
|
|
FormCollection OpenForms = Application.OpenForms;
|
|
bool bOpen = false;
|
|
foreach(Form form in OpenForms)
|
|
{
|
|
if(form == m_ConfigForm)
|
|
{
|
|
bOpen = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(bOpen == false)
|
|
{
|
|
m_ConfigForm.Show();
|
|
}
|
|
else
|
|
{
|
|
m_ConfigForm.BringToFront();
|
|
}
|
|
}
|
|
|
|
public void OnConfigFormClosing()
|
|
{
|
|
m_ConfigForm = null;
|
|
}
|
|
|
|
public void OnManualCodeClick(int iPrice)
|
|
{
|
|
m_CodeList.MakeManualList(iPrice);
|
|
}
|
|
|
|
public void ApplyDenialCode()
|
|
{
|
|
m_CodeList.LoadDenialList();
|
|
}
|
|
public void ApplyDuplicatedCode()
|
|
{
|
|
m_CodeList.LoadDuplicatedList();
|
|
}
|
|
|
|
public void ApplyPositive()
|
|
{
|
|
m_Condition.LoadPositive();
|
|
}
|
|
|
|
public void ApplyManual()
|
|
{
|
|
m_Condition.LoadManual();
|
|
}
|
|
|
|
public void ApplyNegative()
|
|
{
|
|
m_Condition.LoadNegative();
|
|
}
|
|
|
|
public void ApplySynonym()
|
|
{
|
|
m_CodeList.LoadSynonym();
|
|
}
|
|
|
|
private void NewsForm_FormClosing(object sender, FormClosingEventArgs e)
|
|
{
|
|
Util.Clear();
|
|
}
|
|
|
|
private void chBuy_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
m_bBuy = chBuy.Checked;
|
|
|
|
if(m_bBuy == true && Config.GetAccount() == "")
|
|
{
|
|
chBuy.Checked = false;
|
|
MessageBox.Show("계좌를 선택해주시기 바랍니다");
|
|
return;
|
|
}
|
|
|
|
if(m_bBuy == true)
|
|
Util.Log(Util.LOG_TYPE.VERVOSE, "매수 시작");
|
|
else
|
|
Util.Log(Util.LOG_TYPE.VERVOSE, "매수 취소");
|
|
}
|
|
|
|
public string[] GetAccounts()
|
|
{
|
|
return m_CybosHelper.GetAccounts();
|
|
}
|
|
|
|
public void ApplyAccount(string strAccount, string strAccountSub)
|
|
{
|
|
Config.SetAccount(strAccount, strAccountSub);
|
|
}
|
|
}
|
|
|
|
|
|
class ListViewItemComparer : IComparer
|
|
{
|
|
int m_iColumn = 0;
|
|
SortOrder m_Order = SortOrder.Ascending;
|
|
|
|
public ListViewItemComparer(int column, SortOrder Order)
|
|
{
|
|
m_iColumn = column;
|
|
m_Order = Order;
|
|
}
|
|
|
|
public int Compare(object x, object y)
|
|
{
|
|
ListViewItem item1 = (ListViewItem)x;
|
|
ListViewItem item2 = (ListViewItem)y;
|
|
|
|
double num1;
|
|
double num2;
|
|
if(double.TryParse(item1.SubItems[m_iColumn].Text, out num1) &&
|
|
double.TryParse(item2.SubItems[m_iColumn].Text, out num2))
|
|
{
|
|
return (num1>num2)?1:-1;
|
|
}
|
|
else
|
|
{
|
|
if(m_Order == SortOrder.Ascending)
|
|
return string.Compare(item1.SubItems[m_iColumn].Text, item2.SubItems[m_iColumn].Text);
|
|
else
|
|
return string.Compare(item2.SubItems[m_iColumn].Text, item1.SubItems[m_iColumn].Text);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|