Selenium을 이용한 네이버 기사 10페이지 제목 리스트 스크레이핑!(크롤링)

* Selenium을 이용한 네이버 기사 10페이지 제목 리스트 스크레이핑!(크롤링)


실제 개발 시 구글링을 통해 참고하다보니 쓸데 없이 긴 글 보다 짧지만 정확한 정보가 있는 글이 몰입감이 훨씬 높다는 사실을 깨달았다. 그래서 필요한 과정만 정확히 쓰는 습관을 들이도록 하겠당.. = =

저번 포스팅에서 예고했던 것 처럼, 스크레이핑 툴인 셀레니움을 이용해 네이버 IT/과학 홈에 있는 기사 제목 200개를 스크레이핑 해보겠다. IDE은 주피터 노트북을 사용하겠다.

주피터 노트북은 터미널 창에서 pip install jupyter 를 입력하면 설치 할 수 있고, 파일들이 있는 폴더에서 Bash shell을 실행해 jupyter notebook 을 입력하면 실행시킬 수 있다.

* 바로 이 부분의 제목을 스크레이핑 할 것이다.

1. 스크레이핑을 위한 Selenium 설치

이곳에 셀레니움 설치 방법이 나와있다. 조금 수정하자면

  • 현재 ChromeDriver는 최신 버전이 2.4다. 받아준다.
  • chromedriver.exe를 굳이 D:\로 이동해주지 않아도 된다. 아래 예제에 경로가 이렇게 나와 있는데, D:/chromedriver에 해당하는 부분을 chromedriver.exe 파일이 있는 경로로 수정만 하면 된다.
1
driver = webdriver.Chrome('D:/chromedriver') # D:/chromedriver 부분을 수정해주자.


설치가 끝났으면 주피터 노트북을 켜고 New file을 만들어주고, 첫 줄에

1
2
3
from selenium import webdriver
import time
driver = webdriver.Chrome()

를 입력해주자. 동작을 하지 않는다면 () 안에 들어갈 부분을 적절하게 수정해주자. 그럼 아래와 같은 창이 뜬다.

Chrome이 자동화된 테스트 소프트웨어에 의해 제어되고 있습니다. 라는 멘트가 의미심장하다. 바로 이 새로운 Chrome 창에서 우리가 입력하는 명령어들이 수행된다.

import 는 추후 페이지를 이동 할 때 1초의 Delay를 걸어주기 위한 모듈이다. 일단 임포트 해주자.


2. 스크레이핑 할 네이버 기사 타이틀을 긁어오기
1
driver.get("http://news.naver.com/main/main.nhn?mode=LSD&mid=shm&sid1=105")

get 명령어를 통해 해당 URL로 이동한다. 그럼 자동화된 Chrome창이 아래와 같이 보일 것이다.

이어서

1
time.sleep(1)

코드를 추가해준다. 웹 페이지가 읽어들여질 때 까지 잠깐 기다려 주는 것이다. get 으로 웹페이지를 읽어준 후 추가해주는게 가장 효율적이다.

1
articles = driver.find_elements_by_css_selector('#section_body > ul > li > dl > dt > a')

그리고 기사 목록을 읽어들여준다. find_elements_by_css_selector 명령어를 사용해주는데, 저번 포스팅에서 사용했던 requests 모듈을 이용한 방식이 아닌 CSS Selector 방식을 사용하겠다.

CSS Selector에 대해 잘 모르겠다면, 이 곳을 참고하자. 너무나도 잘 설명되어 있다.


F12 를 눌러 개발자 도구로 들어간다. 그리고 빨간색 원 부분을 눌러준다. 단축키로는 Ctrl+Shift+C 이다.

스크롤을 아래로 내리면 기사가 시작되는 부분 가장 위에 배틀그라운드 모바일, 매출 순위 다시 급상승 이라는 기사 제목이 있다.(물론 기사가 계속 바뀌므로 다른 제목이 보일 것이다.) 이를 눌러주면 오른쪽 연한 파란 상자가 해당 제목이 들어가있는 html 코드 부분을 선택해준다.

오른쪽 연한 파란 상자 부분을 오른쪽으로 클릭한 후 Copy -> Copy selector 을 클릭하면

#section_body > ul.type06_headline > li:nth-child(1) > dl > dt:nth-child(2) > a

가 복사된다. 오른쪽으로 갈 수록 하위 코드로 내려가게 된다. 하나하나 간단하게 뜯어보자.


  1. #section_body : 앞에 #id 를 나타낸다.

왼쪽은 id="section_body" 가 해당되는 범위이고, 오른쪽 파란 박스는 해당 id가 포함된 코드 부분이다.

class="section_body" 를 나타내는 .section_body 로 대체 할 수 있다.


  1. ul.type06_headline : ul 뒤의 .type06_headlineclass 를 나타낸다.

HTML에서 목록을 나타내는 태그인 ul 는 순서가 없는 목록이며, ol 은 순서가 있는 목록이다.

ul의 u는 위로 구멍이 뚫려 있으므로 제한이 없고, ol의 o는 구멍이 뚫려있지 않으므로 제한이 없다고 기억하자.

ul.type06_headline = ul + . + type06_headline 이라고 생각하면 된다.


  1. li:nth-child(1) : li 태그 밑에 붙는 nth-child(1) 에 대해 궁금하다면 이 곳을 참고한다. 카인드데스네~
  2. dl
  3. dt:nth-child(2)
  4. a

들의 설명은 생략하겠다.. 링크 글을 읽었다면 쉽게 이해할 수 있다. 모르면 댓글로..


결국, #section_body > ul.type06_headline > li:nth-child(1) > dl > dt:nth-child(2) > a CSS Selector 코드는 '#section_body > ul > li > dl > dt > a' 코드로 변경된다. (#section_body.section_body 로 변경해도 상관 없다.)


3. 10페이지 기사 제목을 모두 담기

이를 article_Scraping 함수로 만들면 다음과 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
article_list = []
def article_Scraping():
driver = webdriver.Chrome()
for i in range(1, 11):
driver.get("http://news.naver.com/main/main.nhn?\
mode=LSD&mid=shm&sid1=105#&date=%2000:00:00&page=" + str(i))
time.sleep(1)
articles = driver.find_elements_by_css_selector('#section_body > ul > li > dl > dt > a')
for article in articles:
if article.text == "동영상기사":
pass
elif len(article.text) != 0:
article_list.append(article.text)
driver.quit()
for article in article_list:
print(article)

article_Scraping()
  1. article_list : 1부터 10페이지의 모든 제목이 담길 list이다.
  2. article_Scraping : 10페이지 기사 제목을 담을 명령을 가진 함수를 만들었다.
  3. driver : chromedriver 실행!
  4. for문 (1) : 1부터 10페이지까지 1페이지 당 20개의 기사 제목들을 article_list 에 담는 노가다를 해준다.
  5. driver.get : 페이지를 이동해준다. 1페이지 주소는 아래와 같이 이루어져 있다.

끝에 있는 page=11 부분만 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 으로 바꿔주면 된다.

그래서 for문 (1)range 를 1부터 11까지 잡은 것이다.

  1. time.sleep : get 명령어로 1초 동안 다음 명령어로 움직이지 않고 쿨쿨 자준다.
  2. articles : CSS Selector로 기사가 있는 경로로 접근해준다. 최종 도착점은 a 태그이다. 하지만, articles를 무턱대고 출력하면 아래와 같은 결과가 나온다.

모든 텍스트를 출력하다보니 아무 내용 없는 "" 부분도 출력해버리게 된다. 걸러야 할 부분은 두 가지이다.

  • "동영상기사" 라는 내용이 입력된 기사의 Text
  • "" 로서 Text 길이가 0인 Text
  1. for article in articles: : 첫 번째로 article.text"동영상기사" 인지 판단하여 맞으면 pass.
    두 번째로 article.text 의 길이가 0 이 아니면(0이면 pass인거임) article_listappend.
    두 조건의 순서가 뒤바뀌면 안된다.
  2. driver.quit : article_list 에 모든 기사 제목이 입력되었기 때문에 chromedriver 를 끈다.
  3. article_list 에 있는 모든 article 을 출력한다.
  4. article_Scraping 함수를 실행한다.

결과는 아래와 같다.

기사 제목이 한 줄씩 출력된다. 1페이지에 20개 기사씩, 총 200개의 기사 제목이 출력되는 것이다.


어떻게 보면 기초적인 스크레이핑지만, 생각보다 자잘한 조건들을 찾아서 넣어줘야 했다.

스크레이핑(크롤링)은 노가다다. 노가다를 즐기도록 하자.


* 더 궁금한 부분이 있다면, 댓글을 남겨주세요. 바로 대답 드리겠습니다.