c#프로젝트

데이터마이닝2(크롤링 c# selenium)

He110 2019. 3. 10. 22:47

안녕하세요.. 오늘도 좋은 하루 보내고 계신가요? ^^ 저는 블로그를 처음 시작해서 약간 글쓰는 게 어색하지만 너그럽게 봐주세요..

Form1.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 OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using System.Threading;

using OpenQA.Selenium은 nuget패키지를 통해 다운받은 selenium패키지를 사용한다는 것을 뜻합니다.  


Thread Search_1 = null;
Thread Upload_1 = null;

IWebDriver driver = null;
String[,] str = null;
        
int num1 = 0;
int num2 = 0;

int eCount = 0;

먼저 FORM CLASS안에 다음과 같이 구성을 해줍니다.  먼저 Search_1 스레드는 말 그대로 데이터를 서치해주는 스레드이고 Upload_1스레드는 Search_1스레드를 통해 수집한 데이터를 listview에 띄우는 역할을 합니다. driver는 browser(chrome)을 통해 데이터 수집을 하는 역할을 합니다. str은 2차원 배열로 title하고 사이트 url를 저장 할 공간입니다. num1과 num2는 이후 반복문을 통해 데이터를 str에서 listview로 옮길때 사용할 것입니다. eCount는 배열의 공간 length를 저장해 listview로 데이터를 옮기는 과정에 사용될 것입니다. 



private void Form_Load(object sender, EventArgs e)
 {
            driver = new ChromeDriver();
 }

이제 Form디자이너를 더블클릭하면 Form의 프로시저가 형성됩니다. 이후 driver의 개체를 new ChromeDriver()로 초기화 시켜줍니다.



 private void btnSearch_Click(object sender, EventArgs e)
{
           
            Search_1 = new Thread(Search1);
            Search_1.Start();
}

검색버튼를 더블클릭하면 다음과 같은 이벤트가 형성됩니다. 혹시 아직 디자인을 구성하지 않으신 분은 1편을 참고해주세요...^^ Search_1스레드의 개체를 Search1함수로 초기화 시켜줍니다.


Search1함수 설명에 앞서서 chrome개발자도구옵션을 통해 수집할 데이터를 확인해보도록 하겠습니다.

먼저 구글 주소를 살펴보겠습니다.

https://www.google.com/search?q=맛있는 음식

다음과 같은 구조에 대해 설명하겠습니다. q라는 쿼리에 사용자에 검색값을 넣어 웹에 전송해 그에 대한 결과를 다시 웹을 통해 사용자에게 띄어줍니다.

이제 chrome을 켜주시고 맛있는 음식을 검색하신후 F12(개발자옵션)단축키를 PRESS합니다.


이제 웹사이트 소스코드를 분석해 데이터를 찾아보겠습니다.

저걸 클릭해주시고 밑에 사진과 같이 해줍니다.


이제 소스코드를 확인해보겠습니다.

저 소스코드를 보시면 class name이 "r"인 것을 확인 하실 수 있습니다.  제가 원하는 데이터는 h3태그에 들어있는 text값입니다.  IList<IWebElement> e1 = driver.FindElements(By.ClassName("r"));  다음과 같은 e1의 list를 초기화 시켜줘서 데이터를 수집하는 알고리즘을 작성할 것입니다. 


그 밑에 코드를 보면 class name이 "TbwUpd"인 것을 보실 수 있습니다. 이것을 이용해서 

IList<IWebElement> e2 = driver.FindElements(By.ClassName("TbwUpd")); 다음과 코드를 작성해줍니다. 이 코드를 이용해서 제목에 해당하는 cite url를 추출할 것 입니다. 


이제 다음과 같은 Search1()함수를 구성해줍니다.

private void Search1()
{
            driver.Manage().Window.Maximize();
            driver.Url = "https://www.google.com/search?q="+this.tbSearch.Text; //데이터 쿼리 전송

            for (int BTNcounT = 1; BTNcounT <5; BTNcounT++) //총 4페이지까지의 데이터를 수집합니다.
            {
                Thread.Sleep(3500);

               IList e1 = driver.FindElements(By.ClassName("r"));
               IList e2 = driver.FindElements(By.ClassName("TbwUpd"));  

                if (BTNcounT == 1)
                {
                    eCount = e1.Count * 10;

                    str = new string[e1.Count * 10, 2];
                }

                int Forcount = 0;
                foreach (IWebElement i in e1)
                {
                    str[num1, num2] = i.FindElement(By.TagName("h3")).Text;
                    str[num1, num2+1] = e2[Forcount].FindElement(By.TagName("cite")).Text;
                    Forcount++;
                    num1++;
                }


                string xpath = "//a[contains(text()," + "'" + (BTNcounT+1).ToString() + "')]";
                
                driver.FindElement(By.XPath(xpath)).Click();
            }
            
             Upload_1 = new Thread(Upload1);
       }

   str[num1, num2] = i.FindElement(By.TagName("h3")).Text;

 str[num1, num2+1] = e2[Forcount].FindElement(By.TagName("cite")).Text;

ClassName이 "r"하고"TbwUpd"인 것을 list로 받고 받은 list를 foreach문을 돌려 h3 tag를 검색하여 원하는 데이터를 추출합니다.


이제 Upload_1스레드를 Upload1함수를 이용해 초기화 시켜줍니다. 이제 Upload1함수를 작성하겠습니다.

다음의 코드는 수집한 데이터를 listview에 보여지도록 하는 코드입니다.

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 OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using System.Threading;

namespace c_sharp_Crawling1
{

    public partial class Form : System.Windows.Forms.Form
    {
        Thread Search_1 = null;
        Thread Upload_1 = null;

        IWebDriver driver = null;
        String[,] str = null;
        
        int num1 = 0;
        int num2 = 0;

      int eCount = 0;

        public Form()
        {
            InitializeComponent();
        }

        private void btnSearch_Click(object sender, EventArgs e)
        {
           
            Search_1 = new Thread(Search1);
            Search_1.Start();
        }

        private void Search1()
        {
            driver.Manage().Window.Maximize();
            driver.Url = "https://www.google.com/search?q="+this.tbSearch.Text;

            for (int BTNcounT = 1; BTNcounT <5; BTNcounT++)
            {
                Thread.Sleep(3500);

                IList<IWebElement> e1 = driver.FindElements(By.ClassName("r"));
                IList<IWebElement> e2 = driver.FindElements(By.ClassName("TbwUpd"));

                if (BTNcounT == 1)
                {
                    eCount = e1.Count * 10;

                    str = new string[e1.Count * 10, 2];
                }

                int Forcount = 0;
                foreach (IWebElement i in e1)
                {
                    str[num1, num2] = i.FindElement(By.TagName("h3")).Text;
                    str[num1, num2+1] = e2[Forcount].FindElement(By.TagName("cite")).Text;
                    Forcount++;
                    num1++;
                }


                string xpath = "//a[contains(text()," + "'" + (BTNcounT+1).ToString() + "')]";
                
                driver.FindElement(By.XPath(xpath)).Click();
            }
            
             Upload_1 = new Thread(Upload1);
            Upload_1.Start();
        }

        private void Upload1()
        {
            ListViewItem item = null;

            for(int i=0; i<eCount; i++)
            {
                if (str[i, 0] == null)
                    break;

                item = new ListViewItem(new string[] { str[i, 0], str[i, 1] });

                lvView1.Items.Add(item);
            }
           
            
        }

        private void Form_Load(object sender, EventArgs e)
        {
            driver = new ChromeDriver();
        }
    }
}

Ctrl+F5 단축키를 눌러 컴파일을 완료합니다.


다음 사진은 컴파일된 프로그램이 수집한 데이터들입니다.

이상 C#에 관심많은 고등학생이었습니다. 감사합니다.

다음 3편도 기대해주세요!!