반응형
개요
차세대 나라장터 크롤링하여 메일로 발송하는 C# 코드입니다.
소스 길이가 길어 이번 글에는 코드만 공유하고 다음장에 C# 개발 환경에 대해 설명 드리겠습니다.
아래 파일을 다운받아 압축을 풀면 코드가 있습니다.
g2b_simple.zip
18.54MB
g2b_simple.z01
19.53MB
g2b_simple.z02
19.53MB
g2b_simple.z03
19.53MB
g2b_simple.z04
19.53MB
코드 내용
메인폼(FormG2B.cs)
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using OpenQA.Selenium;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WebDriverManager;
using WebDriverManager.DriverConfigs.Impl;
using System.Diagnostics;
using System.IO;
using OpenQA.Selenium.Interactions;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TaskbarClock;
using System.Net;
using System.Net.Mail;
using AngleSharp.Dom;
using System.Data.SQLite;
using AngleSharp.Common;
using WebDriverManager.Helpers;
namespace g2b
{
public partial class FormG2B : Form
{
IWebDriver driver;
readonly CommonSQL cs = new CommonSQL();
MailForm mailForm;
private string smtp = "test@test.co.kr";
private string sendPassword = "";
string cr = System.Environment.NewLine;
bool isDebug = false; // 디버그 모드 여부
public FormG2B()
{
InitializeComponent();
// 창의 크기를 전체크기로 설정
this.Size = new System.Drawing.Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height - 38);
this.Cursor = Cursors.Hand;
contextMenuStripMainForm.Cursor = Cursors.Hand;
this.notifyIconMainForm.ContextMenuStrip = contextMenuStripMainForm; // NotifyIcon에 ContextMenuStrip 설정
this.notifyIconMainForm.Visible = true;//Tray 보이기 속성
toolStripMenuItemClose.Click += new EventHandler(CloseApp);
toolStripMenuItemHide.Click += new EventHandler(HideForm);
#if DEBUG
isDebug = true; // 디버그 모드 활성화
#else
isDebug = false; // 프로덕션 모드 활성화
#endif
if (isDebug)
{
textBoxLog.AppendText("디버그 모드로 실행 중입니다." + cr);
textBoxLog.AppendText("크롬창 및 크롬드라이버가 모두 닫힙니다." + cr);
foreach (Process process in Process.GetProcesses()) // 프로세스 목록들 모두에 대해
{
if (process.ProcessName.StartsWith("chrome"))
{
process.Kill(); // 그 프로세스를 강제 종료
}
}
}
else
{
//textBoxLog.AppendText("프로덕션 모드로 실행 중입니다." + cr);
}
// Chrome 폴더 삭제
try
{
string chromeDir = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Chrome");
if (Directory.Exists(chromeDir))
{
Directory.Delete(chromeDir, true); // 하위 폴더/파일까지 모두 삭제
// 필요시 로그 출력
// textBoxLog.AppendText("Chrome 폴더 삭제 완료" + cr);
}
}
catch (Exception ex)
{
// 삭제 실패 시 로그 출력
textBoxLog.AppendText("Chrome 폴더 삭제 실패: " + ex.Message + cr);
}
GetBaseInfo();
/*
//초기 설정
textBoxBizNm.Text = "비점오염"; //테스트 중에만 사용
comboBoxRunTM.SelectedItem = "17"; //17시 실행 기본값 설정
listViewEmail.Items.Add("dhhan@neobrix.co.kr");
*/
checkedListBoxBizType.SetItemChecked(2, true); // 일반용역 기본값 설정
// 창의 시작 위치를 (0, 0) 좌표로 설정
this.Location = new System.Drawing.Point(0, 0);
}
private void GetBaseInfo()
{
cs.InitDB();
// 메일 발송 정보 가져오기
string sql = "select fromUser, pw from mailAuth";
SQLiteDataReader sdr = cs.SelectSql(sql);
while (sdr.Read())
{
smtp = sdr["fromUser"].ToString();
sendPassword = sdr["pw"].ToString();
//textBoxLog.AppendText($"메일 발송 정보: {smtp}, {sendPassword}" + cr);
}
sdr.Close();
// 메일 수신자 정보 가져오기
sql = "select email from mailTarget";
sdr = cs.SelectSql(sql);
while (sdr.Read())
{
listViewEmail.Items.Add(sdr["email"].ToString());
//textBoxLog.AppendText($"메일 수신자: {sdr["email"].ToString()}" + cr);
}
sdr.Close();
// 검색어 정보 가져오기
sql = "select word from searchWord";
sdr = cs.SelectSql(sql);
while (sdr.Read())
{
textBoxBizNm.Text = sdr["word"].ToString();
//textBoxLog.AppendText($"검색어: {sdr["word"].ToString()}" + cr);
}
sdr.Close();
// 발송 시간 정보 가져오기
sql = "select time from sendTime";
sdr = cs.SelectSql(sql);
while (sdr.Read())
{
comboBoxRunTM.SelectedItem = sdr["time"].ToString();
//textBoxLog.AppendText($"발송 시간: {sdr["time"].ToString()}" + cr);
}
}
/* 크롬 드라이버 업데이트 및 초기화 설정
*/
public void InitSelenium()
{
try
{
// Chrome 버전 확인
string chromeVersion = GetChromeVersion();
textBoxLog.AppendText($"Chrome 버전: {chromeVersion}" + cr);
// ChromeDriver 설정
try
{
var driverManager = new DriverManager();
//driverManager.SetUpDriver(new ChromeConfig(), chromeVersion);
driverManager.SetUpDriver(new ChromeConfig(), VersionResolveStrategy.MatchingBrowser);
textBoxLog.AppendText("ChromeDriver 설정 완료" + cr);
}
catch (Exception ex)
{
textBoxLog.AppendText($"ChromeDriver 자동 설정 실패: {ex.Message}" + cr);
textBoxLog.AppendText("기본 ChromeDriver 사용" + cr);
}
// Chrome 옵션 설정
ChromeOptions options = new ChromeOptions();
if(isDebug)
{
//options.AddArgument("--headless=new"); // 헤드리스 모드 제거
}
else
{
//options.AddArgument("headless"); // 헤드리스
}
options.AddArgument("--disable-blink-features=AutomationControlled");
options.AddArgument("--disable-notifications");
options.AddArgument("--start-maximized");
options.AddArgument("--no-sandbox");
options.AddArgument("--disable-dev-shm-usage");
options.AddArgument("--disable-gpu");
options.AddArgument("--disable-extensions");
options.AddArgument("--disable-popup-blocking");
options.AddArgument("--disable-infobars");
options.AddArgument("--disable-web-security");
options.AddArgument("--disable-features=IsolateOrigins,site-per-process");
options.AddArgument("--disable-site-isolation-trials");
options.AddArgument("--dns-prefetch-disable");
options.AddArgument("--disable-application-cache");
options.AddArgument("--disable-cache");
options.AddArgument("--disable-offline-load-stale-cache");
options.AddArgument("--disk-cache-size=0");
options.AddArgument("--ignore-certificate-errors");
options.AddArgument("--allow-running-insecure-content");
options.PageLoadStrategy = PageLoadStrategy.Normal;
options.AddExcludedArgument("enable-automation");
options.AddAdditionalOption("useAutomationExtension", false);
options.AddArgument($"--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/{chromeVersion} Safari/537.36");
// ChromeDriver 초기화
if (driver != null)
{
try
{
driver.Quit();
}
catch { }
driver.Dispose();
}
ChromeDriverService driverService = ChromeDriverService.CreateDefaultService();
driverService.HideCommandPromptWindow = true; // 콘솔 창 숨기기
driver = new ChromeDriver(driverService, options);
textBoxLog.AppendText("ChromeDriver 초기화 완료" + cr);
}
catch(Exception ex)
{
textBoxLog.AppendText("InitSelenium" + cr);
textBoxLog.AppendText($"에러 발생: {ex.Message}" + cr);
if (driver != null)
{
try
{
driver.Quit();
}
catch { }
driver.Dispose();
driver = null;
}
throw;
}
}
/* Chrome 버전 확인
*/
private string GetChromeVersion()
{
try
{
string[] possiblePaths = new string[]
{
@"C:\Program Files\Google\Chrome\Application\chrome.exe",
@"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe",
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\Google\Chrome\Application\chrome.exe"
};
foreach (string chromePath in possiblePaths)
{
if (File.Exists(chromePath))
{
var versionInfo = FileVersionInfo.GetVersionInfo(chromePath);
string version = versionInfo.FileVersion;
textBoxLog.AppendText("Chrome version : " + version);
if (!string.IsNullOrEmpty(version))
{
// 버전 번호에서 마지막 부분만 사용 (예: 136.0.7049.115 -> 136)
return version.Split('.')[0];
}
}
}
}
catch (Exception ex)
{
textBoxLog.AppendText("GetChromeVersion" + cr);
textBoxLog.AppendText($"Chrome 버전 확인 중 에러: {ex.Message}" + cr);
}
return "136"; // 기본값 설정
}
/* 크롤링 시작(발주 및 사전규격)
*/
public void Run()
{
try
{
// 타임아웃 설정
driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(120);
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(30);
driver.Manage().Timeouts().AsynchronousJavaScript = TimeSpan.FromSeconds(30);
// 웹사이트 접속 시도
int maxRetries = 5; // 재시도 횟수 증가
int currentTry = 0;
bool connected = false;
while (!connected && currentTry < maxRetries)
{
try
{
// 연결 전 대기 시간 증가
System.Threading.Thread.Sleep(5000);
textBoxLog.AppendText($"접속 시도 {currentTry + 1}/{maxRetries}" + cr);
// URL 접속
driver.Navigate().GoToUrl("https://www.g2b.go.kr");
// 페이지 로드 완료 확인을 위한 대기
WebDriverWait pageLoadWait = new WebDriverWait(driver, TimeSpan.FromSeconds(180));
// 1. document.readyState 확인
pageLoadWait.Until(driver => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));
// 2. jQuery 로드 완료 확인 (jQuery가 있는 경우)
try
{
pageLoadWait.Until(driver => ((IJavaScriptExecutor)driver).ExecuteScript("return (typeof jQuery !== 'undefined') && jQuery.active === 0"));
}
catch
{
textBoxLog.AppendText("jQuery 로드 확인 실패 (무시됨)" + cr);
}
// 3. 네트워크 요청 완료 확인
try
{
pageLoadWait.Until(driver => ((IJavaScriptExecutor)driver).ExecuteScript(@"
return new Promise((resolve) => {
if (window.performance && window.performance.getEntriesByType) {
const resources = window.performance.getEntriesByType('resource');
const pending = resources.filter(r => !r.responseEnd);
resolve(pending.length === 0);
} else {
resolve(true);
}
});
"));
}
catch
{
textBoxLog.AppendText("네트워크 요청 확인 실패 (무시됨)" + cr);
}
// 4. 페이지 로드 이벤트 확인
try
{
pageLoadWait.Until(driver => ((IJavaScriptExecutor)driver).ExecuteScript(@"
return new Promise((resolve) => {
if (document.readyState === 'complete') {
resolve(true);
} else {
window.addEventListener('load', () => resolve(true));
}
});
"));
}
catch
{
textBoxLog.AppendText("페이지 로드 이벤트 확인 실패 (무시됨)" + cr);
}
// 5. 특정 요소 존재 확인 (예: body)
pageLoadWait.Until(driver => driver.FindElement(By.TagName("body")).Displayed);
textBoxLog.AppendText("페이지 로드 완료 확인됨" + cr);
// 추가 대기
System.Threading.Thread.Sleep(3000);
connected = true;
textBoxLog.AppendText("드라이버 연결 성공" + cr);
}
catch (Exception ex)
{
currentTry++;
textBoxLog.AppendText($"연결 시도 {currentTry}/{maxRetries} 실패: {ex.Message}" + cr);
if (currentTry < maxRetries)
{
System.Threading.Thread.Sleep(15000); // 대기 시간 증가
try
{
driver.Navigate().Refresh();
System.Threading.Thread.Sleep(5000); // 새로고침 후 대기
}
catch { }
}
}
}
if (!connected)
{
textBoxLog.AppendText("최대 재시도 횟수를 초과했습니다." + cr);
CloseDriver();
throw new Exception("최대 재시도 횟수를 초과했습니다.");
}
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(120));
wait.IgnoreExceptionTypes(typeof(StaleElementReferenceException));
wait.IgnoreExceptionTypes(typeof(NoSuchElementException));
// 발주정보 바로가기
textBoxLog.AppendText("발주 메뉴 클릭 시도" + cr);
// 발주 메뉴 찾기 및 클릭
try
{
// 먼저 "발주" 메뉴 찾기
IWebElement parentMenu = null;
string[] parentSelectors = new string[]
{
"ID: mf_wfm_gnb_wfm_gnbMenu_genDepth1_0_btn_menuLvl1_span",
"XPath: //span[@id='mf_wfm_gnb_wfm_gnbMenu_genDepth1_0_btn_menuLvl1_span']",
"XPath: //span[contains(@class, 'w2textbox') and contains(text(), '발주')]",
"CSS: span#mf_wfm_gnb_wfm_gnbMenu_genDepth1_0_btn_menuLvl1_span"
};
foreach (string selector in parentSelectors)
{
try
{
textBoxLog.AppendText($"상위 메뉴 {selector} 시도 중..." + cr);
if (selector.StartsWith("ID:"))
{
string id = selector.Substring(4).Trim();
parentMenu = wait.Until(d => d.FindElement(By.Id(id)));
}
else if (selector.StartsWith("XPath:"))
{
string xpath = selector.Substring(7).Trim();
parentMenu = wait.Until(d => d.FindElement(By.XPath(xpath)));
}
else if (selector.StartsWith("CSS:"))
{
string css = selector.Substring(5).Trim();
parentMenu = wait.Until(d => d.FindElement(By.CssSelector(css)));
}
if (parentMenu != null && parentMenu.Displayed && parentMenu.Enabled)
{
textBoxLog.AppendText($"상위 메뉴 {selector} 찾기 성공" + cr);
break;
}
}
catch (Exception ex)
{
textBoxLog.AppendText($"상위 메뉴 {selector} 시도 실패: {ex.Message}" + cr);
parentMenu = null;
}
}
if (parentMenu == null)
{
textBoxLog.AppendText("발주 상위 메뉴를 찾을 수 없습니다.");
CloseDriver();
throw new Exception("발주 상위 메뉴를 찾을 수 없습니다.");
}
// 상위 메뉴에 마우스 오버
try
{
// 요소가 보이도록 스크롤
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].scrollIntoView(true);", parentMenu);
System.Threading.Thread.Sleep(1000);
// Actions를 사용하여 마우스 오버
new Actions(driver)
.MoveToElement(parentMenu)
.Perform();
textBoxLog.AppendText("발주 메뉴 마우스 오버 성공" + cr);
// 하위 메뉴가 나타날 때까지 대기
System.Threading.Thread.Sleep(2000);
}
catch (Exception ex)
{
textBoxLog.AppendText($"마우스 오버 실패: {ex.Message}" + cr);
CloseDriver();
throw;
}
// 하위 메뉴 찾기 및 클릭
IWebElement orderMenu = null;
string[] subMenuSelectors = new string[]
{
"ID: mf_wfm_gnb_wfm_gnbMenu_genDepth1_0_genDepth2_0_btn_menuLvl2",
"XPath: //a[@id='mf_wfm_gnb_wfm_gnbMenu_genDepth1_0_genDepth2_0_btn_menuLvl2']",
"XPath: //a[contains(@class, 'w2group') and .//span[contains(text(), '발주목록')]]",
"CSS: a.w2group.w2trigger_anchor.btn.depth2.depth-last",
"CSS: a#mf_wfm_gnb_wfm_gnbMenu_genDepth1_0_genDepth2_0_btn_menuLvl2"
};
foreach (string selector in subMenuSelectors)
{
try
{
textBoxLog.AppendText($"하위 메뉴 {selector} 시도 중..." + cr);
if (selector.StartsWith("ID:"))
{
string id = selector.Substring(4).Trim();
orderMenu = wait.Until(d => d.FindElement(By.Id(id)));
}
else if (selector.StartsWith("XPath:"))
{
string xpath = selector.Substring(7).Trim();
orderMenu = wait.Until(d => d.FindElement(By.XPath(xpath)));
}
else if (selector.StartsWith("CSS:"))
{
string css = selector.Substring(5).Trim();
orderMenu = wait.Until(d => d.FindElement(By.CssSelector(css)));
}
if (orderMenu != null)
{
// 요소가 클릭 가능해질 때까지 대기
wait.Until(d =>
{
try
{
return orderMenu.Displayed &&
orderMenu.Enabled &&
!orderMenu.GetAttribute("class").Contains("disabled");
}
catch
{
return false;
}
});
textBoxLog.AppendText($"하위 메뉴 {selector} 찾기 성공, 클릭 시도" + cr);
// 여러 클릭 방법 시도
bool clicked = false;
Exception lastException = null;
// 1. Actions 클릭 시도 (마우스 이동 후 클릭)
try
{
new Actions(driver)
.MoveToElement(orderMenu)
.Click()
.Perform();
clicked = true;
textBoxLog.AppendText("Actions 클릭 성공" + cr);
}
catch (Exception ex)
{
lastException = ex;
textBoxLog.AppendText($"Actions 클릭 실패: {ex.Message}" + cr);
}
// 2. JavaScript 클릭 시도
if (!clicked)
{
try
{
((IJavaScriptExecutor)driver).ExecuteScript(
"arguments[0].click(); arguments[0].dispatchEvent(new MouseEvent('click', {bubbles: true}));",
orderMenu);
clicked = true;
textBoxLog.AppendText("JavaScript 클릭 성공" + cr);
}
catch (Exception ex)
{
lastException = ex;
textBoxLog.AppendText($"JavaScript 클릭 실패: {ex.Message}" + cr);
}
}
// 3. 일반 클릭 시도
if (!clicked)
{
try
{
orderMenu.Click();
clicked = true;
textBoxLog.AppendText("일반 클릭 성공" + cr);
}
catch (Exception ex)
{
lastException = ex;
textBoxLog.AppendText($"일반 클릭 실패: {ex.Message}" + cr);
}
}
if (clicked)
{
// 클릭 성공 후 페이지 로드 대기
System.Threading.Thread.Sleep(5000);
break;
}
else
{
textBoxLog.AppendText($"모든 클릭 방법 실패: {lastException?.Message}" + cr);
orderMenu = null;
}
}
}
catch (Exception ex)
{
textBoxLog.AppendText($"하위 메뉴 {selector} 시도 실패: {ex.Message}" + cr);
orderMenu = null;
}
}
if (orderMenu == null)
{
textBoxLog.AppendText("발주목록 하위 메뉴를 클릭할 수 없습니다.");
CloseDriver();
throw new Exception("발주목록 하위 메뉴를 클릭할 수 없습니다.");
}
textBoxLog.AppendText("발주목록 메뉴 클릭 완료" + cr);
}
catch (Exception ex)
{
textBoxLog.AppendText($"메뉴 클릭 실패: {ex.Message}" + cr);
CloseDriver();
throw;
}
// 페이지 로드 대기
//System.Threading.Thread.Sleep(5000);
textBoxLog.AppendText("발주정보 페이지 이동 완료" + cr);
OrderPlan(wait);
PriSpecDisc(wait);
if(listViewOrderPlan.Items.Count == 0 && listViewSpec.Items.Count == 0)
{
textBoxLog.AppendText("조회된 데이터가 없습니다." + cr);
return;
}
}
catch (Exception ex)
{
textBoxLog.AppendText("Run" + cr);
textBoxLog.AppendText($"에러 발생: {ex.Message}" + cr);
}
finally
{
//textBoxLog.AppendText("검색이 완료되었습니다. Selenium 드라이버를 종료합니다." + cr);
//CloseDriver();
}
}
/* 크롤링 시작(입찰공고)
*/
public void RunNotice()
{
try
{
// 타임아웃 설정
driver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(120);
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(30);
driver.Manage().Timeouts().AsynchronousJavaScript = TimeSpan.FromSeconds(30);
// 웹사이트 접속 시도
int maxRetries = 5; // 재시도 횟수 증가
int currentTry = 0;
bool connected = false;
while (!connected && currentTry < maxRetries)
{
try
{
// 연결 전 대기 시간 증가
System.Threading.Thread.Sleep(5000);
textBoxLog.AppendText($"접속 시도 {currentTry + 1}/{maxRetries}" + cr);
// URL 접속
driver.Navigate().GoToUrl("https://www.g2b.go.kr");
// 페이지 로드 완료 확인을 위한 대기
WebDriverWait pageLoadWait = new WebDriverWait(driver, TimeSpan.FromSeconds(180));
// 1. document.readyState 확인
pageLoadWait.Until(driver => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));
// 2. jQuery 로드 완료 확인 (jQuery가 있는 경우)
try
{
pageLoadWait.Until(driver => ((IJavaScriptExecutor)driver).ExecuteScript("return (typeof jQuery !== 'undefined') && jQuery.active === 0"));
}
catch
{
textBoxLog.AppendText("jQuery 로드 확인 실패 (무시됨)" + cr);
}
// 3. 네트워크 요청 완료 확인
try
{
pageLoadWait.Until(driver => ((IJavaScriptExecutor)driver).ExecuteScript(@"
return new Promise((resolve) => {
if (window.performance && window.performance.getEntriesByType) {
const resources = window.performance.getEntriesByType('resource');
const pending = resources.filter(r => !r.responseEnd);
resolve(pending.length === 0);
} else {
resolve(true);
}
});
"));
}
catch
{
textBoxLog.AppendText("네트워크 요청 확인 실패 (무시됨)" + cr);
}
// 4. 페이지 로드 이벤트 확인
try
{
pageLoadWait.Until(driver => ((IJavaScriptExecutor)driver).ExecuteScript(@"
return new Promise((resolve) => {
if (document.readyState === 'complete') {
resolve(true);
} else {
window.addEventListener('load', () => resolve(true));
}
});
"));
}
catch
{
textBoxLog.AppendText("페이지 로드 이벤트 확인 실패 (무시됨)" + cr);
}
// 5. 특정 요소 존재 확인 (예: body)
pageLoadWait.Until(driver => driver.FindElement(By.TagName("body")).Displayed);
textBoxLog.AppendText("페이지 로드 완료 확인됨" + cr);
// 추가 대기
System.Threading.Thread.Sleep(3000);
connected = true;
textBoxLog.AppendText("드라이버 연결 성공" + cr);
}
catch (Exception ex)
{
currentTry++;
textBoxLog.AppendText($"연결 시도 {currentTry}/{maxRetries} 실패: {ex.Message}" + cr);
if (currentTry < maxRetries)
{
System.Threading.Thread.Sleep(15000); // 대기 시간 증가
try
{
driver.Navigate().Refresh();
System.Threading.Thread.Sleep(5000); // 새로고침 후 대기
}
catch { }
}
}
}
if (!connected)
{
textBoxLog.AppendText("최대 재시도 횟수를 초과했습니다." + cr);
CloseDriver();
throw new Exception("최대 재시도 횟수를 초과했습니다.");
}
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(120));
wait.IgnoreExceptionTypes(typeof(StaleElementReferenceException));
wait.IgnoreExceptionTypes(typeof(NoSuchElementException));
// 입찰메뉴 바로가기
textBoxLog.AppendText("입찰 메뉴 클릭 시도" + cr);
// 입찰 대메뉴 찾기 및 클릭
try
{
IWebElement parentMenu = null;
string[] parentSelectors = new string[]
{
"ID: mf_wfm_gnb_wfm_gnbMenu_genDepth1_1_btn_menuLvl1_span",
"XPath: //span[@id='mf_wfm_gnb_wfm_gnbMenu_genDepth1_1_btn_menuLvl1_span']",
"XPath: //span[contains(@class, 'w2textbox') and contains(text(), '입찰')]",
"CSS: span#mf_wfm_gnb_wfm_gnbMenu_genDepth1_1_btn_menuLvl1_span"
};
foreach (string selector in parentSelectors)
{
try
{
textBoxLog.AppendText($"상위 메뉴 {selector} 시도 중..." + cr);
if (selector.StartsWith("ID:"))
{
string id = selector.Substring(4).Trim();
parentMenu = wait.Until(d => d.FindElement(By.Id(id)));
}
else if (selector.StartsWith("XPath:"))
{
string xpath = selector.Substring(7).Trim();
parentMenu = wait.Until(d => d.FindElement(By.XPath(xpath)));
}
else if (selector.StartsWith("CSS:"))
{
string css = selector.Substring(5).Trim();
parentMenu = wait.Until(d => d.FindElement(By.CssSelector(css)));
}
if (parentMenu != null && parentMenu.Displayed && parentMenu.Enabled)
{
textBoxLog.AppendText($"상위 메뉴 {selector} 찾기 성공" + cr);
break;
}
}
catch (Exception ex)
{
textBoxLog.AppendText($"상위 메뉴 {selector} 시도 실패: {ex.Message}" + cr);
parentMenu = null;
}
}
if (parentMenu == null)
{
textBoxLog.AppendText("입찰 메뉴를 찾을 수 없습니다.");
CloseDriver();
throw new Exception("입찰 메뉴를 찾을 수 없습니다.");
}
// 상위 메뉴에 마우스 오버
try
{
// 요소가 보이도록 스크롤
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].scrollIntoView(true);", parentMenu);
System.Threading.Thread.Sleep(1000);
// Actions를 사용하여 마우스 오버
new Actions(driver)
.MoveToElement(parentMenu)
.Perform();
textBoxLog.AppendText("입찰 메뉴 마우스 오버 성공" + cr);
// 하위 메뉴가 나타날 때까지 대기
System.Threading.Thread.Sleep(2000);
}
catch (Exception ex)
{
textBoxLog.AppendText($"마우스 오버 실패: {ex.Message}" + cr);
CloseDriver();
throw;
}
// 하위 메뉴 찾기 및 클릭
IWebElement orderMenu = null;
string[] subMenuSelectors = new string[]
{
"ID: mf_wfm_gnb_wfm_gnbMenu_genDepth1_1_genDepth2_0_genDepth3_0_btn_menuLvl3",
"XPath: //a[@id='mf_wfm_gnb_wfm_gnbMenu_genDepth1_1_genDepth2_0_genDepth3_0_btn_menuLvl3']",
"XPath: //a[contains(@class, 'w2group') and .//span[contains(text(), '입찰공고 목록')]]",
//"CSS: a.w2group.w2trigger_anchor.btn.depth2.depth-last",
"CSS: a#mf_wfm_gnb_wfm_gnbMenu_genDepth1_1_genDepth2_0_genDepth3_0_btn_menuLvl3"
};
foreach (string selector in subMenuSelectors)
{
try
{
textBoxLog.AppendText($"하위 메뉴 {selector} 시도 중..." + cr);
if (selector.StartsWith("ID:"))
{
string id = selector.Substring(4).Trim();
orderMenu = wait.Until(d => d.FindElement(By.Id(id)));
}
else if (selector.StartsWith("XPath:"))
{
string xpath = selector.Substring(7).Trim();
orderMenu = wait.Until(d => d.FindElement(By.XPath(xpath)));
}
else if (selector.StartsWith("CSS:"))
{
string css = selector.Substring(5).Trim();
orderMenu = wait.Until(d => d.FindElement(By.CssSelector(css)));
}
if (orderMenu != null)
{
// 요소가 클릭 가능해질 때까지 대기
wait.Until(d =>
{
try
{
return orderMenu.Displayed &&
orderMenu.Enabled &&
!orderMenu.GetAttribute("class").Contains("disabled");
}
catch
{
return false;
}
});
textBoxLog.AppendText($"하위 메뉴 {selector} 찾기 성공, 클릭 시도" + cr);
// 여러 클릭 방법 시도
bool clicked = false;
Exception lastException = null;
// 1. Actions 클릭 시도 (마우스 이동 후 클릭)
try
{
new Actions(driver)
.MoveToElement(orderMenu)
.Click()
.Perform();
clicked = true;
textBoxLog.AppendText("Actions 클릭 성공" + cr);
}
catch (Exception ex)
{
lastException = ex;
textBoxLog.AppendText($"Actions 클릭 실패: {ex.Message}" + cr);
}
// 2. JavaScript 클릭 시도
if (!clicked)
{
try
{
((IJavaScriptExecutor)driver).ExecuteScript(
"arguments[0].click(); arguments[0].dispatchEvent(new MouseEvent('click', {bubbles: true}));",
orderMenu);
clicked = true;
textBoxLog.AppendText("JavaScript 클릭 성공" + cr);
}
catch (Exception ex)
{
lastException = ex;
textBoxLog.AppendText($"JavaScript 클릭 실패: {ex.Message}" + cr);
}
}
// 3. 일반 클릭 시도
if (!clicked)
{
try
{
orderMenu.Click();
clicked = true;
textBoxLog.AppendText("일반 클릭 성공" + cr);
}
catch (Exception ex)
{
lastException = ex;
textBoxLog.AppendText($"일반 클릭 실패: {ex.Message}" + cr);
}
}
if (clicked)
{
// 클릭 성공 후 페이지 로드 대기
System.Threading.Thread.Sleep(5000);
break;
}
else
{
textBoxLog.AppendText($"모든 클릭 방법 실패: {lastException?.Message}" + cr);
orderMenu = null;
}
}
}
catch (Exception ex)
{
textBoxLog.AppendText($"하위 메뉴 {selector} 시도 실패: {ex.Message}" + cr);
orderMenu = null;
}
}
if (orderMenu == null)
{
textBoxLog.AppendText("입찰공고 목록 메뉴를 클릭할 수 없습니다.");
CloseDriver();
throw new Exception("입찰공고 목록 메뉴를 클릭할 수 없습니다.");
}
textBoxLog.AppendText("입찰 메뉴 클릭 완료" + cr);
}
catch (Exception ex)
{
textBoxLog.AppendText($"메뉴 클릭 실패: {ex.Message}" + cr);
CloseDriver();
throw;
}
// 페이지 로드 대기
//System.Threading.Thread.Sleep(5000);
textBoxLog.AppendText("입찰공고 페이지 이동 완료" + cr);
OrderNotice(wait);
if (listViewOrderNotice.Items.Count == 0)
{
textBoxLog.AppendText("조회된 데이터가 없습니다." + cr);
return;
}
DateTime now = DateTime.Now;
string formattedTime = now.ToString("yyyy-MM-dd HH:mm:ss");
//SendMail("나라장터 조회 결과(" + formattedTime + ")", MakeMailBody());
}
catch (Exception ex)
{
textBoxLog.AppendText("Run" + cr);
textBoxLog.AppendText($"에러 발생: {ex.Message}" + cr);
}
finally
{
textBoxLog.AppendText("검색이 완료되었습니다. Selenium 드라이버를 종료합니다." + cr);
CloseDriver();
}
}
/* 발주계획
*/
private void OrderPlan(WebDriverWait wait)
{
//발주계획 탭으로 이동 불필요
// 검색 설정
textBoxLog.AppendText("검색 설정" + cr);
try
{
SelectElement select = new SelectElement(driver.FindElement(By.Id("mf_wfm_container_sbxRecordCountPerPage")));
//조회수 설정
if (radioButtonRstCnt10.Checked == true)
{
select.SelectByText("10"); // 조회수 설정
}
else if (radioButtonRstCnt30.Checked == true)
{
select.SelectByText("30"); // 조회수 설정
}
else if (radioButtonRstCnt50.Checked == true)
{
select.SelectByText("50"); // 조회수 설정
}
else if (radioButtonRstCnt100.Checked == true)
{
select.SelectByText("100"); // 조회수 설정
}
if (checkedListBoxBizType.CheckedItems.Count > 0)
{
foreach (var item in checkedListBoxBizType.CheckedItems)
{
//textBoxLog.AppendText("선택 아이템 : " + item.ToString()+ cr);
if (item.ToString() == "전체")
{
IWebElement bizType = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_chkRqdcBsneSeCd_input_0\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizType);
break;
}
else if (item.ToString() == "물품")
{
IWebElement bizType = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_chkRqdcBsneSeCd_input_1\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizType);
}
else if (item.ToString() == "일반용역")
{
IWebElement bizType = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_chkRqdcBsneSeCd_input_2\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizType);
}
else if (item.ToString() == "기술용역")
{
IWebElement bizType = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_chkRqdcBsneSeCd_input_3\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizType);
}
else if (item.ToString() == "공사")
{
IWebElement bizType = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_chkRqdcBsneSeCd_input_4\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizType);
}
else if (item.ToString() == "외자")
{
IWebElement bizType = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_chkRqdcBsneSeCd_input_5\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizType);
}
else if (item.ToString() == "리스")
{
IWebElement bizType = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_chkRqdcBsneSeCd_input_6\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizType);
}
}
}
else
{
textBoxLog.AppendText("체크된 항목이 없습니다." + cr);
return;
}
// 검색 조건 설정 (사업명)
IWebElement bizNmInput = wait.Until(d => d.FindElement(By.Id("mf_wfm_container_txtBizNm")));
bizNmInput.Clear();
bizNmInput.SendKeys(textBoxBizNm.Text);
// 검색 실행
IWebElement executeSearchButton = wait.Until(d => d.FindElement(By.Id("mf_wfm_container_btnS0001")));
executeSearchButton.Click();
textBoxLog.AppendText("검색 실행 완료" + cr);
// 검색 후 대기
System.Threading.Thread.Sleep(5000);
}
catch (Exception ex)
{
textBoxLog.AppendText($"검색 설정 실패: {ex.Message}" + cr);
textBoxLog.AppendText(ex.StackTrace.ToString() + cr);
CloseDriver();
throw;
}
// 데이터 추출
textBoxLog.AppendText("데이터 추출 시도" + cr);
try
{
var item = wait.Until(d => d.FindElement(By.Id("mf_wfm_container_gridView1_body_tbody")));
listViewOrderPlan.Items.Clear(); // 리스트뷰 초기화
try
{
var rows = item.FindElements(By.TagName("tr"));
//textBoxLog.AppendText(" : " + rows.GetAttribute("innerHTML") + cr);
textBoxLog.AppendText(cr + cr + cr + "=================================================================" + cr);
int idx = 1;
foreach (var row in rows)
{
string prcmBsneSeNm = row.FindElement(By.XPath(".//td[@col_id='prcmBsneSeNm']")).Text; //업무구분
string bizNm = row.FindElement(By.XPath(".//td[@col_id='bizNm']")).Text; //사업명
string oderInstUntyGrpNm = row.FindElement(By.XPath(".//td[@col_id='oderInstUntyGrpNm']")).Text; //수요기관
string picNm = row.FindElement(By.XPath(".//td[@col_id='picNm']")).Text; //담당자
string prcsYmd = row.FindElement(By.XPath(".//td[@col_id='prcsYmd']")).Text; //진행일자
string oderPlanPgstNm = row.FindElement(By.XPath(".//td[@col_id='oderPlanPgstNm']")).Text; //진행상태
string rfrnYn = row.FindElement(By.XPath(".//td[@col_id='rfrnYn']")).Text; //참조여부
string oderYymm = row.FindElement(By.XPath(".//td[@col_id='oderYymm']")).Text; //발주시기
string bgtSumAmt = row.FindElement(By.XPath(".//td[@col_id='bgtSumAmt']")).Text; //예산금액
//textBoxLog.AppendText(idx.ToString() + " : " + row.GetAttribute("innerHTML") + cr);
if (bizNm == null || "".Equals(bizNm))
break;
textBoxLog.AppendText(idx.ToString() + $" 업무구분: {prcmBsneSeNm}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 사업명: {bizNm}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 수요기관: {oderInstUntyGrpNm}" + cr);
//textBoxLog.AppendText(idx.ToString() + $" 공고기관: {tkcgDeptNm}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 담당자: {picNm}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 진행일자: {prcsYmd}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 진행상태: {oderPlanPgstNm}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 참조여부: {rfrnYn}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 발주시기: {oderYymm}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 예산금액: {bgtSumAmt}" + cr);
textBoxLog.AppendText(cr + cr + cr);
ListViewItem listViewItem = new ListViewItem(idx.ToString());
listViewItem.SubItems.Add(prcmBsneSeNm);
listViewItem.SubItems.Add(bizNm);
listViewItem.SubItems.Add(oderInstUntyGrpNm);
listViewItem.SubItems.Add(picNm);
listViewItem.SubItems.Add(prcsYmd);
listViewItem.SubItems.Add(oderPlanPgstNm);
listViewItem.SubItems.Add(rfrnYn);
listViewItem.SubItems.Add(oderYymm);
listViewItem.SubItems.Add(bgtSumAmt);
listViewOrderPlan.Items.Add(listViewItem);
idx++;
}
}
catch (Exception ex)
{
textBoxLog.AppendText($"항목 처리 중 에러: {ex.Message}" + cr);
}
}
catch (Exception ex)
{
textBoxLog.AppendText($"데이터 추출 실패: {ex.Message}" + cr);
CloseDriver();
throw;
}
///컨텐츠 내용에 따라 자동변환
listViewOrderPlan.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
}
/* 사전규격공개
*/
private void PriSpecDisc(WebDriverWait wait)
{
//사전규격공개 탭으로 이동 로직 추가 필요
IWebElement radSrchTy = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_radSrchTy_input_1\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", radSrchTy);
System.Threading.Thread.Sleep(1000);
// 검색 설정
textBoxLog.AppendText("검색 설정" + cr);
try
{
//상세 설정 클릭
//IWebElement executeDetailButton = wait.Until(d => d.FindElement(By.CssSelector(".w2trigger.btn_cm.srch_toggle")));
//((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", executeDetailButton);
//System.Threading.Thread.Sleep(1000);
SelectElement select = new SelectElement(driver.FindElement(By.Id("mf_wfm_container_sbxRecordCountPerPage")));
//조회수 설정
if (radioButtonRstCnt10.Checked == true)
{
select.SelectByText("10"); // 조회수 설정
}
else if (radioButtonRstCnt30.Checked == true)
{
select.SelectByText("30"); // 조회수 설정
}
else if (radioButtonRstCnt50.Checked == true)
{
select.SelectByText("50"); // 조회수 설정
}
else if (radioButtonRstCnt100.Checked == true)
{
select.SelectByText("100"); // 조회수 설정
}
System.Threading.Thread.Sleep(1000);
// 입찰공고에서 설정되어 있는 값 동일하게 사용
/*
if (checkedListBoxBizType.CheckedItems.Count > 0)
{
foreach (var item in checkedListBoxBizType.CheckedItems)
{
if (item.ToString() == "전체")
{
IWebElement bizType = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_chkRqdcBsneSeCd_input_0\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizType);
break;
}
else if (item.ToString() == "물품")
{
IWebElement bizType = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_chkRqdcBsneSeCd_input_1\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizType);
}
else if (item.ToString() == "일반용역")
{
IWebElement bizType = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_chkRqdcBsneSeCd_input_2\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizType);
}
else if (item.ToString() == "기술용역")
{
IWebElement bizType = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_chkRqdcBsneSeCd_input_3\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizType);
}
else if (item.ToString() == "공사")
{
IWebElement bizType = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_chkRqdcBsneSeCd_input_4\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizType);
}
else if (item.ToString() == "외자")
{
IWebElement bizType = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_chkRqdcBsneSeCd_input_5\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizType);
}
else if (item.ToString() == "리스")
{
IWebElement bizType = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_chkRqdcBsneSeCd_input_6\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizType);
}
}
}
else
{
textBoxLog.AppendText("체크된 항목이 없습니다." + cr);
return;
}
*/
// 검색 조건 설정 (사업명)
IWebElement bizNmInput = wait.Until(d => d.FindElement(By.Id("mf_wfm_container_txtBizNm")));
bizNmInput.Clear();
bizNmInput.SendKeys(textBoxBizNm.Text);
// 검색 실행
IWebElement executeSearchButton = wait.Until(d => d.FindElement(By.Id("mf_wfm_container_btnS0001")));
executeSearchButton.Click();
textBoxLog.AppendText("검색 실행 완료" + cr);
// 검색 후 대기
System.Threading.Thread.Sleep(5000);
}
catch (Exception ex)
{
textBoxLog.AppendText($"검색 설정 실패: {ex.Message}" + cr);
textBoxLog.AppendText(ex.StackTrace.ToString() + cr);
CloseDriver();
throw;
}
// 데이터 추출
textBoxLog.AppendText("데이터 추출 시도" + cr);
try
{
var item = wait.Until(d => d.FindElement(By.Id("mf_wfm_container_gridView1_body_tbody")));
listViewSpec.Items.Clear(); // 리스트뷰 초기화
try
{
var rows = item.FindElements(By.TagName("tr"));
//textBoxLog.AppendText(" : " + rows.GetAttribute("innerHTML") + cr);
textBoxLog.AppendText(cr + cr + cr + "================================================================" + cr);
int idx = 1;
foreach (var row in rows)
{
string prcmBsneSeNm = row.FindElement(By.XPath(".//td[@col_id='prcmBsneSeNm']")).Text; //업무구분
string bizNm = row.FindElement(By.XPath(".//td[@col_id='bizNm']")).Text; //사업명
string oderInstUntyGrpNm = row.FindElement(By.XPath(".//td[@col_id='oderInstUntyGrpNm']")).Text; //수요기관
string tkcgDeptNm = row.FindElement(By.XPath(".//td[@col_id='tkcgDeptNm']")).Text; //공고기관
string picNm = row.FindElement(By.XPath(".//td[@col_id='picNm']")).Text; //담당자
string prcsYmd = row.FindElement(By.XPath(".//td[@col_id='prcsYmd']")).Text; //진행일자
string oderPlanPgstNm = row.FindElement(By.XPath(".//td[@col_id='oderPlanPgstNm']")).Text; //진행상태
string rfrnYn = row.FindElement(By.XPath(".//td[@col_id='rfrnYn']")).Text; //참조여부
string bfSpecOpnnCnt = row.FindElement(By.XPath(".//td[@col_id='bfSpecOpnnCnt']")).Text; //업체등록수
//textBoxLog.AppendText(idx.ToString() + " : " + row.GetAttribute("innerHTML") + cr);
if (bizNm == null || "".Equals(bizNm))
break;
textBoxLog.AppendText(idx.ToString() + $" 업무구분: {prcmBsneSeNm}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 사업명: {bizNm}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 수요기관: {oderInstUntyGrpNm}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 공고기관: {tkcgDeptNm}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 담당자: {picNm}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 진행일자: {prcsYmd}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 진행상태: {oderPlanPgstNm}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 참조여부: {rfrnYn}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 업체등록수: {bfSpecOpnnCnt}" + cr);
textBoxLog.AppendText(cr + cr + cr);
ListViewItem listViewItem = new ListViewItem(idx.ToString());
listViewItem.SubItems.Add(prcmBsneSeNm);
listViewItem.SubItems.Add(bizNm);
listViewItem.SubItems.Add(oderInstUntyGrpNm);
listViewItem.SubItems.Add(tkcgDeptNm);
listViewItem.SubItems.Add(picNm);
listViewItem.SubItems.Add(prcsYmd);
listViewItem.SubItems.Add(oderPlanPgstNm);
listViewItem.SubItems.Add(rfrnYn);
listViewItem.SubItems.Add(bfSpecOpnnCnt);
listViewSpec.Items.Add(listViewItem);
idx++;
}
}
catch (Exception ex)
{
textBoxLog.AppendText($"항목 처리 중 에러: {ex.Message}" + cr);
}
}
catch (Exception ex)
{
textBoxLog.AppendText($"데이터 추출 실패: {ex.Message}" + cr);
CloseDriver();
throw;
}
///컨텐츠 내용에 따라 자동변환
listViewSpec.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
}
/* 입찰공고 조회
*/
private void OrderNotice(WebDriverWait wait)
{
// 검색 설정
textBoxLog.AppendText("검색 설정" + cr);
try
{
SelectElement select = new SelectElement(driver.FindElement(By.Id("mf_wfm_container_tacBidPbancLst_contents_tab2_body_sbxRecordCountPerPage1")));
//조회수 설정
if (radioButtonRstCnt10.Checked == true)
{
select.SelectByText("10"); // 조회수 설정
}
else if (radioButtonRstCnt30.Checked == true)
{
select.SelectByText("30"); // 조회수 설정
}
else if (radioButtonRstCnt50.Checked == true)
{
select.SelectByText("50"); // 조회수 설정
}
else if (radioButtonRstCnt100.Checked == true)
{
select.SelectByText("100"); // 조회수 설정
}
if (checkedListBoxBizType.CheckedItems.Count > 0)
{
foreach (var item in checkedListBoxBizType.CheckedItems)
{
//textBoxLog.AppendText("선택 아이템 : " + item.ToString()+ cr);
if (item.ToString() == "전체")
{
break;
}
else if (item.ToString() == "물품")
{
IWebElement bizAll = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_tacBidPbancLst_contents_tab2_body_chkBidPbancSrchTyCd_input_0\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizAll);
IWebElement bizType = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_tacBidPbancLst_contents_tab2_body_chkBidPbancSrchTyCd_input_1\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizType);
}
else if (item.ToString() == "일반용역")
{
IWebElement bizAll = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_tacBidPbancLst_contents_tab2_body_chkBidPbancSrchTyCd_input_0\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizAll);
IWebElement bizType = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_tacBidPbancLst_contents_tab2_body_chkBidPbancSrchTyCd_input_2\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizType);
}
else if (item.ToString() == "기술용역")
{
IWebElement bizAll = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_tacBidPbancLst_contents_tab2_body_chkBidPbancSrchTyCd_input_0\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizAll);
IWebElement bizType = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_tacBidPbancLst_contents_tab2_body_chkBidPbancSrchTyCd_input_3\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizType);
}
else if (item.ToString() == "공사")
{
IWebElement bizAll = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_tacBidPbancLst_contents_tab2_body_chkBidPbancSrchTyCd_input_0\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizAll);
IWebElement bizType = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_tacBidPbancLst_contents_tab2_body_chkBidPbancSrchTyCd_input_4\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizType);
}
else if (item.ToString() == "외자")
{
IWebElement bizAll = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_tacBidPbancLst_contents_tab2_body_chkBidPbancSrchTyCd_input_0\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizAll);
IWebElement bizType = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_tacBidPbancLst_contents_tab2_body_chkBidPbancSrchTyCd_input_5\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizType);
}
else if (item.ToString() == "리스")
{
IWebElement bizAll = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_tacBidPbancLst_contents_tab2_body_chkBidPbancSrchTyCd_input_0\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizAll);
IWebElement bizType = wait.Until(d => d.FindElement(By.XPath("//*[@id=\"mf_wfm_container_tacBidPbancLst_contents_tab2_body_chkBidPbancSrchTyCd_input_6\"]")));
((IJavaScriptExecutor)driver).ExecuteScript("arguments[0].click();", bizType);
}
}
}
else
{
textBoxLog.AppendText("체크된 항목이 없습니다." + cr);
return;
}
// 검색 조건 설정 (사업명)
IWebElement bizNmInput = wait.Until(d => d.FindElement(By.Id("mf_wfm_container_tacBidPbancLst_contents_tab2_body_bidPbancNm")));
bizNmInput.Clear();
bizNmInput.SendKeys(textBoxBizNm.Text);
// 검색 실행
IWebElement executeSearchButton = wait.Until(d => d.FindElement(By.Id("mf_wfm_container_tacBidPbancLst_contents_tab2_body_btnS0004")));
executeSearchButton.Click();
textBoxLog.AppendText("검색 실행 완료" + cr);
// 검색 후 대기
System.Threading.Thread.Sleep(5000);
}
catch (Exception ex)
{
textBoxLog.AppendText($"검색 설정 실패: {ex.Message}" + cr);
textBoxLog.AppendText(ex.StackTrace.ToString() + cr);
CloseDriver();
throw;
}
// 데이터 추출
textBoxLog.AppendText("데이터 추출 시도" + cr);
try
{
var item = wait.Until(d => d.FindElement(By.Id("mf_wfm_container_tacBidPbancLst_contents_tab2_body_gridView1_body_tbody")));
listViewOrderNotice.Items.Clear(); // 리스트뷰 초기화
try
{
var rows = item.FindElements(By.TagName("tr"));
//textBoxLog.AppendText(" : " + rows.GetAttribute("innerHTML") + cr);
textBoxLog.AppendText(cr + cr + cr + "=================================================================" + cr);
int idx = 1;
foreach (var row in rows)
{
string prcmBsneSeCdNm = row.FindElement(By.XPath(".//td[@col_id='prcmBsneSeCdNm']")).Text; //업무구분
string pbancSeYnNm = row.FindElement(By.XPath(".//td[@col_id='pbancSeYnNm']")).Text; //업무여부
string pbancSttsNm = row.FindElement(By.XPath(".//td[@col_id='pbancSttsNm']")).Text; //구분
string bidPbancUntyNoOrd = row.FindElement(By.XPath(".//td[@col_id='bidPbancUntyNoOrd']")).Text; //입찰공고번호
string bidPbancNm = row.FindElement(By.XPath(".//td[@col_id='bidPbancNm']")).Text; //공고명
string oderInstUntyGrpNm = row.FindElement(By.XPath(".//td[@col_id='oderInstUntyGrpNm']")).Text; //공고기관
string dmstNm = row.FindElement(By.XPath(".//td[@col_id='dmstNm']")).Text; //수요기관
string pbancPstgDt = row.FindElement(By.XPath(".//td[@col_id='pbancPstgDt']")).Text; //게시일시
string stepBsneUntNm = row.FindElement(By.XPath(".//td[@col_id='stepBsneUntNm']")).Text; //단계
string prssBsneUntNm = row.FindElement(By.XPath(".//td[@col_id='prssBsneUntNm']")).Text; //세부절차
string bsnePrssPrgrsSeNm = row.FindElement(By.XPath(".//td[@col_id='bsnePrssPrgrsSeNm']")).Text; //세부절차상태
//입찰진행
//요약
if (bidPbancNm == null || "".Equals(bidPbancNm))
break;
textBoxLog.AppendText(idx.ToString() + $" 업무구분: {prcmBsneSeCdNm}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 업무여부: {pbancSeYnNm}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 구분: {pbancSttsNm}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 입찰공고번호: {bidPbancUntyNoOrd}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 공고명: {bidPbancNm}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 공고기관: {oderInstUntyGrpNm}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 수요기관: {dmstNm}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 게시일시: {pbancPstgDt}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 단계: {stepBsneUntNm}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 세부절차: {prssBsneUntNm}" + cr);
textBoxLog.AppendText(idx.ToString() + $" 세부절차상태: {bsnePrssPrgrsSeNm}" + cr);
textBoxLog.AppendText(cr + cr + cr);
ListViewItem listViewItem = new ListViewItem(idx.ToString());
listViewItem.SubItems.Add(prcmBsneSeCdNm);
listViewItem.SubItems.Add(pbancSeYnNm);
listViewItem.SubItems.Add(pbancSttsNm);
listViewItem.SubItems.Add(bidPbancUntyNoOrd);
listViewItem.SubItems.Add(bidPbancNm);
listViewItem.SubItems.Add(oderInstUntyGrpNm);
listViewItem.SubItems.Add(dmstNm);
listViewItem.SubItems.Add(pbancPstgDt);
listViewItem.SubItems.Add(stepBsneUntNm);
listViewItem.SubItems.Add(prssBsneUntNm);
listViewItem.SubItems.Add(bsnePrssPrgrsSeNm);
listViewOrderNotice.Items.Add(listViewItem);
idx++;
}
}
catch (Exception ex)
{
textBoxLog.AppendText($"항목 처리 중 에러: {ex.Message}" + cr);
}
}
catch (Exception ex)
{
textBoxLog.AppendText($"데이터 추출 실패: {ex.Message}" + cr);
CloseDriver();
throw;
}
///컨텐츠 내용에 따라 자동변환
listViewOrderNotice.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
}
/* 메일 전송
* 네이버 SMTP 메일 사용
* 네이버 메일 설정에서 imap 사용 허용필요
* 네이버 메일 로그인 > 환경설정 > POP3/IMAP 설정 > IMAP 사용 설정 으로 이동 후 IMAP/SMTP 사용 항목 중 사용함 선택
*/
private void SendMail(string subject, string body)
{
MailAddress sendAddress = new MailAddress(smtp.ToString());
MailMessage message = new System.Net.Mail.MailMessage();
message.From = new System.Net.Mail.MailAddress(sendAddress.Address); //ex : ooo@naver.com
foreach (var item in listViewEmail.Items)
{
ListViewItem list1 = item as ListViewItem;
if (list1 != null)
{
message.To.Add(list1.SubItems[0].Text); // 메일주소 추가
}
}
if(message.To.Count == 0)
{
textBoxLog.AppendText("메일 수신자 없음" + cr);
return;
}
message.Subject = subject;
message.SubjectEncoding = System.Text.Encoding.UTF8;
message.IsBodyHtml = true; // HTML 형식으로 전송
message.Body = body;
message.BodyEncoding = System.Text.Encoding.UTF8;
try
{
System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient("smtp.naver.com", 587);
smtp.UseDefaultCredentials = false; // 시스템에 설정된 인증 정보를 사용하지 않는다.
smtp.EnableSsl = true; // SSL을 사용한다.
smtp.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network; // 이걸 하지 않으면 naver 에 인증을 받지 못한다.
smtp.Credentials = new System.Net.NetworkCredential(sendAddress.Address, sendPassword);
if(string.IsNullOrEmpty(sendPassword))
{
textBoxLog.AppendText("메일 비밀번호가 설정되지 않았습니다." + cr);
return;
}
if (string.IsNullOrEmpty(sendAddress.Address))
{
textBoxLog.AppendText("메일 주소가 설정되지 않았습니다." + cr);
return;
}
if(!isDebug)
{
smtp.Send(message);
}
textBoxLog.AppendText("메일 전송 완료" + cr);
}
catch (Exception ex)
{
textBoxLog.Text += ex.ToString();
}
finally
{
//if (smtp != null) { smtp.Dispose(); }
if (message != null) { message.Dispose(); }
}
}
/* 발주계획, 사전규격공개 내용을 메일로 전송
* HTML 형식으로 작성
* 메일 내용이 많아 width를 늘릴수 있도록 조정 필요
*/
private string MakeMailBody()
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("<html>");
sb.AppendLine("<head>");
sb.AppendLine("<meta charset=\"utf-8\">");
sb.AppendLine("<style>");
sb.AppendLine("table { border-collapse: collapse; border: 1px solid #bfbfbf; width=100%;}");
sb.AppendLine("table tbody{ border: 1px solid #bfbfbf; }");
sb.AppendLine("table tbody td{ border: 1px solid #bfbfbf; 5px;}");
sb.AppendLine("table tbody th{ border: 1px solid #bfbfbf; 5px;}");
sb.AppendLine("th, td { border: 1px solid #bfbfbf; padding: 5px; }");
sb.AppendLine("th { background-color: #bfbfbf; }");
sb.AppendLine("</style>");
sb.AppendLine("</head>");
sb.AppendLine("<body>");
sb.AppendLine("<h2>나라장터 발주계획 및 사전규격공개</h2>");
sb.AppendLine("<p>아래는 나라장터에서 수집한 발주계획 및 사전규격공개 정보입니다.</p>");
sb.AppendLine("<p>사업명 : " + textBoxBizNm.Text + "</p>");
sb.AppendLine("<p>검색일자 : " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "</p>");
sb.AppendLine("<br/>");
if(listViewOrderPlan.Items.Count == 0)
{
sb.AppendLine("<p>발주계획 : 조회된 데이터 없음</p>");
}
else
{
sb.AppendLine("<p>발주계획</p>");
sb.AppendLine("<table style='border-collapse: collapse; border: 1px solid #bfbfbf; width=100%;'>");
sb.AppendLine("<tr>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>번호</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>업무구분</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>사업명</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>수요기관</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>담당자</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>진행일자</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>진행상태</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>참조여부</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>발주시기</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>예산금액</th>");
sb.AppendLine("</tr>");
sb.AppendLine("<tbody>");
// 발주계획 내용
foreach (var item in listViewOrderPlan.Items)
{
ListViewItem list1 = item as ListViewItem;
if (list1 != null)
{
sb.AppendLine("<tr>");
foreach (ListViewItem.ListViewSubItem sub in list1.SubItems)
{
sb.AppendLine("<td style='border-collapse: collapse; border: 1px solid #bfbfbf;'>" + sub.Text + "</td>");
//sb.Append(sub.Text + "\t");
}
sb.AppendLine("</tr>");
}
sb.AppendLine();
}
sb.AppendLine("</tbody>");
sb.AppendLine("</table>");
sb.AppendLine("</br>");
sb.AppendLine("</br>");
}
if(listViewSpec.Items.Count == 0)
{
sb.AppendLine("<p>사전규격 : 조회된 데이터 없음</p>");
}
else
{
sb.AppendLine("<p>사전규격</p>");
sb.AppendLine("<table style='border-collapse: collapse; border: 1px solid #bfbfbf; width=100%;'>");
sb.AppendLine("<tr>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>번호</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>업무구분</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>사업명</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>수요기관</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>공고기관</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>담당자</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>진행일자</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>진행상태</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>참조여부</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>업체등록수</th>");
sb.AppendLine("</tr>");
sb.AppendLine("<tbody>");
// 사전규격 내용
foreach (var item in listViewSpec.Items)
{
ListViewItem list2 = item as ListViewItem;
if (list2 != null)
{
sb.AppendLine("<tr>");
foreach (ListViewItem.ListViewSubItem sub in list2.SubItems)
{
sb.AppendLine("<td style='border-collapse: collapse; border: 1px solid #bfbfbf;'>" + sub.Text + "</td>");
//sb.Append(sub.Text + "\t");
}
sb.AppendLine("</tr>");
}
sb.AppendLine();
}
sb.AppendLine("</tbody>");
sb.AppendLine("</table>");
sb.AppendLine("</br>");
}
if (listViewOrderNotice.Items.Count == 0)
{
sb.AppendLine("<p>입찰공고 : 조회된 데이터 없음</p>");
}
else
{
sb.AppendLine("<p>입찰공고</p>");
sb.AppendLine("<table style='border-collapse: collapse; border: 1px solid #bfbfbf; width=100%;'>");
sb.AppendLine("<tr>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>번호</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>업무구분</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>업무여부</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>구분</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>입찰공고번호</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>공고명</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>공고기관</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>수요기관</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>게시일시(일찰마감일시)</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>단계</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>세부절차</th>");
sb.AppendLine("<th style='border-collapse: collapse; border: 1px solid #bfbfbf;'>세부절차상태</th>");
sb.AppendLine("</tr>");
sb.AppendLine("<tbody>");
// 입찰공고 내용
foreach (var item in listViewOrderNotice.Items)
{
ListViewItem list3 = item as ListViewItem;
if (list3 != null)
{
sb.AppendLine("<tr>");
foreach (ListViewItem.ListViewSubItem sub in list3.SubItems)
{
sb.AppendLine("<td style='border-collapse: collapse; border: 1px solid #bfbfbf;'>" + sub.Text + "</td>");
//sb.Append(sub.Text + "\t");
}
sb.AppendLine("</tr>");
}
sb.AppendLine();
}
sb.AppendLine("</tbody>");
sb.AppendLine("</table>");
sb.AppendLine("</br>");
}
sb.AppendLine("</body>");
sb.AppendLine("</html>");
textBoxLog.AppendText("메일 내용 작성 완료" + cr + cr + cr);
return sb.ToString();
}
/* 현재 시간 출력
*/
private void printTime()
{
DateTime now = DateTime.Now;
string formattedTime = now.ToString("yyyy-MM-dd HH:mm:ss");
textBoxLog.AppendText(formattedTime + cr);
}
/* 드라이버 종료
* 드라이버 종료 및 자원 해제
*/
private void CloseDriver()
{
// 드라이버 종료
try
{
driver.Quit();
}
catch
{
driver.Dispose();
driver = null;
printTime();
textBoxLog.AppendText("실행 종료" + cr + cr + cr + cr);
}
}
/* 이벤트 시작
* UI, 구현에 필요한 이벤트 처리
*/
/* 실행 버튼 클릭 이벤트
*/
private void buttonRun_Click(object sender, EventArgs e)
{
//검색어 DB저장
string bizNm = textBoxBizNm.Text;
if (bizNm == null || "".Equals(bizNm))
{
MessageBox.Show("사업명을 입력하세요.");
return;
}
string sql = "delete from searchWord;"; //검색어 초기화
cs.ExcuteSql(sql);
sql = "insert into searchWord values( '" + bizNm + "', '', '' );";
cs.ExcuteSql(sql);
textBoxLog.Clear();
printTime();
InitSelenium();
Run();
RunNotice();
DateTime now = DateTime.Now;
string formattedTime = now.ToString("yyyy-MM-dd HH:mm:ss");
SendMail("나라장터 조회 결과(" + formattedTime + ")", MakeMailBody());
}
/* 사업명 텍스트박스 엔터키 이벤트
* 엔터키 입력 시 크롬 드라이버 실행
* 사업명으로 검색 후 결과 리스트뷰에 출력
*/
private void EnterTextBoxBizNm(object sender, KeyEventArgs e)
{
if (e.KeyCode == System.Windows.Forms.Keys.Enter)
{
//검색어 DB저장
string bizNm = textBoxBizNm.Text;
if (bizNm == null || "".Equals(bizNm))
{
MessageBox.Show("사업명을 입력하세요.");
return;
}
string sql = "delete from searchWord;"; //검색어 초기화
cs.ExcuteSql(sql);
sql = "insert into searchWord values( '" + bizNm + "' );";
cs.ExcuteSql(sql);
textBoxLog.Clear();
printTime();
InitSelenium();
Run();
}
return;
}
/* 이메일 추가 버튼
* 이메일 주소를 리스트뷰에 추가
* 리스트뷰에 추가된 이메일 주소로 메일 발송
*/
private void buttonEmail_Click(object sender, EventArgs e)
{
if(textBoxEmail.Text != null && !"".Equals(textBoxEmail.Text))
{
if (textBoxEmail.Text.Contains("@") == false)
{
MessageBox.Show("이메일 형식이 아닙니다.");
return;
}
if (textBoxEmail.Text.Contains(".") == false)
{
MessageBox.Show("이메일 형식이 아닙니다.");
return;
}
if (textBoxEmail.Text.Contains(" ") == true)
{
MessageBox.Show("이메일 형식이 아닙니다.");
return;
}
//listViewEmail.Items.Clear();
listViewEmail.Items.Add(textBoxEmail.Text);
string sql = "insert into mailTarget values( '" + textBoxEmail.Text + "' );";
cs.ExcuteSql(sql);
textBoxEmail.Text = "";
}
else
{
MessageBox.Show("이메일을 입력하세요.");
return;
}
}
/* 타이머 60초마다 체크
* 반복설정 시간과 비교하여 00분에만 실행
*/
private void timerChkRun_Tick(object sender, EventArgs e)
{
DateTime nowDate = DateTime.Now;
//textBoxLog.AppendText("현재시간 : " + nowDate.ToString("yyyy-MM-dd HH:mm:ss") + cr);
//textBoxLog.AppendText("설정시간 : " + comboBoxRunTM.SelectedItem.ToString() + "시 00분" + cr);
if ( nowDate.Hour.ToString() == comboBoxRunTM.SelectedItem.ToString() )
{
if(nowDate.Minute == 0)
{
textBoxLog.Clear();
printTime();
InitSelenium();
Run();
RunNotice();
DateTime now = DateTime.Now;
string formattedTime = now.ToString("yyyy-MM-dd HH:mm:ss");
SendMail("나라장터 조회 결과(" + formattedTime + ")", MakeMailBody());
}
}
}
private void ChangeRunTM(object sender, EventArgs e)
{
string runTime = comboBoxRunTM.SelectedItem.ToString();
labelTM.Text = "* 매일" + runTime + "시 00분에 실행됩니다.";
string sql = "delete from sendTime;";
cs.ExcuteSql(sql);
sql = "insert into sendTime values( '" + runTime +"' );";
cs.ExcuteSql(sql);
}
/* MailForm Delegate
*/
public void GetMailInfo()
{
string from = mailForm.GetFrom();
string pass = mailForm.GetPass();
smtp = from;
sendPassword = pass;
}
private void buttonMailAtuh_Click(object sender, EventArgs e)
{
try
{
mailForm = new MailForm();
mailForm.FormSendEvent += new MailForm.FormSendDataHandler(GetMailInfo);
}
catch (Exception ex)
{
textBoxLog.AppendText( ex.ToString() + cr);
}
mailForm.ShowDialog();
}
private void buttonEmailDel_Click(object sender, EventArgs e)
{
if (listViewEmail.SelectedItems.Count > 0)
{
ListViewItem selectedItem = listViewEmail.SelectedItems[0];
string email = selectedItem.Text;
// 리스트뷰에서 선택된 항목 삭제
listViewEmail.Items.Remove(selectedItem);
// 데이터베이스에서 이메일 삭제
string sql = "delete from mailTarget where email = '" + email + "';";
cs.ExcuteSql(sql);
}
else
{
MessageBox.Show("삭제할 이메일을 선택하세요.");
}
}
/* TrayIcon
*/
private void DClick_Tray(object sender, MouseEventArgs e)
{
if (this.Visible == false)
{
this.Visible = true;
if (this.WindowState == FormWindowState.Minimized)
this.WindowState = FormWindowState.Normal; // 최소화를 멈춘다
this.Activate(); // 폼을 활성화 시킨다
}
else if (this.Visible == true)
{
this.Visible = false;
}
}
public void CloseApp(object sender, EventArgs e)
{
textBoxLog.AppendText("CloseApp 클릭" + cr);
Application.Exit();
}
public void HideForm(object sender, EventArgs e)
{
if (this.Visible == false)
{
this.Visible = true;
if (this.WindowState == FormWindowState.Minimized)
this.WindowState = FormWindowState.Normal; // 최소화를 멈춘다
this.Activate(); // 폼을 활성화 시킨다
}
else if (this.Visible == true)
{
this.Visible = false;
}
}
private void FormG2B_FormClosing(object sender, FormClosingEventArgs e)
{
//폼 닫기 이벤트 시 닫기 취소
//트레이 아이콘에서 CloseApp 클릭 시 제외
if (e.CloseReason != CloseReason.UserClosing)
{
return; // 사용자가 닫는 것이 아닌 경우에는 아무 작업도 하지 않음
}
e.Cancel = true; // 폼 닫기 이벤트 취소
this.Visible = false; // 폼을 숨김
}
private void ConetxtCursorHand(object sender, EventArgs e)
{
//textBoxLog.AppendText("컨트롤에 커서 핸드 모양 적용" + cr);
// 컨트롤에 커서 핸드 모양 적용
this.Cursor = Cursors.Hand;
/*
textBoxBizNm.Cursor = Cursors.IBeam;
textBoxLog.Cursor = Cursors.Arrow;
listViewOrderPlan.Cursor = Cursors.Arrow;
listViewSpec.Cursor = Cursors.Arrow;
listViewEmail.Cursor = Cursors.Arrow;
*/
}
}
}
Mail 계정 관리 폼(MailForm.cs)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Data.SQLite;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
namespace g2b
{
public partial class MailForm : Form
{
readonly CommonSQL cs = new CommonSQL();
//Form 대리자 선언
public delegate void FormSendDataHandler();
public event FormSendDataHandler FormSendEvent;
private string from = "";
private string pass = "";
//private string to = "";
public MailForm()
{
InitializeComponent();
InitForm();
}
public string GetFrom()
{
return from;
}
public string GetPass()
{
return pass;
}
public void InitForm()
{
try
{
string sql = "select fromUser, pw from mailAuth";
SQLiteDataReader sdr = cs.SelectSql(sql);
while (sdr.Read())
{
from = textBoxFrom.Text = sdr["fromUser"].ToString();
pass = textBoxPass.Text = sdr["pw"].ToString();
//to = textBoxTo.Text = sdr["toUser"].ToString();
}
sdr.Close();
}
catch (Exception e)
{
cs.WriteLog(e.ToString());
}
/* finally
{
cs.CloseConn();
}*/
}
private void ButtonClose_Click(object sender, EventArgs e)
{
this.Close();
}
private void ButtonSave_Click(object sender, EventArgs e)
{
if (textBoxFrom.Text.Contains("@") == false)
{
MessageBox.Show("이메일 형식이 아닙니다.");
return;
}
if (textBoxFrom.Text.Contains(".") == false)
{
MessageBox.Show("이메일 형식이 아닙니다.");
return;
}
if (textBoxFrom.Text.Contains(" ") == true)
{
MessageBox.Show("이메일 형식이 아닙니다.");
return;
}
string delSql = "delete from mailAuth";
cs.ExcuteSql(delSql);
//string insSql = "insert into mail (fromUser, pw) values ('" + textBoxFrom.Text + "', '" + textBoxPass.Text + "', '" + textBoxTo.Text + "')";
string insSql = "insert into mailAuth (fromUser, pw) values ('" + textBoxFrom.Text + "', '" + textBoxPass.Text + "')";
int res = cs.ExcuteSql(insSql);
if (res > 0)
{
InitForm();
MessageBox.Show("저장되었습니다.");
}
this.FormSendEvent();
this.Close();
}
}
}
내장DB관리 폼(CommonSQL.cs)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SQLite;
using System.Windows.Forms;
using System.IO;
namespace g2b
{
class CommonSQL
{
public SQLiteConnection conn = null;
public String sqlFilePath = Application.StartupPath + "\\" + @"data.sqlite";
public String sqlConnStr = "";
public CommonSQL()
{
sqlConnStr = "Data Source=" + sqlFilePath + ";Version=3;";
}
public void CloseConn()
{
conn.Close();
}
//데이터베이스
public Boolean InitDB()
{
try
{
FileInfo fi = new FileInfo(sqlFilePath);
if (!fi.Exists)
{
SQLiteConnection.CreateFile(sqlFilePath);
//메일 사용자 테이블 생성
string sql = "create table mailAuth (fromUser varchar(30), pw varchar(30) )";
ExcuteSql(sql);
//검색어 저장 테이블 생성
sql = "create table searchWord ( word varchar(100), radOrgan varchar(30), organName varchar(100) )";
ExcuteSql(sql);
//메일 대상 테이블 생성
sql = "create table mailTarget (email varchar(100) )";
ExcuteSql(sql);
//발송시간 테이블 생성
sql = "create table sendTime (time varchar(10) )";
ExcuteSql(sql);
sql = "insert into sendTime values( '17' );";
ExcuteSql(sql);
//업무구분 테이블 생성
sql = "create table bizType (type varchar(30) )";
ExcuteSql(sql);
sql = "insert into bizType values( '전체' );";
ExcuteSql(sql);
//타입 선택 테이블 생성
//sql = "create table chceckType ( before char(1), anncm char(1) )";
//ExcuteSql(sql);
//타입 선택 데이터 입력
//sql = "insert into chceckType values( '0', '0' );";
//ExcuteSql(sql);
//로그 테이블 생성
sql = "CREATE TABLE history ( dt REAL DEFAULT(DATETIME('now')), errMsg TEXT); ";
ExcuteSql(sql);
}
}
catch (Exception e)
{
WriteLog(e.ToString());
return false;
}
return true;
}
public SQLiteDataReader SelectSql(string sql)
{
SQLiteDataReader sdr = null;
try
{
conn = new SQLiteConnection(sqlConnStr);
conn.Open();
SQLiteCommand command = new SQLiteCommand(sql, conn);
sdr = command.ExecuteReader();
}
catch (Exception e)
{
WriteLog(e.ToString());
}
/*finally
{
conn.Close();
}*/
return sdr;
}
public int ExcuteSql(string sql)
{
int result = 0;
try
{
conn = new SQLiteConnection(sqlConnStr);
conn.Open();
//WriteLog("sql : " + sql);
SQLiteCommand command = new SQLiteCommand(sql, conn);
result = command.ExecuteNonQuery();
}
catch (Exception e)
{
WriteLog(e.ToString());
}
/*finally
{
conn.Close();
}*/
return result;
}
public void WriteLog(String msg)
{
StreamWriter sw = new StreamWriter(Application.StartupPath + @"\log.txt", true);
sw.WriteLine(msg);
sw.Close();
}
}
}
반응형
'DEV > C#' 카테고리의 다른 글
2025년 차세대 나라장터 조회하기 - 개발환경 설명 (0) | 2025.07.21 |
---|---|
2025년 차세대 나라장터 조회하기_v0.2 (2) | 2025.06.16 |
2025년 차세대 나라장터 조회하기 (0) | 2025.05.26 |
크롤링으로 나라장터 검색-메일 전송 방식 변경 (0) | 2022.08.09 |
크롤링으로 나라장터 검색-크롬드라이버 업데이트 (1) | 2022.04.25 |