파이썬/크롤링

[python-파이썬] 7 네이버에서 종목뉴스 크롤링 (crawling) - 2탄

모두의 실험실 2022. 4. 21. 21:05
728x90

안녕하세요. 모두의 파이썬입니다. 1탄에 이어서 2탄을 진행하겠습니다. 모두의 파이썬은 결과물을 만들어 내면서 학습하는 방식으로 진행하고 있습니다. 다소 기초가 탄탄하지 않더라도, 끊임없이 결과물을 만들면, 높은 경지에 도달할 것입니다. 암기한다기보다는 문제를 해결하는 능력을 배운다고 생각하십시오. 앞서 배운 것들을 키워드로 나열해 보겠습니다. '구글링', '포기 않기', 'F12', '우 클릭>검사', 'tag', 'find_all('div' ,{'class','xxx'})' 기타 등등 많이 있습니다. 구구단도 얼마나 많이 듣고 말했나요. 모든 게 같습니다. 반복을 하면 어느새 체화됩니다.

전체 글을 요약하면, 네이버 뉴스 검색 페이지에서 뉴스 정보 크롤링입니다.

1탄에서 검색 페이지의 주소 얻는 방법을 실습했습니다. 2탄에서는 페이지에서 뉴스 목록을 얻고, 하나의 뉴스에서 뉴스 제목, 뉴스 url, 뉴스 출처, 뉴스 본문 요약을 얻어보겠습니다. 시작하기에 앞서 1탄에서 실습한 페이지 url 주소 얻는 코드를 함수로 변환하겠습니다. 코드 참조하세요.

 

 

In [38]:
#네이버에서 종목뉴스 크롤링 (crawling)
## datetime은 날짜 시간을 다루는 package
from datetime import datetime, timedelta
##HTTP를 호출하는 프로그램을 작성할 때 주로 사용한다
import requests
## html의 내용을 사용자가 활용하기 쉽게 하기위해 사용한다
from bs4 import BeautifulSoup 

## 네이버 뉴스검색 page url얻는 함수
def get_news_page_url(stock_name,hour_delta):
    ## strftime을 사용하여 string형태로 변환
    now_time = datetime.now().strftime('%Y.%m.%d.%H.%M') 
    ##timedelta사용하여 해당 시간단위를 이동, 아래예제는 3일을 이동
    start_time = (datetime.now()-timedelta(hours=hour_delta)).strftime('%Y.%m.%d.%H.%M') 
    page_num = 1
    #stock_name = '삼성전자'

    url = 'https://search.naver.com/search.naver?where=news&sm=tab_pge&query=' +  stock_name + \
    '&sort=1&photo=0&field=0&pd=9&ds=' + start_time +'&de=' + now_time + \
        '&mynews=0&office_type=0&office_section_code=0&news_office_checked=&nso=so:dd,p:all,a:all&start=' + \
            str((page_num-1)*10 + 1)

    ## 브라우저 호환을 위해서 설정
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '+ \
        '(KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'
                } 

    ##해당 url에 htlm(정보) 요청에사용 / url은 사용자가 원하는 url
    r = requests.get(url, headers=headers) 
    ## 해당 url의 html을 사용자가 활용하기 쉽게 변환
    html = BeautifulSoup(r.content, 'html.parser')
    tmp = []
    ## try/except 구문을 사용하여 예외처리
    try:
        ## page주소 정보를 가지고 있는 'tag'
        tmp = html.find('div',{'class', 'sc_page_inner'}).find_all('a') 
    except:
        pass

    ##저장될 비어있는 주소리스트 선언
    l_address = []
    ##전체 주소리스트를 l_address에 저장
    for i in tmp:
        tmp_add = 'https://search.naver.com/search.naver'+i.get('href')
        l_address.append(tmp_add)
    return l_address

print(get_news_page_url('삼성전자',2)) ##종목은 삼성전자 지금부터 2시간 전까지의 뉴스 url page주소 얻기
 
['https://search.naver.com/search.naver?where=news&sm=tab_pge&query=%EC%82%BC%EC%84%B1%EC%A0%84%EC%9E%90&sort=1&photo=0&field=0&pd=9&ds=2022.04.22.18.30&de=2022.04.22.21.30&mynews=0&office_type=0&office_section_code=0&news_office_checked=&nso=so:dd,p:all,a:all&start=1', 'https://search.naver.com/search.naver?where=news&sm=tab_pge&query=%EC%82%BC%EC%84%B1%EC%A0%84%EC%9E%90&sort=1&photo=0&field=0&pd=9&ds=2022.04.22.18.30&de=2022.04.22.21.30&mynews=0&office_type=0&office_section_code=0&news_office_checked=&nso=so:dd,p:all,a:all&start=11', 'https://search.naver.com/search.naver?where=news&sm=tab_pge&query=%EC%82%BC%EC%84%B1%EC%A0%84%EC%9E%90&sort=1&photo=0&field=0&pd=9&ds=2022.04.22.18.30&de=2022.04.22.21.30&mynews=0&office_type=0&office_section_code=0&news_office_checked=&nso=so:dd,p:all,a:all&start=21']

 

page주소를 기반으로 뉴스출처/ 뉴스제목/ 뉴스url/ 뉴스본문을 크롤링하는 함수를 구현하겠습니다. 지금까지 실습하고 구현한 코드로 충분히 해결할 수 있습니다. 'F12'클릭 그리고 'tag'정보 찾기 이것만 할 수 있으면, 모두 구현할 수 있습니다. 

 

ⓒ삼성전자 뉴스 3시간전 최신순 검색결과 첫페이지, 출처 네이버검색

 

페이지에서 'tag'정보를 각각 확인할 수 있습니다. find_all('ul',{'class','list_news'})은 뉴스 전체 리스트이며, 리스트 첫째 항목을 선택하여, 뉴스 정보를 크롤링 합니다. 뉴스 출처는 find('div',{'class','info_group'}).find('a').text, 뉴스 제목은 find('a',{'class','news_tit'}).text, 뉴스 url은 find('a',{'class','news_tit'}).get('href'), 그리고 뉴스 본문은 find('div',{'class','dsc_wrap'}).text의 tag에서 구할 수 있습니다. 코드 참조하세요.

 

 

In [57]:
#네이버에서 종목뉴스 크롤링 (crawling)
## datetime은 날짜 시간을 다루는 package
from datetime import datetime, timedelta
##HTTP를 호출하는 프로그램을 작성할 때 주로 사용한다
import requests
## html의 내용을 사용자가 활용하기 쉽게 하기위해 사용한다
from bs4 import BeautifulSoup 

## 네이버 뉴스검색 page url얻는 함수
def get_news_page_url(stock_name,hour_delta):
    ## strftime을 사용하여 string형태로 변환
    now_time = datetime.now().strftime('%Y.%m.%d.%H.%M') 
    ##timedelta사용하여 해당 시간단위를 이동, 아래예제는 3일을 이동
    start_time = (datetime.now()-timedelta(hours=hour_delta)).strftime('%Y.%m.%d.%H.%M') 
    page_num = 1
    #stock_name = '삼성전자'

    url = 'https://search.naver.com/search.naver?where=news&sm=tab_pge&query=' +  stock_name + \
    '&sort=1&photo=0&field=0&pd=9&ds=' + start_time +'&de=' + now_time + \
        '&mynews=0&office_type=0&office_section_code=0&news_office_checked=&nso=so:dd,p:all,a:all&start=' + \
            str((page_num-1)*10 + 1)

    ## 브라우저 호환을 위해서 설정
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '+ \
        '(KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'
                } 

    ##해당 url에 htlm(정보) 요청에사용 / url은 사용자가 원하는 url
    r = requests.get(url, headers=headers) 
    ## 해당 url의 html을 사용자가 활용하기 쉽게 변환
    html = BeautifulSoup(r.content, 'html.parser')
    tmp = []
    ## try/except 구문을 사용하여 예외처리
    try:
        ## page주소 정보를 가지고 있는 'tag'
        tmp = html.find('div',{'class', 'sc_page_inner'}).find_all('a') 
    except:
        pass

    ##저장될 비어있는 주소리스트 선언
    l_address = []
    ##전체 주소리스트를 l_address에 저장
    for i in tmp:
        tmp_add = 'https://search.naver.com/search.naver'+i.get('href')
        l_address.append(tmp_add)
    return l_address

def get_news_info(url):
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '+ \
        '(KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'
                } 
    ##해당 url에 htlm(정보) 요청에사용 / url은 사용자가 원하는 url
    r = requests.get(url, headers=headers) 
    ## 해당 url의 html을 사용자가 활용하기 쉽게 변환
    html = BeautifulSoup(r.content, 'html.parser')
    news_list = html.find('ul',{'class','list_news'}).find_all('li',{'class','bx'})[0]
    ##뉴스출처
    news_press = news_list.find('div',{'class','info_group'}).find('a').text
    ##뉴스제목
    news_title = news_list.find('a',{'class','news_tit'}).text
    ##뉴스url
    news_url = news_list.find('a',{'class','news_tit'}).get('href')
    ##뉴스본문
    news_contents = news_list.find('div',{'class','dsc_wrap'}).text
    print([news_press,news_title,news_url,news_contents])
    
    

##종목은 삼성전자 지금부터 2시간 전까지의 뉴스 url page주소 얻기
for i in get_news_page_url('삼성전자',2)[:1]:
    get_news_info(i)
 
['이코노뉴스', '코스피, 기관과 외인 매도에 하락 마감…LG화학, 네이버, 삼성SDI, SK하이닉스...', 'http://www.econonews.co.kr/news/articleView.html?idxno=244109', ' LG화학(-3.38%), NAVER(-3.07%), 삼성SDI(-2.30%), SK하이닉스(-2.21%), 카카오(-1.71%), 현대차(-1.64%), 삼성전자(-1.03%), 삼성바이오로직스(-0.62%), 삼성전자우(-0.33%), LG에너지솔루션(-0.11%) 등이 하락 마감했다. ']

 

코드에서 입력은 두 가지입니다. 종목 변수는 '삼성전자' 시간 변수는 '2'입니다. 두 가지 입력 정보로 뉴스 정보를 크롤링 하겠습니다. 코드 참조하세요.

 

 

 

In [66]:
#네이버에서 종목뉴스 크롤링 (crawling)
## datetime은 날짜 시간을 다루는 package
from datetime import datetime, timedelta
##HTTP를 호출하는 프로그램을 작성할 때 주로 사용한다
import requests
## html의 내용을 사용자가 활용하기 쉽게 하기위해 사용한다
from bs4 import BeautifulSoup 

## 네이버 뉴스검색 page url얻는 함수
def get_news_page_url(stock_name,hour_delta):
    ## strftime을 사용하여 string형태로 변환
    now_time = datetime.now().strftime('%Y.%m.%d.%H.%M') 
    ##timedelta사용하여 해당 시간단위를 이동, 아래예제는 3일을 이동
    start_time = (datetime.now()-timedelta(hours=hour_delta)).strftime('%Y.%m.%d.%H.%M') 
    page_num = 1
    #stock_name = '삼성전자'

    url = 'https://search.naver.com/search.naver?where=news&sm=tab_pge&query=' +  stock_name + \
    '&sort=1&photo=0&field=0&pd=9&ds=' + start_time +'&de=' + now_time + \
        '&mynews=0&office_type=0&office_section_code=0&news_office_checked=&nso=so:dd,p:all,a:all&start=' + \
            str((page_num-1)*10 + 1)

    ## 브라우저 호환을 위해서 설정
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '+ \
        '(KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'
                } 

    ##해당 url에 htlm(정보) 요청에사용 / url은 사용자가 원하는 url
    r = requests.get(url, headers=headers) 
    ## 해당 url의 html을 사용자가 활용하기 쉽게 변환
    html = BeautifulSoup(r.content, 'html.parser')
    tmp = []
    ## try/except 구문을 사용하여 예외처리
    try:
        ## page주소 정보를 가지고 있는 'tag'
        tmp = html.find('div',{'class', 'sc_page_inner'}).find_all('a') 
    except:
        pass

    ##저장될 비어있는 주소리스트 선언
    l_address = []
    ##전체 주소리스트를 l_address에 저장
    for i in tmp:
        tmp_add = 'https://search.naver.com/search.naver'+i.get('href')
        l_address.append(tmp_add)
    return l_address

def get_news_info(url):
    #print(url)
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '+ \
        '(KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36'
                } 
    ##해당 url에 htlm(정보) 요청에사용 / url은 사용자가 원하는 url
    r = requests.get(url, headers=headers) 
    ## 해당 url의 html을 사용자가 활용하기 쉽게 변환
    html = BeautifulSoup(r.content, 'html.parser')
    news_list = html.find('ul',{'class','list_news'}).find_all('li',{'class','bx'})
    #print(news_list)
    for i in news_list:
        ##뉴스출처
        news_press = i.find('div',{'class','info_group'}).find('a').text
        ##뉴스제목
        news_title = i.find('a',{'class','news_tit'}).text
        ##뉴스url
        news_url = i.find('a',{'class','news_tit'}).get('href')
        ##뉴스본문
        news_contents = i.find('div',{'class','dsc_wrap'}).text
        print([news_press,news_title,news_url,news_contents])
    
    

##종목은 삼성전자 지금부터 2시간 전까지의 뉴스 url page주소 얻기
for i in get_news_page_url('삼성전자',2):
    get_news_info(i)
 
['YTN', '"버려진 페트병으로 지구를 살리자"...경비 절감은 \'덤\'', 'https://www.ytn.co.kr/_ln/0102_202204222322234700', ' 단순히 그냥 재미없게 재활용한다, 여기 멈추지 않고 심미성을 가지고 있고….] 삼성전자는 올해 3월 출시한 갤럭시 S22와 갤럭시탭 S8 일부 부품에 해양 폐기물을 재료로 만든 소재를 사용했습니다. 이런 방식으로 올해... ']
['인천일보', '국민의힘 경기도당 1차 공천 추가 발표…광역 경선 21곳·단수 81곳', 'http://www.incheonilbo.com/news/articleView.html?idxno=1141092', ' 전 삼성전자 미국변호사)·부천시4선거구(이상윤 현 부천시의원)·부천시7선거구(허태래 현 성지새마을금고 감사)·부천시8선거구(박영호 현 더크는중앙유치원 원장) ▲광명시 광명시2선거구(김상겸 현 국민의힘 광명갑... ']
['경향신문언론사 선정', '이종호, 배우자에 11억 증여 10년간 신고 안 해…‘세금 탈루 ’의혹', 'https://www.khan.co.kr/national/national-general/article/202204222220005', ' 서울대 전기·정보공학부 교수인 이 후보자는 대학 교수로서 받는 근로소득 외에도 매년 특허 수익을 내다가 특허 침해 소송과 관련해 삼성전자와 합의한 해에 거액의 소득을 올린 것으로 보인다. 윤 의원은... ']
['이코노뉴스', '코스피, 기관과 외인 매도에 하락 마감…LG화학, 네이버, 삼성SDI, SK하이닉스...', 'http://www.econonews.co.kr/news/articleView.html?idxno=244109', ' LG화학(-3.38%), NAVER(-3.07%), 삼성SDI(-2.30%), SK하이닉스(-2.21%), 카카오(-1.71%), 현대차(-1.64%), 삼성전자(-1.03%), 삼성바이오로직스(-0.62%), 삼성전자우(-0.33%), LG에너지솔루션(-0.11%) 등이 하락 마감했다. ']
['이코노뉴스', '[공매도 TOP 10 종목] 코스피, 대한전선 공매도 1위…HMM-LG디스플레이-삼성중...', 'http://www.econonews.co.kr/news/articleView.html?idxno=244107', ' 이어 HMM(70만8529주), LG디스플레이(63만9132주), 삼성중공업(50만2220주), 한화솔루션(46만4934주), 삼성전자(42만2047주), 우리금융지주(39만7812주), 두산에너빌리티(36만755주), 카카오뱅크(31만7294주), 후성(26만5472주)... ']
['열린뉴스통신', '윤석열 대통령 당선인, "새 정부는 부산세계박람회 유치를 위해서 모든 역량을...', 'https://www.onews.tv/news/articleView.html?idxno=122823', ' 이인용 삼성전자 사장, 공영운 현대차 사장, 이형희 SK SV위원장, 하범종 LG사장, 이동우 롯데지주 부회장, 정탁 포스코 사장 등 국내 10대 그룹 대표 등 경제계 주요 인사들이 참석했다. 최태원 회장-윤석열 당선인-김영주... ']
['투데이에너지', '포스코, 전기강판 제조공장 착공', 'http://www.todayenergy.kr/news/articleView.html?idxno=247504', ' 22일 광양제철소에서 열린 착공식에는 김학동 포스코 대표이사 부회장을 비롯해 김경호 광양부시장, 박진만 한국산업단지공단 전남지역본부장과 현대차·기아, 삼성전자, LG전자 등 고객사와 시공사 대표 및 임원들이... ']
['경향신문언론사 선정', '이종호 후보자, 장관 지명 나흘 뒤 2억대 증여세 납부…‘세금 탈루’ 의혹', 'https://www.khan.co.kr/national/national-general/article/202204222114001', ' 이 후보자는 대학 교수로서 받는 근로소득 외에도 매년 특허 수익을 내다가 특허 침해 소송과 관련해 삼성전자와 합의한 해에 거액의 소득을 올린 것으로 보인다. 윤 의원은 “국립대 교수로 재직해온 후보자가... ']
['경향신문', '이종호 , 서울대 교수로 2020년 특허 수익료만 13억원 이상 거둬', 'https://www.khan.co.kr/national/national-general/article/202204222113015', ' 삼성전자와의 특허 소송서 승소 양측이 합의한 해에 거액의 소득 일본 출장 때 가족 동행도 논란 이종호 과학기술정보통신부 장관 후보자(56·사진)가 한 해에 13억원 이상의 특허 수익료를 얻은 것으로 확인됐다. 이... ']
['비즈니스포스트', '[4월23일자] 비즈니스포스트 아침의 주요기사', 'https://www.businesspost.co.kr/BP?command=article_view&num=278726', " ● '신의 직장' 삼성전자 옛말 되나, 몸값 올리려는 '2030' 잡기 쉽지 않아 ● \u200b\u200b[현장] '21.5호' 파운데이션을 찾아서, 라네즈숍 '비스포크 네오' 체험 ● [백브리핑] 산업은행은 왜 번번이 기업 '새 주인 찾기'에... "]
['헤럴드경제언론사 선정', '“124만원→19만원, 이게 말이 돼?” ‘헐값’ 삼성 초고가 뭐길래', 'http://news.heraldcorp.com/view.php?ud=20220422000686', ' “124만원짜리 갤럭시S20, 19만원 ‘헐값’ 됐다!” KT가 삼성전자 갤럭시S20 시리즈 재고 떨이에 들어갔다. 갤럭시S20과 갤럭시S20플러스(+) 공시 지원금을 크게 인상했다. 출시 직후 신종 코로나바이러스 감염증... ']
['팍스경제TV', '수원시, 제52주년 지구의 날 기념 소등행사…저녁 8시부터 10분 동안', 'http://www.paxetv.com/news/articleView.html?idxno=143045', " '기후 행동'의 필요성 알리는 이번 소등행사 수원시가 제52주년 지구의 날을 맞아 4월 22일 저녁 8시부터 10분 동안 수원화성, 삼성전자, 수원컨벤션센터와 수원시청·4개 구청 등 공공청사의 전등을 끈다. '탄소중립'에... "]
['OBS', "코스피, '매파 파월'에 하락 마감…2,700선 턱걸이", 'http://www.obsnews.co.kr/news/articleView.html?idxno=1350762', ' 기관과 외국인이 6천988억 원가 1천563억 원을 순매도한 가운데, 삼성전자 등 시가총액 상위 10개 종목이 일제히 하락했습니다. 코스닥지수는 6.90p, 0.74% 내린 922.78에 마감했습니다. ']

 

결과를 살펴 보면 허점이 있습니다. '삼성전자'로 검색했는데, 제목 또는 본문에 키워드('삼성전자')가 있다는 사실 하나 만으로 불필요한 크롤링 결과가 나왔습니다. 이것은 여러분이 조건문을 사용하여, 제외하거나, 응용하여 사용할 수 있습니다. 코드를 암기하는 것이 아니라 이해하는 것입니다. 'find_all' 활용하면 크롤링의 9할은 성공입니다.

print('모두의 파이썬')

※좋아요/댓글은 서로를 응원합니다!

 

728x90
반응형