using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using RealTimeNews;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Net.Sockets;
using System.Security.Policy;
using System.Windows.Forms;
namespace RealTimeNews
{
public partial class Crawler : Form
{
string date = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
ChromeDriver driver;
bool Changed = false;
List<string> New_Paticle = new List<string>();
List<string> Changed_data = new List<string>();
string Last_Paticle = string.Empty;
Timer timer = new Timer();
string url = "https://www.daishin.com/g.ds?m=1073&p=2062&v=1442";
string Element = "/html/body/div[2]/div[7]/div/div[2]/div[1]/ul/li/a";
public Crawler()
{
InitializeComponent();
this.DoubleBuffered = true;
}
private void Crawler_Load(object sender, EventArgs e)
{
Getdriver();
var headline = GetNewsData();
addtitle(headline);
Crawler_refreshing();
}
private void Crawler_refreshing()
{
timer.Interval = 7000; //주기 설정
timer.Tick += new EventHandler(titmer_tick); //주기마다 실행되는 이벤트 등록
timer.Start();
}
private void titmer_tick(object sender, EventArgs e)
{
var headline = refresh_News();
if (Changed == true) // 변경된 데이터가 있다면
{
addtitle(headline); // 데이터 추가
Changed = false;
}
else
{
return;
}
}
private void Getdriver()
{
ChromeOptions options = new ChromeOptions();
ChromeDriverService driverService = ChromeDriverService.CreateDefaultService();
driverService.HideCommandPromptWindow = true;
options.AddArgument("--headless");
driver = new ChromeDriver(driverService, options);
driver.Url = url;
}
private List<string> GetNewsData()
{
string Title = string.Empty;
// 대신증권 뉴스페이지는 만약 이미지가 있는 기사를 선택했다면 이미지와 같이볼건지 묻는 팝업을 띄운다
// 팝업을 무시하는 구문이다
try
{
var alert = driver.SwitchTo().Alert(); // driver가 Alert 팝업을 선택
alert.Dismiss(); // 취소
}
catch (NoAlertPresentException)
{
}
var headline = driver.FindElementsByXPath(Element); // 기사 페이지에있는 전체 헤드라인들을 불러온다
for (int i = 0; i < headline.Count; i++)
{
// 공백을 무시
if (headline[i].Text == "")
{
}
else
{
// 대신증권 제목 특성상 문자열 가공
char[] delimiter = { ',' };
OpenQA.Selenium.IWebElement k = headline[i];
var RawTitle = k.GetAttribute("onclick");
RawTitle.Remove(8);
var processTitle = RawTitle.Split(delimiter);
if (processTitle[6].Contains("방금") || processTitle[6].Contains("분전"))
{
Title = processTitle[5];
}
else
{
Title = processTitle[5] + processTitle[6];
}
New_Paticle.Add(Title);
}
}
Last_Paticle = New_Paticle[0]; // 가장 최신 데이터를 설정하여 새로고침할때 참고한다.
// DataGridview의 특성은 가장 하단의 셀에 최신데이터가 추가된다.
// List 특성상 가장 최근데이터가 먼저 추가되기때문에 List상에는 가장 먼저들어온 데이터가 가장 뒤에있는 현상이 일어난다.
// 그러므로 DataGridview에 추가할때 가장 최근데이터가 가장 늦게 들어가는 현상이 일어난다.
// 최신데이터를 DataGridveiw에서 가장 아래쪽에 배치하기위해서(DataGridview에 특성은 하단 셀이 최근의 추가된 데이터) 추가된 List를 Reverse(반대) 시킨다.
New_Paticle.Reverse();
return New_Paticle;
}
private List<string> refresh_News()
{
string Title = string.Empty;
driver.Navigate().Refresh();
try
{
// 페이지에 뜨는 팝업 창 닫기
var alert = driver.SwitchTo().Alert();
alert.Dismiss();
}
catch (NoAlertPresentException)
{
}
var headline = driver.FindElementsByXPath(Element);
New_Paticle.Clear();
for (int i = 0; i < headline.Count; i++)
{
if (headline[i].Text == "") // 네이버 기사특성상 공백이 같이오기때문에 공백을 무시
{
}
else
{
char[] delimiter = { ',' };
IWebElement k = headline[i];
// 대신증권 기사 제목 특성을 감안해 문자열 가공
var RawTitle = k.GetAttribute("onclick");
RawTitle.Remove(8);
var processTitle = RawTitle.Split(delimiter);
if (processTitle[6].Contains("방금") || processTitle[6].Contains("분전"))
{
Title = processTitle[5];
}
else
{
Title = processTitle[5] + processTitle[6];
}
New_Paticle.Add(Title);
}
}
if (New_Paticle.IndexOf(Last_Paticle) != 0 && New_Paticle.IndexOf(Last_Paticle) != -1) // 데이터가 존재하고 변동이 있다면
{
Changed = true;
Changed_data.Clear();
int Last_Paticle_li_Number = New_Paticle.IndexOf(Last_Paticle);
for (int i = Last_Paticle_li_Number - 1; i >= 0; i--)
{
Changed_data.Add(New_Paticle[i]);
}
Last_Paticle = Changed_data[Changed_data.Count - 1]; // 최신 기사로 바꾼다.
return Changed_data;
}
else if (New_Paticle.IndexOf(Last_Paticle) == -1) // 기사가 삭제되거나 수정되면 다시 실행(제일 큰 문제..)
{
Debug.WriteLine("데이터가 존재하지않습니다. 프로그램을 재시작합니다.");
Changed = false;
timer.Stop();
Crawler_Load(null, null); // 재시작
}
else if (New_Paticle.IndexOf(Last_Paticle) == 0) // 데이터가 변동이 없다면
{
Changed = false;
}
return New_Paticle;
}
public void addtitle(List<string> Paticle)
{
Debug.WriteLine("값 추가");
var title = Paticle.ToArray();
var key = keyword();
for (int i = 0; i < title.Length; i++)
{
RawNews.Rows.Add(title[i]);
foreach (string x in key)
{
// 제목에 아래 keyword 함수에 추가해놓은 단어가 하나라도 있다면 알림을 띄우고 ClassificationNews로 분류한다.
if (title[i].Contains(x))
{
ClassificationNews.Rows.Add(title[i]);
notification(title[i], title[i]);
Debug.WriteLine(title[i]);
break;
}
}
}
}
public void notification(string Text, string Title)
{
var notification = new NotifyIcon()
{
Visible = true,
Icon = System.Drawing.SystemIcons.Information,
BalloonTipText = Text,
BalloonTipTitle = Title,
};
notification.ShowBalloonTip(10000);
}
public List<string> keyword()
{
List<string> keyword = new List<string>();
keyword.Add("체결");
keyword.Add("수주");
keyword.Add("승인");
keyword.Add("FDA");
keyword.Add("계약");
keyword.Add("개발");
keyword.Add("임상");
keyword.Add("수출");
keyword.Add("공급");
keyword.Add("허가");
keyword.Add("납품");
keyword.Add("증자");
keyword.Add("치료제");
keyword.Add("인수");
keyword.Add("취득");
keyword.Add("합병");
keyword.Add("정부");
keyword.Add("특허");
keyword.Add("진단키트");
keyword.Add("공시");
keyword.Add("정부지원");
return keyword;
}
private void Crawler_FormClosed(object sender, FormClosedEventArgs e)
{
Process[] chromeDriverProcesses = Process.GetProcessesByName("chromedriver");
foreach (var chromeDriverProcess in chromeDriverProcesses)
{
chromeDriverProcess.Kill();
}
}