728x90
반응형

웹 이벤트를 자동(batch)수행하기 위해 Selenium기반으로 C#으로 접근해 보았습니다.

 

기능하고자 한 것은

   1. 신문사의 특정 기사에 접근

   2. Tag를 찾아내서  그 하이퍼링크된 주소를  클릭

   3. 새창으로 열린 창으로 접근

   4. 특정 iframe을 찾기 및 iframe 선택

   5. Javascript 구문을 수행하기

   6. PageSource에 접근하여 내용 수정

   7. 페이지 코드를 파일로 저장

 

 

728x90

 

 

ChromdeDriver를 생성하여 그 인터페이스(Interface)를 사용합니다.

IWebDriver driver = new ChromeDriver(options)

       

 

크롬 웹브라우저를 열 URL을 지정합니다. 반환값은 처리한 URL입니다. 즉, 그대로 출력합니다.

 string strResult = driver.Url = "https://www.etnews.com/20230331000229";   // implicitly  wait until the load is complete.
 Console.WriteLine(strResult);

 

 

제대로 URL이 열렸는지는 Title 값을 활용하여 Heuristic하게 프로그래밍 했습니다.

 if (driver.Title.IndexOf("missing.html") == -1)

 

 

특정 태그('a')를 찾아 그 이름이 "Englisth"일 경우,  그 하이퍼링크 URL을 호출(click)합니다. 

IList<IWebElement> links = driver.FindElements(By.TagName("a"));
//Console.WriteLine(links[0].Text);
//links.First(element => element.Text == "English").Click();
foreach (var link in links)
{
    Console.WriteLine(link.Text);
    if (link.Text == "English")
    {
        Console.WriteLine(link.GetAttribute("href"));
        link.Click();
        break;
    }
}

 

 

'새창'으로 열렸기 때문에,  제어권을 '새창'으로 옮깁니다.(SwitchTo)

string originWindow = driver.CurrentWindowHandle;
Console.WriteLine(originWindow);
foreach (string window in driver.WindowHandles)
{
    //새창을 찾는다.
    if (originWindow != window)
    {
        Console.WriteLine(window);
        driver.SwitchTo().Window(window);
        break;
    }
}

 

 

특정 iFrame 요소를 찾습니다.

List<IWebElement> frames = new List<IWebElement>(driver.FindElements(By.TagName("iframe")));
Console.WriteLine("Number of Frames: " + frames.Count);
var bFoundResultPage = 0;
for (int i = 0; i < frames.Count; i++)
{
    Console.WriteLine("frame[" + i + "]: " + frames[i].GetAttribute("id").ToString());
    if (frames[i].GetAttribute("id").ToString() == "CSLiResulPage")
    {
        bFoundResultPage = 1;
    }
}

 

특정 iFrame을 사용합니다.

driver.SwitchTo().Frame("CSLiResultPage");

 

JavaScript를 수행하여, 속성을 바꾸어 봅니다.

IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
//js.ExecuteScript("window.open()");
js.ExecuteScript("document.getElementsByTagName(\"html\")[0].setAttribute(\"lang\",\"en\") ");

 

웹페이지소스코드의 내용을 수정해 봅니다.

string aaa = driver.PageSource.ToString();
string bbb = aaa.Replace("https://trans.etnews.com", "http://klaud.between.io");
//Console.WriteLine(bbb);

 

 

 

 

 

전체 소스코드는 아래와 같습니다.

( 메모리 최적화 delete ,   sleep 대신에 await 등 처리 대기 등은  더 최적화 되어야 합니다.^^)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.IO;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium;

namespace WebCrawler
{
    static class Program
    {
        static void Main(string[] args)
        {
            // ChomeDriver 인스턴스 생성                        
            ChromeOptions options = new ChromeOptions();
            options.AddArguments("--test-type");
            options.AddArguments("--ignore-certificate-errors");
                                    
            using ( IWebDriver driver = new ChromeDriver(options) )
            {
                // URL로 접속 
                string strResult = driver.Url = "https://www.etnews.com/20230331000229";   // implicitly  wait until the load is complete.
                Console.WriteLine(strResult);

                if (driver.Title.IndexOf("missing.html") == -1)
                {

                    // 대기 설정. (find로 객체를 찾을 때까지 검색이 되지 않으면 대기하는 시간 초단위)
                    driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(2);

                    Thread.Sleep(1000);

                    IList<IWebElement> links = driver.FindElements(By.TagName("a"));
                    foreach (var link in links)
                    {
                        Console.WriteLine(link.Text);
                        if (link.Text == "English")
                        {
                            Console.WriteLine(link.GetAttribute("href"));
                            link.Click();
                            break;
                        }
                    }


                    // 5초 기다린다.
                    Thread.Sleep(5000);

                    // 기존창 대신에 새창에서 열린다.
                    string originWindow = driver.CurrentWindowHandle;
                    Console.WriteLine(originWindow);
                    foreach (string window in driver.WindowHandles)
                    {
                        //새창을 찾는다.
                        if (originWindow != window)
                        {
                            Console.WriteLine(window);
                            driver.SwitchTo().Window(window);
                            break;
                        }
                    }

                    // iFrame 찾기
                    List<IWebElement> frames = new List<IWebElement>(driver.FindElements(By.TagName("iframe")));
                    Console.WriteLine("Number of Frames: " + frames.Count);
                    var bFoundResultPage = 0;
                    for (int i = 0; i < frames.Count; i++)
                    {
                        Console.WriteLine("frame[" + i + "]: " + frames[i].GetAttribute("id").ToString());
                        if (frames[i].GetAttribute("id").ToString() == "CSLiResulPage")
                        {
                            bFoundResultPage = 1;
                        }
                    }

                    if (bFoundResultPage == 1)
                    {
                        driver.SwitchTo().Frame("CSLiResultPage");
                        
                        IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
                        js.ExecuteScript("document.getElementsByTagName(\"html\")[0].setAttribute(\"lang\",\"en\") ");


                        string aaa = driver.PageSource.ToString();
                        string bbb = aaa.Replace("https://trans.etnews.com", "http://klaud.between.io");
                        //Console.WriteLine(bbb);


                        File.WriteAllText("C:\\UsersDownloads\\PageSource.html", bbb);
                        //File.WriteAllText("C:\\UsersDownloads\\PageSource.html", driver.PageSource);

                        // 5초 기다린다.
                        Thread.Sleep(1000);
                    }                    
                }
                driver.Quit();
            }
           
            // 아무 키나 누르면 종료
            Console.WriteLine("Press any key...");
            Console.ReadKey();
        }

    }
}
728x90
반응형

+ Recent posts