From 702ddda3d78613501dd701e443605cce8bde58a5 Mon Sep 17 00:00:00 2001 From: chodadoo Date: Fri, 13 Aug 2021 15:57:21 +0900 Subject: [PATCH] =?UTF-8?q?1.=20=EC=88=98=EC=8B=A0=20JSON=20=EC=96=91?= =?UTF-8?q?=EC=8B=9D=20=EB=B3=80=EA=B2=BD=202.=20VS=20=EC=B6=94=EC=B2=9C?= =?UTF-8?q?=20=EC=BD=94=EB=93=9C=20=ED=98=95=ED=83=9C=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=203.=20=EC=88=98=EC=8B=A0=20=EC=98=B5=EC=85=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SmartSearch/SmartSearch.cs | 360 ++++++++++++++++++++----------------- 1 file changed, 195 insertions(+), 165 deletions(-) diff --git a/SmartSearch/SmartSearch.cs b/SmartSearch/SmartSearch.cs index e7b8d00..2bd9344 100644 --- a/SmartSearch/SmartSearch.cs +++ b/SmartSearch/SmartSearch.cs @@ -4,14 +4,10 @@ using OpenQA.Selenium.Chrome; using OpenQA.Selenium.Support.UI; using SeleniumExtras.WaitHelpers; using System; -using System.Collections.Generic; using System.Collections.ObjectModel; -using System.ComponentModel; -using System.Data; using System.Diagnostics; using System.Linq; using System.ServiceProcess; -using System.Text; using System.Threading; using WebSocketSharp; using ThreadState = System.Threading.ThreadState; @@ -20,38 +16,34 @@ namespace SmartSearch { public partial class SmartSearch : ServiceBase { - private static Random m_Random = new Random(); + static readonly private Random m_Random = new Random(); - private static readonly string x00 = "w"; - private static readonly string x01 = "s"; - private static readonly string x02 = ":"; - private static readonly string x03 = "/"; - private static readonly string x04 = "/"; - private static readonly string x05 = "a"; - private static readonly string x06 = "p"; - private static readonly string x07 = "i"; - private static readonly string x08 = "."; - private static readonly string x09 = "i"; - private static readonly string x0A = "n"; - private static readonly string x0B = "r"; - private static readonly string x0C = "o"; - private static readonly string x0D = "s"; - private static readonly string x0E = "e"; - private static readonly string x0F = "."; - private static readonly string x10 = "c"; - private static readonly string x11 = "o"; - private static readonly string x12 = "m"; + static readonly private string x00 = "w"; + static readonly private string x01 = "s"; + static readonly private string x02 = ":"; + static readonly private string x03 = "/"; + static readonly private string x04 = "/"; + static readonly private string x05 = "a"; + static readonly private string x06 = "p"; + static readonly private string x07 = "i"; + static readonly private string x08 = "."; + static readonly private string x09 = "i"; + static readonly private string x0A = "n"; + static readonly private string x0B = "r"; + static readonly private string x0C = "o"; + static readonly private string x0D = "s"; + static readonly private string x0E = "e"; + static readonly private string x0F = "."; + static readonly private string x10 = "c"; + static readonly private string x11 = "o"; + static readonly private string x12 = "m"; - private static readonly string xFF = (x00 + x01 + x02 + x03 + x04 + x05 + x06 + x07 + x08 + x09 + x0A + x0B + x0C + x0D + x0E + x0F + x10 + x11 + x12); - - private WebSocket m_WebSocket = new WebSocket(xFF); + static readonly private string xFF = (x00 + x01 + x02 + x03 + x04 + x05 + x06 + x07 + x08 + x09 + x0A + x0B + x0C + x0D + x0E + x0F + x10 + x11 + x12); + readonly private WebSocket m_WebSocket = new WebSocket(xFF); private Thread m_Thread = new Thread(NaverSearcherExcute); - private static uint optPageMoveWaitMin = 2000; - private static uint optPageMoveWaitMax = 3000; - - private static uint optSearchWaitMin = 2000; - private static uint optSearchWaitMax = 6000; + static private uint optPageMoveWaitMin = 2000; + static private uint optPageMoveWaitMax = 3000; public SmartSearch() { @@ -65,8 +57,7 @@ namespace SmartSearch m_WebSocket.Send("{\"GUID\":\"" + Properties.Settings.Default.GUID + "\"}"); }; - m_WebSocket.OnMessage += (sender, e) => - { + m_WebSocket.OnMessage += (sender, e) => { JObject _JObject = JObject.Parse(e.Data); if (_JObject.ContainsKey("option")) @@ -78,7 +69,9 @@ namespace SmartSearch optPageMoveWaitMin = uint.Parse(_JObject_option.GetValue("PageMoveWaitMin").ToString()); if (optPageMoveWaitMin > optPageMoveWaitMax) + { optPageMoveWaitMax = optPageMoveWaitMin; + } } if (_JObject_option.ContainsKey("PageMoveWaitMax")) @@ -86,41 +79,30 @@ namespace SmartSearch optPageMoveWaitMax = uint.Parse(_JObject_option.GetValue("PageMoveWaitMax").ToString()); if (optPageMoveWaitMax < optPageMoveWaitMin) + { optPageMoveWaitMin = optPageMoveWaitMax; - } - - if (_JObject_option.ContainsKey("SearchWaitMin")) - { - optSearchWaitMin = uint.Parse(_JObject_option.GetValue("SearchWaitMin").ToString()); - - if (optSearchWaitMin > optSearchWaitMax) - optSearchWaitMax = optSearchWaitMin; - } - - if (_JObject_option.ContainsKey("SearchWaitMax")) - { - optSearchWaitMax = uint.Parse(_JObject_option.GetValue("SearchWaitMax").ToString()); - - if (optSearchWaitMax < optSearchWaitMin) - optSearchWaitMin = optSearchWaitMax; + } } } - if (_JObject.ContainsKey("key_pairs")) + if (_JObject.ContainsKey("keyword")) { if (m_Thread.ThreadState != ThreadState.Unstarted) + { m_Thread.Join(); + } if (m_Thread.ThreadState == ThreadState.Stopped) + { m_Thread = new Thread(NaverSearcherExcute); + } m_Thread.IsBackground = true; m_Thread.Start(_JObject); } }; - m_WebSocket.OnError += (sender, e) => - { + m_WebSocket.OnError += (sender, e) => { Trace.WriteLine(e.Message); if (m_Thread.ThreadState != ThreadState.Unstarted) @@ -133,8 +115,7 @@ namespace SmartSearch m_WebSocket.Close(); }; - m_WebSocket.OnClose += (sender, e) => - { + m_WebSocket.OnClose += (sender, e) => { Trace.WriteLine(e.Reason); if (m_Thread.ThreadState != ThreadState.Unstarted) @@ -155,88 +136,93 @@ namespace SmartSearch } - private static void NaverSearcherExcute(Object _Object) + static private void NaverSearcherExcute(object _Object) { - JObject _JObject = (JObject)_Object; - - ChromeOptions _ChromeOptions = new ChromeOptions(); - _ChromeOptions.AddArguments("disable-infobars"); - _ChromeOptions.AddArguments("--js-flags=--expose-gc"); - _ChromeOptions.AddArguments("--enable-precise-memory-info"); - _ChromeOptions.AddArguments("--disable-popup-blocking"); - _ChromeOptions.AddArguments("--disable-default-apps"); - _ChromeOptions.AddArguments("--headless"); - _ChromeOptions.AddArguments("start-maximized"); - _ChromeOptions.AddArguments("--window-size=1920x1080"); - _ChromeOptions.AddArguments("--lang=ko_KR"); - _ChromeOptions.AddArguments("--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36"); - _ChromeOptions.AddArguments("--app-version=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515"); - - _ChromeOptions.BinaryLocation = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\SmartSearch\\chrome.exe"; - - // 프록시 설정 - //Proxy proxy = new Proxy(); - //proxy.Kind = ProxyKind.Manual; - //proxy.IsAutoDetect = false; - //proxy.HttpProxy = - //proxy.SslProxy = ip; - //_ChromeOptions.Proxy = proxy; - //_ChromeOptions.AddArgument("ignore-certificate-errors"); - - ChromeDriverService _ChromeDriverService = ChromeDriverService.CreateDefaultService(); - _ChromeDriverService.HideCommandPromptWindow = true; - bool bResult = false; + JObject _JObjec_Result = null; try { - foreach (var key_words in _JObject["key_pairs"]) + // 멤버변수로 확장 시키는 코드 제거 하자 + + #region 수신 데이터 정리 + JObject _JObject = (JObject)_Object; + + // 옵션값 추출 + JToken _JToken_SearchWaitMin = _JObject.GetValue("SearchWaitMin"); + uint optSearchWaitMin = _JToken_SearchWaitMin == null ? 20000 : uint.Parse(_JToken_SearchWaitMin.ToString()); + + JToken _JToken_SearchWaitMax = _JObject.GetValue("SearchWaitMax"); + uint optSearchWaitMax = _JToken_SearchWaitMax == null ? 60000 : uint.Parse(_JToken_SearchWaitMax.ToString()); + + // 키워드 추출 + JToken JToken_keyword = _JObject.GetValue("keyword"); + + _JObjec_Result = JObject.Parse(JToken_keyword.ToString()); + #endregion + + ChromeOptions _ChromeOptions = new ChromeOptions(); + _ChromeOptions.AddArguments("disable-infobars"); + _ChromeOptions.AddArguments("--js-flags=--expose-gc"); + _ChromeOptions.AddArguments("--enable-precise-memory-info"); + _ChromeOptions.AddArguments("--disable-popup-blocking"); + _ChromeOptions.AddArguments("--disable-default-apps"); + _ChromeOptions.AddArguments("--headless"); + _ChromeOptions.AddArguments("start-maximized"); + _ChromeOptions.AddArguments("--window-size=1920x1080"); + _ChromeOptions.AddArguments("--lang=ko_KR"); + _ChromeOptions.AddArguments("--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36"); + _ChromeOptions.AddArguments("--app-version=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515"); + + _ChromeOptions.BinaryLocation = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + "\\SmartSearch\\chrome.exe"; + + // 프록시 설정 + //Proxy proxy = new Proxy(); + //proxy.Kind = ProxyKind.Manual; + //proxy.IsAutoDetect = false; + //proxy.HttpProxy = + //proxy.SslProxy = ip; + //_ChromeOptions.Proxy = proxy; + //_ChromeOptions.AddArgument("ignore-certificate-errors"); + + ChromeDriverService _ChromeDriverService = ChromeDriverService.CreateDefaultService(); + _ChromeDriverService.HideCommandPromptWindow = true; + + foreach (JToken key_words in _JObjec_Result["key_pairs"]) { - // 로그인 여부 확인 - // 로그아웃 실행 - // 네이버 메인 - // 스크롤 내린다. - // 20 ~ 60초 대기 - ChromeDriver _ChromeDriver = new ChromeDriver(_ChromeDriverService, _ChromeOptions); - - WebDriverWait _WebDriverWait = new WebDriverWait(_ChromeDriver, TimeSpan.FromSeconds(3)); + WebDriverWait _WebDriverWait = new WebDriverWait(_ChromeDriver, TimeSpan.FromSeconds(5)); try { _ChromeDriver.Navigate().GoToUrl(@"https://naver.com"); _WebDriverWait.Until(ExpectedConditions.ElementIsVisible(By.XPath("//*[@id=\"query\"]"))); + #region 네이버 로그아웃 string _logout = @"/html/body/div/div/div[1]/div[1]/a[1]"; if (IsElementPresent(_ChromeDriver, By.XPath(_logout))) { _ChromeDriver.FindElement(By.XPath(_logout)).Click(); } + #endregion - foreach (var key_word in key_words["key_words"]) + string _query_xpath = ""; + IWebElement _query_elment; + + foreach (JToken key_word in key_words["key_words"]) { - // 검색어 입력 (검색어 1) - // 검색어 확인 - // 스크롤 내린다. - // 20 ~ 60초 대기 - // 아무 게시글 클릭 - // 이동된 페이지 작업 - // 스크롤 내리기 - // 20 ~ 60초 대기 - // 새창 닫기 - try { _ChromeDriver.Navigate().GoToUrl(@"https://naver.com"); - string _query_xpath = "//*[@id=\"query\"]"; + _query_xpath = "//*[@id=\"query\"]"; _WebDriverWait.Until(ExpectedConditions.ElementIsVisible(By.XPath(_query_xpath))); - IWebElement _query_elment = _ChromeDriver.FindElement(By.XPath(_query_xpath)); + _query_elment = _ChromeDriver.FindElement(By.XPath(_query_xpath)); - foreach (var item in StringParser.CharacterMakeHistory(key_word["key_word"].ToString())) + foreach (string item in StringParser.CharacterMakeHistory(key_word["key_word"].ToString())) { _query_elment.Clear(); _query_elment.SendKeys(item); @@ -248,35 +234,13 @@ namespace SmartSearch PageMoveWait(_ChromeDriver); - ((IJavaScriptExecutor)_ChromeDriver).ExecuteScript("window.scrollBy(0, document.body.scrollHeight);"); + SearchWait(_ChromeDriver, optSearchWaitMin, optSearchWaitMax); - SearchWait(_ChromeDriver); - - ReadOnlyCollection links = _ChromeDriver.FindElements(By.CssSelector("a[href*='https://']")); - - int _try = links.Count; - - do - { - try - { - int _sel = m_Random.Next(0, links.Count); - links[_sel].Click(); - - break; - } - catch (Exception ex) - { - Console.WriteLine("=== 무작위 링크 접속 ==="); - Console.WriteLine(ex.Message); - } - } while (--_try > 0); + RandomClick(_ChromeDriver); PageMoveWait(_ChromeDriver); - ((IJavaScriptExecutor)_ChromeDriver).ExecuteScript("window.scrollBy(0, document.body.scrollHeight);"); - - SearchWait(_ChromeDriver); + SearchWait(_ChromeDriver, optSearchWaitMin, optSearchWaitMax); if (_ChromeDriver.WindowHandles.First() != _ChromeDriver.WindowHandles.Last()) { @@ -287,56 +251,74 @@ namespace SmartSearch } catch (Exception ex) { - Console.WriteLine("=== 검색어 ==="); - Console.WriteLine(ex.Message); + Trace.WriteLine("=== 검색어 ==="); + Trace.WriteLine(ex.Message); throw ex; } } + #region 비선형 검색 + + JToken _JToken_use_after = _JObject.GetValue("use_after"); + bool opt_use_after = _JToken_use_after == null ? false : bool.Parse(_JToken_use_after.ToString()); + + if (opt_use_after) + { + string[] random_keywords = { "음료", "음식", "간식", "식사", "밥", "물", "커피", "제조", "추천", "데이트", "장소", "순위", "방법" }; + + _ChromeDriver.Navigate().GoToUrl(@"https://naver.com"); + + _query_xpath = "//*[@id=\"query\"]"; + + _WebDriverWait.Until(ExpectedConditions.ElementIsVisible(By.XPath(_query_xpath))); + + _query_elment = _ChromeDriver.FindElement(By.XPath(_query_xpath)); + + foreach (string item in StringParser.CharacterMakeHistory(random_keywords[m_Random.Next(random_keywords.Length)])) + { + _query_elment.Clear(); + _query_elment.SendKeys(item); + + Thread.Sleep(m_Random.Next(500, 1000)); + } + + _query_elment.SendKeys(OpenQA.Selenium.Keys.Enter); + + PageMoveWait(_ChromeDriver); + + SearchWait(_ChromeDriver, optSearchWaitMin, optSearchWaitMax); + + RandomClick(_ChromeDriver); + + PageMoveWait(_ChromeDriver); + + SearchWait(_ChromeDriver, optSearchWaitMin, optSearchWaitMax); + } + + #endregion + bResult = true; } catch (Exception ex) { - Console.WriteLine("=== 검색어 페어 ==="); - Console.WriteLine(ex.Message); - - bResult = false; + Trace.WriteLine("=== 검색어 페어 ==="); + Trace.WriteLine(ex.Message); } finally { _ChromeDriver.Quit(); } } - - // 결과 던지기 - using (WebSocket _WebSocket = new WebSocket(xFF)) - { - _WebSocket.OnOpen += (sender, e) => { - _WebSocket.Send("{\"GUID\":\"" + Properties.Settings.Default.GUID + "\", \"keyword\":" + _JObject + ", \"done\":" + bResult.ToString().ToLower() + "}"); - }; - - _WebSocket.OnMessage += (sender, e) => { - }; - - _WebSocket.OnError += (sender, e) => { - }; - - _WebSocket.OnClose += (sender, e) => { - }; - - _WebSocket.Connect(); - - Thread.Sleep(5000); - } } catch (Exception ex) { - Console.WriteLine("=== 실행 ==="); - Console.WriteLine(ex.Message); + Trace.WriteLine("=== 실행 ==="); + Trace.WriteLine(ex.Message); } finally { + SendResult(_JObjec_Result, bResult); } } @@ -353,18 +335,66 @@ namespace SmartSearch } } - private static void PageMoveWait(IWebDriver _IWebDriver) + static private void SendResult(JObject _JObject, bool bResult) + { + // 결과 던지기 + using (WebSocket _WebSocket = new WebSocket(xFF)) + { + _WebSocket.OnOpen += (sender, e) => { + _WebSocket.Send("{\"GUID\":\"" + Properties.Settings.Default.GUID + "\", \"keyword\":" + _JObject + ", \"done\":" + bResult.ToString().ToLower() + "}"); + }; + + _WebSocket.OnMessage += (sender, e) => { + }; + + _WebSocket.OnError += (sender, e) => { + }; + + _WebSocket.OnClose += (sender, e) => { + }; + + _WebSocket.Connect(); + + Thread.Sleep(5000); + } + } + + static private void RandomClick(IWebDriver _IWebDriver) + { + ReadOnlyCollection links = _IWebDriver.FindElements(By.CssSelector("a[href*='https://']")); + + int _try = links.Count; + + do + { + try + { + int _sel = m_Random.Next(0, links.Count); + links[_sel].Click(); + + break; + } + catch (Exception ex) + { + Trace.WriteLine("=== 무작위 링크 접속 ==="); + Trace.WriteLine(ex.Message); + } + } while (--_try > 0); + } + + static private void PageMoveWait(IWebDriver _IWebDriver) { // 페이지 이동 후 대기 및 끝 탭 설정 Thread.Sleep(m_Random.Next((int)optPageMoveWaitMin, (int)optPageMoveWaitMax)); _IWebDriver.SwitchTo().Window(_IWebDriver.WindowHandles.Last()); } - private static void SearchWait(IWebDriver _IWebDriver) + static private void SearchWait(IWebDriver _IWebDriver, uint optSearchWaitMin, uint optSearchWaitMax) { // 페이지 이동 후 대기 및 끝 탭 설정 - Thread.Sleep(m_Random.Next((int)optSearchWaitMin, (int)optSearchWaitMax)); _IWebDriver.SwitchTo().Window(_IWebDriver.WindowHandles.Last()); + ((IJavaScriptExecutor)_IWebDriver).ExecuteScript("window.scrollBy(0, document.body.scrollHeight);"); + Thread.Sleep(m_Random.Next((int)optSearchWaitMin, (int)optSearchWaitMax)); } } }