본문 바로가기
[python]데이터 분석/[python]웹 스크랩핑(scraping)

네이버 뉴스 스크랩핑 하기 (news scraping)

by 코드몽규 2022. 1. 28.
반응형

1. 먼저 필요한 모듈들을 import 해준다.

#%%

import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin

2. 다음으로 스크랩핑을 원하는 페이지의 URL과 브라우저 정보를 파악하고 이를 통해 아래와 같이 불러온다.

#%%

url = 'https://news.naver.com/main/main.naver?mode=LSD&mid=shm&sid1=100'
req_header_dict = {
    # 요청헤더 : 브라우저 정보
    'user-agent':
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36'
}
res = requests.get(url, headers=req_header_dict) #get을 이용하여 해당 url의 hearders를 지정해준다. get(url, headers = custom_headers)
print(res.status_code, res.ok) #print(상태코드, response.ok) res.ok는 status_code가 200이상 400미만의 값인지 여부확인
print(type(res))
print('응답헤더',res.headers)
print('요청헤더',res.request.headers)

3. res.ok를 통해 해당페이지의 반응이 정상적이라는것을 확인했다면 스크랩핑하고싶은 데이터를 프린트한다.

if res.ok:
    html = res.text #소스보기로 보여지는 text
    soup = BeautifulSoup(html, 'html.parser') #BeautifulSoup을 이용해 html을 parsing한다.
    atag_list= soup.select("a[href*='read.naver']") #<a></a>태그의 <href>속의 값에 read.naver가 포함된 모두를 선택
    print(len(atag_list))
    for i in atag_list:
         title = i.text.strip() #strip() 공백을 제거해준다.
         print(title)

 위의 코드를 실행하면 맨처음 설정한 url에 있는 뉴스 기사의 제목들이 스크랩핑 되어서 나온다.

왜냐하면 select()를 통해 href속에 read.naver가 들어간 자료를 모두 선택했기때문이다. 

(*여기서 <a href = read.naver~ </a>로된 자료들이 처음 등록한 url의 카테고리속 포함된 여러 기사라는 사실을 알 수 있다.)

 

print(title)결과로 다음과같이 나온 것을 확인 할 수 있다.

(*나는 네이버 뉴스의 정치 카테고리에 해당하는 url을 기준으로 스크랩핑을 해봤는데 해당 카테고리에 있는 기사들의 제목들이 심각해서 나 또한 심각해지는 느낌이다.😂)

N번방 최초 신고자, 민주당 선대위 합류…“더 나은 세상 위해”
이재명 "디지털 성범죄 심각...완전히 뿌리 뽑겠다"
‘n번방’ 밝힌 ‘추적단 불꽃’, 與선대위 합류…젠더 공약 돕는다
N번방 파헤친 '추적단 불꽃' 활동가 박지현씨 민주당 선대위 합류

"김원웅이 수익 횡령" vs "前간부 개인비리"…보훈처, 감사착수(종합)
광복회, 김원웅 횡령 의혹에 "실무 직원 개인 비리"
보훈처 “김원웅 ‘광복회 카페 수익금’ 횡령 의혹 감사”
보훈처 “김원웅 광복회장 국회 카페 ‘헤리티지 815’ 수익 횡령 의혹” 감사 개시

北 새해 6번째 미사일…이재명 “선거 악영향” 윤석열 “힘으로 도발 무력화”
이재명 “고질적인 북한의 대선 개입”···대선 후보들에 대북 공동선언 제안
이재명, 北 미사일 발사 규탄...여야 후보들에 '중단 촉구' 공동 선언 제안
이재명 "北 대선개입 중지 촉구"‥대선 후보 공동선언 제안

민주당, 尹측 양자토론 제안 수용…“4자 토론도 참석”
대선 첫 4자토론 이르면 31일 열릴듯…내일 실무 협상
국힘 양자토론 제안…민주 "양자도, 4자도 다 하자"ㅣ썰전 라이브
정의당, 국민의힘 李-尹 양자토론 역제안에…"꼼수에 넘어가지 않겠다"

윤석열 '주식양도세 폐지'…이재명 '부자감세 반대' 6글자 응수

윤석열 "주식양도세 폐지" 7글자 공약…"개미투자자 보호"

北피격 공무원 아들, 尹에 편지…"아버지 명예회복 도와달라"

다시 본론으로 돌아와서 스크랩핑된 기사 제목들을 보면 무언가 정리가 잘 안된 느낌이다. 

정리된 느낌을 주기위해 이번에는 해당기사가 가지고 있는 번호를 포함해서 출력해보자.

for idx, atag in enumerate(atag_list,1): #enumerate()를 이용해 위에서 만든 atag_list를 인덱스 번호와 기사 제목을 튜플형식으로 뽑아보자
      title = atag.text.strip()
      print(f'{idx} = {title}')

먼저 위의 코드를 실행해보았다. 

인덱스번화와 그에 맞는 title을 갖는 튜플형식의 자료로 스크랩핑 되었지만 title을 작성되지 않은 기사도 있어서

아래처럼 출력되었다.

 

20 = 李, 100분간 광주 붕괴현장 머물고 "참으로 기가 막히다, 돈보다 생명" [현장]
21 = 
22 = "韓 확산세 너무 걱정할 필요 없어" 英 외교관 트윗 공유한 文 "감사"
23 = 
24 = '韓 의료 훌륭, 걱정말라' 英 참사관 글에…문대통령 "감사"
25 = 동영상기사
26 = 청해부대 또 집단감염…"먹는 치료제 공급"

때문에 title이 없는 기사는 nesw_link라는 변수를 만들어 url이 나오도록 해주었다.

 #href의 속성을 갖고올 때을 기준으로
    for idx, atag in enumerate(atag_list, 1):
        title = atag.text.strip() #뉴스 제목을 갖고오는 것
        news_link = atag['href']
        print(f'{idx} = {title}{news_link}')
        
        ########################################
#urljoin기능을 이용한 코드
for atag in atag_list:
         title = atag.text.strip() #atag의 뉴스 제목 타이틀 / 공백제거
         news_link = urljoin(url, atag['href']) #atag의 href에 해당하는 "url"을 가져오는것(href="url")
         print(title,news_link)

아래와 같이 결과가 나오는 것을 확인 할 수 있다.

11 = https://news.naver.com/main/read.naver?mode=LSD&mid=shm&sid1=100&oid=023&aid=0003669078
12 = 이재명 “5·18정신 헌법 명문화… 군 공항 이전 지원” 광주 공약 발표https://news.naver.com/main/read.naver?mode=LSD&mid=shm&sid1=100&oid=023&aid=0003669078
13 = 이재명 “광주에 혁신적인 새 희망 만들어 드릴 것”https://news.naver.com/main/read.naver?mode=LSD&mid=shm&sid1=100&oid=277&aid=0005036807
14 = 이재명, 역대 정부 못한 '광주 군공항 이전'…"국가 책임하에"(종합)https://news.naver.com/main/read.naver?mode=LSD&mid=shm&sid1=100&oid=018&aid=0005135329
15 = 텃밭 찾은 이재명, “호남서 인정받는 게 먼저”https://news.naver.com/main/read.naver?mode=LSD&mid=shm&sid1=100&oid=056&aid=0011203528
16 = 이재명, 문 대통령 칠순에 손편지 "깊이 존경...성과 잇겠다"https://news.naver.com/main/read.naver?mode=LSD&mid=shm&sid1=100&oid=052&aid=0001695105
17 = [단독] 이재명, 문 대통령 칠순에 '손편지' 보냈다… "깊이 존경한다"https://news.naver.com/main/read.naver?mode=LSD&mid=shm&sid1=100&oid=469&aid=0000655082
18 = 이재명, 文 칠순 축하 존경 담아 손글씨 편지와 꽃다발 전달https://news.naver.com/main/read.naver?mode=LSD&mid=shm&sid1=100&oid=025&aid=0003169865
19 = 이재명, 文대통령 70번째 생일에 손편지 보내…"깊이 존경"https://news.naver.com/main/read.naver?mode=LSD&mid=shm&sid1=100&oid=421&aid=0005872602

URL을 매번 바꿔가면서 해당 페이지의 자료들을 스크랩핑하는것은 매우 귀찮은 일이다.

 

따라서 우리는 네이버 뉴스 기사의 카테고리가 가진 규칙성을 이용해서 다음과 같은 프로그램을 만들 수 있다.

import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin

def print_news_info(section):
    url_dict = {'정치':100,'경제':101,'사회':102,'생활/문화':103,'세계':104,'IT/과학':105}
    code = url_dict.get(section)
    if code:
        url = f'https://news.naver.com/main/main.naver?mode=LSD&mid=shm&sid1={code}'
        print(url)

    req_header_dict = {
        # 요청헤더 : 브라우저정보
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36'
    }
    res = requests.get(url, headers=req_header_dict)
    print(res.status_code, res.ok)
    # print(type(res))
    # print('응답헤더 ', res.headers)
    # print('요청헤더 ', res.request.headers)
    if res.ok:
        # 소스보기로 보여지는 text
        html = res.text
        soup = BeautifulSoup(html, 'html.parser')
        # href 속성의 값에 read.naver 문자열이 포함된 a tag 선택하기
        atag_list = soup.select("a[href*='read.naver']")
        print(len(atag_list))
        for atag in atag_list:
            #<a >뉴스제목 </a>
            title = atag.text.strip()
            #<a href="url">
            news_link = urljoin(url, atag['href'])
            print(title, news_link)
print_news_info('생활/문화')

#생활/문화 에 해당하는 103번이 URL에 들어가서 생활/문화에 해당하는 다음과 같은 뉴스기사의 제목을 출력한다.

https://news.naver.com/main/read.naver?mode=LSD&mid=shm&sid1=103&oid=052&aid=0001694805
'콩고 왕자' 조나단 한국 귀화 결정 "난민 받아준 한국에 보은" https://news.naver.com/main/read.naver?mode=LSD&mid=shm&sid1=103&oid=052&aid=0001694805
‘콩고 왕자’ 조나단, 한국 귀화 결정…“가능하다면 군대도” https://news.naver.com/main/read.naver?mode=LSD&mid=shm&sid1=103&oid=023&aid=0003669051
'콩고왕자' 조나단 "한국 귀화 결정…군대도 가고 싶다" https://news.naver.com/main/read.naver?mode=LSD&mid=shm&sid1=103&oid=009&aid=0004914657
조나단 “귀화하고 군대 가고 싶다”…귀화자 병역 의무 어디까지 왔나 https://news.naver.com/main/read.naver?mode=LSD&mid=shm&sid1=103&oid=056&aid=0011203258
반응형

댓글