[파이썬] 보안 뉴스 기사 크롤링하기 (제목, 본문 원하는만큼)
- 프로그래밍/파이썬
- 2020. 2. 7. 17:11
뉴스 기사 크롤링 첫번째 - 보안뉴스
뉴스 기사 크롤링, 뉴스 기사 크롤러 만들기 첫번째 대상은 '보안뉴스' 이다. 왜냐면 내가 보안 종사자이기 때문이다. 어쨌든 보안뉴스 #전체기사 부분에서 기사 제목과 본문, 날짜를 원하는 만큼 크롤링해서 txt 파일에 저장해본다.
파이썬 Selenium webdriver를 사용해 크롤링할 것이기 때문에 Selenium 사용법에 대한 설명은 아래 관련포스팅을 참고해주길 바란다.
관련포스팅
[파이썬] 동적 웹 크롤링 (3) - Selenium 사용법 (tag, class, xpath 등)
[파이썬] 동적 웹 크롤링 (1) - Selenium webdriver 설치 및 사용
보안 뉴스 기사 크롤링 방식 결정
뉴스 기사 하나만 크롤링하는게 아니라 원하는 만큼 반복적으로 크롤링을 해야하기 때문에 무작정 크롤링을 시작하는 것보단, 어떤 방식으로 url 반복문을 돌릴지 결정하는게 좋다. 난 전체기사를 크롤링할 것이기 때문에 먼저 전체기사 메뉴로 들어간 후, 첫번째에 있는 기사의 index가 어디에 있는지 확인했다.
아래 캡쳐 이미지 빨간 박스의 idx= 뒤에 인덱스가 저장되어 있는 것을 볼 수 있다.
첫번째 기사 인덱스는 위 부분을 파싱하면 되고 -1 씩 해주면서 반복적으로 크롤링해주면 되는데 다시 하나 결정해야할 것은 idx 뒤에 있는 page, kind 변수 처리를 어떻게 해줄지이다. 그래서 이것저것 테스트하고 있는데 허무한 것을 발견했다. idx만 맞으면 page와 kind를 안써주어도 기사에 접근이 가능한 것이다.
아래 캡쳐 이미지를 보면 '~idx=XXXXX&page=1&kind=2'와 '~idx=XXXXX' 결과가 동일하다. 뉴스 기사 크롤링은 처음이라 원래 이런식인지? 보안뉴스만 이런것인지 모르겠지만 어쨌든 뭐 편하게 됐다.
webdriver 객체 생성 및 보안뉴스 #전체기사 접근
self 때문에 class를 생성하는게 편해서 CRAWL 클래스를 생성해주겠다. 클래스 생성 후 parsing_news_url 함수에 보안뉴스의 #전체기사 URL을 넘겨준다. CRAWL.parsing_news_url에서는 Selenium webdriver 객체를 생성한 후 보안뉴스의 #전체기사에 접근한다.
import sys
import time
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
class CRAWL:
def __init__(self):
self.driver = ""
self.news_url=""
self.index=0
# 크롤링을 시작할 뉴스 기사 URL 구성을 위해 index를 가져옴
def parsing_news_url(self,url):
self.driver = webdriver.Chrome(ChromeDriverManager().install())
self.driver.get(url)
# 코드...
def crawling(self):
# 코드...
if __name__=="__main__":
# 보안뉴스 전체기사 URL
secu_news_all = "https://www.boannews.com/media/t_list.asp"
crawl = CRAWL()
crawl.parsing_news_url(secu_news_all)
crawl.crawling()
첫번째 기사 인덱스 파싱
idx를 -1 씩 해주면서 반복적으로 크롤링해줄 것이기 때문에 첫번째 기사의 인덱스를 파싱해야 한다.
find_element_by_id를 이용해서 'scroll_up' div 에 접근한 후 find_element_by_tag_name을 사용해 <a> 태그에 접근한 후 get_attribute로 href 속성 값을 얻어줄 것이다.
그럼 아래와 같은 순서대로 href 값에 접근할 수 있다.
depth_1=self.dirver.find_element_by_id("scroll_up")
depth_2=depth_1.find_element_by_tag_name("a")
depth_3=depth_2.get_attribute("href")
마지막으로, idx 부분을 잘라준 후 index에 저장해준다.
# 크롤링을 시작할 뉴스 기사 URL 구성을 위해 index를 가져옴
def parsing_news_url(self,url):
self.driver = webdriver.Chrome(ChromeDriverManager().install())
self.driver.get(url)
# 전체기사에서 첫 기사의 idx 가져오기
depth_1=self.driver.find_element_by_id("scroll_up")
depth_2=depth_1.find_element_by_tag_name("a")
depth_3=depth_2.get_attribute("href")
self.index = depth_3[44:49]
뉴스 기사 제목, 본문 크롤링하기
이제 URL도 다 구했으니 뉴스 기사 제목, 본문을 크롤링하는 일만 남았다. 제일 먼저, 크롤링한 내용을 써줄 txt를 열어준다.
def crawling(self):
# 크롤링 결과를 저장하기 위한 txt
f = open('secu_crawl.txt','w',encoding='utf-8')
그 후 원하는 만큼 반복문을 구성해주면 된다. 난 일단 테스트 겸 50까지 했는데 개인 취향에 따라 원하는 날짜를 인자로 받은 후에 해당 날짜까지만 반복하게끔 하거나 등등 응용을 하면 된다. (나도 이렇게 할 생각이다)
그리고, 위에서 구한 첫 인덱스부터 시작하도록 news_url을 구성해주고 Selenium webdriver를 사용해 url에 접근하기 전, 끊김 방지를 위해 sleep을 5정도로 준다. 처음에 sleep을 안줬었는데 계속 아래와 같이 'Connection ResetError 현재 연결은 원격 호스트에 의해 강제로 끊겼습니다.' 와 같은 에러가 발생하면서 중간에 강제로 끊겨서 구글링해봤는데 sleep으로 해결이 가능했다.
여기까지의 crawling() 함수 코드를 작성하면 아래와 같다.
def crawling(self):
# 크롤링 결과를 저장하기 위한 txt
f = open('secu_crawl.txt','w',encoding='utf-8')
for i in range(50):
# 위에서 구한 index를 넣어 URL을 구성 (index는 계속 -1 됨)
self.news_url = "https://www.boannews.com/media/view.asp?idx="+str(self.index)+"&page=1"
# 강제 끊김을 방지하기 위한 sleep
time.sleep(5)
self.driver.get(self.news_url)
이렇게 크롤링을 하다보면, 아래와 같은 alert 경고창을 만나게 된다. alert 경고창 처리에 관한 건 따로 포스팅도 썼는데 간단해서 그냥 여기서 확인해도 될 듯 하다.
alert 경고창 처리는 아래 코드와 같이 할 수 있다. switch_to_alert()를 사용해서 alert가 있는지 유무를 먼저 확인하고 dismiss()로 끄기 처리를 해버렸다. try, except 문이기 때문에 alert 경고창이 없는 경우에 대한 코드는 execpt 구문 밑에 작성해줄 것이다.
def crawling(self):
# 코드...
# alert 경고창 처리를 위한 try, except 구문
try:
is_alert = self.driver.switch_to_alert()
is_alert.dismiss()
except:
# 뉴스 기사 본문 텍스트에 접근
그럼 이제 마지막 단계이다. 뉴스 기사의 제목, 날짜, 본문에 접근해서 내용을 긁어오자. 먼저 제목과 날짜는 각각 div 태그의 "news_title02" id와 "news_util01" id에 저장되어 있다. find_element_by_id 로 접근하면 될 것이다. 대신 날짜는 "입력 : " 뒤에서부터 시작하므로 날짜 시작지점에 맞게 잘라준다.
그리고 뉴스 기사 본문은 div 태그의 "news_content" id에 저장되어 있다. 이것 또한 find_element_by_id로 접근해준다.
그럼 여기까지 코드는 아래와 같다.
def crawling(self):
# 코드...
# alert 경고창 처리를 위한 try, except 구문
try:
is_alert = self.driver.switch_to_alert()
is_alert.dismiss()
except:
# 뉴스 기사 제목,날짜,본문 텍스트에 접근
news_title=self.driver.find_element_by_id("news_title02").text
news_content=self.driver.find_element_by_id("news_content").text
news_date=self.driver.find_element_by_id("news_util01").text
news_date = news_date[10:20]
제대로 크롤링되고 있는지 바로 확인하기 위한 출력문과 파일에 써주는 부분, index를 -1 해주는 부분도 마저 작성한다.
# 출력
print("["+news_title+"]\n")
print(news_date+"\n")
print(news_content+"\n\n")
# 파일에 쓰기
f.write("["+news_title+"]\n")
f.write(news_date+"\n")
f.write(news_content+"\n\n")
# 다음 기사 크롤링을 위해 index -1 을 해줌
self.index = int(self.index)
self.index -= 1
그리고 마지막으로 열었던 webdriver 객체와 open 객체 를 닫아주면 끝이다.
f.close()
self.driver.close()
보안뉴스 기사 크롤링 결과는 아래와 같다.
그 사이에 새 기사가 떴다!
어쨌든, 이제 이렇게 크롤링한 데이터를 가지고 본인이 원하는 응용을 마음껏 수행하면 된다. 나는 명사 단어만 가지고 빈도수 순으로 키워드를 추출해서 시각화하는 방법을 생각해보고 있다.
보안 뉴스 기사 전체 크롤링 코드
그럼, 아래에 전체 코드를 제시하면서 이번 포스팅을 마친다.
import sys
import time
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
class CRAWL:
def __init__(self):
self.driver = ""
self.news_url=""
self.index=0
# 크롤링을 시작할 뉴스 기사 URL 구성을 위해 index를 가져옴
def parsing_news_url(self,url):
self.driver = webdriver.Chrome(ChromeDriverManager().install())
self.driver.get(url)
# 전체기사에서 첫 기사의 idx 가져오기
depth_1=self.driver.find_element_by_id("scroll_up")
depth_2=depth_1.find_element_by_tag_name("a")
depth_3=depth_2.get_attribute("href")
self.index = depth_3[44:49]
def crawling(self):
# 크롤링 결과를 저장하기 위한 txt
f = open('secu_crawl.txt','w',encoding='utf-8')
for i in range(50):
# 위에서 구한 index를 넣어 URL을 구성 (index는 계속 -1 됨)
self.news_url = "https://www.boannews.com/media/view.asp?idx="+str(self.index)+"&page=1"
# 강제 끊김을 방지하기 위한 sleep
time.sleep(5)
self.driver.get(self.news_url)
# alert 경고창 처리를 위한 try, except 구문
try:
is_alert = self.driver.switch_to_alert()
is_alert.dismiss()
except:
# 뉴스 기사 본문 텍스트에 접근
news_title=self.driver.find_element_by_id("news_title02").text
news_content=self.driver.find_element_by_id("news_content").text
news_date=self.driver.find_element_by_id("news_util01").text
news_date = news_date[10:20]
# 출력
print("["+news_title+"]\n")
print(news_date+"\n")
print(news_content+"\n\n")
# 파일에 쓰기
f.write("["+news_title+"]\n")
f.write(news_date+"\n")
f.write(news_content+"\n\n")
# 다음 기사 크롤링을 위해 index -1 을 해줌
self.index = int(self.index)
self.index -= 1
f.close()
self.driver.close()
if __name__=="__main__":
# 보안뉴스 전체기사 URL
secu_news_all = "https://www.boannews.com/media/t_list.asp"
crawl = CRAWL()
crawl.parsing_news_url(secu_news_all)
crawl.crawling()
'프로그래밍 > 파이썬' 카테고리의 다른 글
파이썬 KoNLPy를 사용한 한글 명사 추출 및 빈도 계산 (28) | 2020.02.14 |
---|---|
KoNLPy (파이썬 한글 형태소 분석기 ) 윈도우 설치 방법 (9) | 2020.02.14 |
[파이썬] Selenium alert 경고창 처리하기 (8) | 2020.02.07 |
[파이썬] 동적 웹 크롤링 (4) - Selenium을 이용한 비트코인 거래소 크롤링 (5) | 2020.02.01 |
[파이썬] winreg 모듈을 사용한 레지스트리 등록 (윈도우 자동업데이트 해제) (0) | 2020.01.30 |