DevSSOM

파이썬 크롤링 실습 - 네이버 뉴스 섹션들 기사 링크 추출하기 본문

Python/크롤링

파이썬 크롤링 실습 - 네이버 뉴스 섹션들 기사 링크 추출하기

데브쏨 2021. 7. 2. 15:21
반응형

네이버 뉴스 섹션들 기사 href 추출하기

 

네이버 뉴스 속보 페이지에는 여러 섹션이 있음. 이번엔 “정치”, “경제”, “사회”, “생활”, “세계”, “과학”으로 나뉘어진 다양한 분야의 속보 기사를 추출하는 실습.

 

https://news.naver.com/main/list.nhn?sid1=100

 

언론사별 속보 뉴스

언론사별 속보 뉴스를 제공합니다.

news.naver.com

 

위 url에서, sid1 부분으로 분야를 설정할 수 있음.

 

100 정치 103 생활
101 경제 104 세계
102 사회 105 과학

 

해야할 것

  1. get_request 함수를 올바르게 구현하기. get_request 함수에 문자열 형태의 분야 이름이 들어가면, 해당 분야의 뉴스 속보 홈페이지의 GET 요청의 응답을 반환해야 함.
  2. get_href 함수를 올바르게 구현하기. get_request 함수로부터 특정 분야에 대한 GET 요청의 응답을 올바르게 받았다면, get_href는 분야별 속보 기사에 접근할 수 있는 href를 리스트로 반환해야 함.

 

  • 이번 실습의 코드를 살펴보면 이전까지의 실습에선 볼 수 없었던 새로운 함수 get_request가 등장함.
  • main 함수의 req 변수는 get_request 함수의 반환값을 가짐.
  • get_request는 requests.get() 함수를 실행한 결과(응답)을 반환.
  • 기본 url에, 입력된 분야에 맞게끔 params 매개변수를 설정하거나 문자열 연산을 통해 분야별 속보 페이지에 접근할 수 있도록 하기.
import requests
from bs4 import BeautifulSoup

def get_href(soup) :
    # 각 분야별 속보 기사에 접근할 수 있는 href를 리스트로 반환
    return None

def get_request(section) :
    # 입력된 분야에 맞는 request 객체를 반환
    # 아래 url에 쿼리를 적용한 것을 반환
    custom_header = {
        'referer' : 'https://www.naver.com/',
        'user-agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
    }
    
    url = "https://news.naver.com/main/list.nhn"
    
    req = requests.get(url, headers = custom_header,
            params = ???) # params 매개변수를 올바르게 설정
    return None

def main() :
    list_href = []
    
    # 섹션을 입력
    section = input('"정치", "경제", "사회", "생활", "세계", "과학" 중 하나를 입력하세요.\n  > ')
    
    req = get_request(section)
    soup = BeautifulSoup(req.text, "html.parser")
    
    list_href = get_href(soup)
    
    print(list_href)


if __name__ == "__main__" :
    main()

 

 

>>>

 

크롬 개발자도구로 각각의 뉴스의 하이퍼링크가 어느 태그에 속해있는지를 보면, <a>태그가 <dt>라는 태그 안에 들어있어. 근데 들어있는 링크가 똑같은개 두개야. <dt>에도 <a>가 있고, <dt class="photo">에도 동일한 href를 가진 <a>가 있어. href를 추출할 때 같은 링크가 두 번씩 나오면 안되니까, <dt> 중에 하나만 골라서 필터링 해보는걸로. 그래서 <a> -<dt class="photo"> - <div class="list_body newsflash_body"> 이 구조로 코드 작성해볼거임.

def get_href(soup) :
    # 각 분야별 속보 기사에 접근할 수 있는 href를 리스트로 반환
    
    div = soup.find("div", class_="list_body newsflash_body")
    
    for dt in div.find_all("dt", class_="photo"):
        print(dt.find("a")["href"])

return되는 값들이 리스트 안에 들어갈 수 있도록 잘 정리해보면

def get_href(soup) :
    # 각 분야별 속보 기사에 접근할 수 있는 href를 리스트로 반환
    
    result = []
    
    div = soup.find("div", class_="list_body newsflash_body")
    
    for dt in div.find_all("dt", class_="photo"):
        result.append(dt.find("a")["href"])
        
    return result

 

 

이제는 get_request 함수쪽으로 가서, 어떻게 해야 여러 속보 섹션들을 크롤링할 수 있을지 고민. params 매개변수를 설정해야 되는데, 정치 섹션에서 -> 경제 섹션으로 이동하면 URL에서 sid1=100, sid1=101 이렇게 달라지는걸 볼 수 있어.

 

100 정치 103 생활
101 경제 104 세계
102 사회 105 과학

 

이렇게 각각 섹션과 sid1 값을 연결시켜주는 sections라는 딕셔너리를 만들어줘.

    sections = {
        "정치" : 100,
        "경제" : 101,
        "사회" : 102,
        "생활" : 103,
        "세계" : 104,
        "과학" : 105
    }

그리고 request.get의 params 매개변수를 설정. section은 사용자로부터 input을 받는 값.

req = requests.get(url, headers = custom_header,
	params = {"sid1" : sections[section]}) # params 매개변수를 올바르게 설정

그래서 완성된 get_request 함수는

 

def get_request(section) :
    # 입력된 분야에 맞는 request 객체를 반환
    # 아래 url에 쿼리를 적용한 것을 반환
    custom_header = {
        'referer' : 'https://www.naver.com/',
        'user-agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
    }
    
    url = "https://news.naver.com/main/list.nhn"
    
    sections = {
        "정치" : 100,
        "경제" : 101,
        "사회" : 102,
        "생활" : 103,
        "세계" : 104,
        "과학" : 105
    }
    
    req = requests.get(url, headers = custom_header,
    	params = {"sid1" : sections[section]}) # params 매개변수를 올바르게 설정

	return req

 

 

최종 코드

import requests
from bs4 import BeautifulSoup

def get_href(soup) :
    # 각 분야별 속보 기사에 접근할 수 있는 href를 리스트로 반환
    
    result = []
    
    div = soup.find("div", class_="list_body newsflash_body")
    
    for dt in div.find_all("dt", class_="photo"):
        result.append(dt.find("a")["href"])
        
    return result

def get_request(section) :
    # 입력된 분야에 맞는 request 객체를 반환
    # 아래 url에 쿼리를 적용한 것을 반환
    custom_header = {
        'referer' : 'https://www.naver.com/',
        'user-agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
    }
    
    url = "https://news.naver.com/main/list.nhn"
    
    sections = {
        "정치" : 100,
        "경제" : 101,
        "사회" : 102,
        "생활" : 103,
        "세계" : 104,
        "과학" : 105
    }
    
    req = requests.get(url, headers = custom_header,
        params = {"sid1" : sections[section]}) # params 매개변수를 올바르게 설정
    return req

def main() :
    list_href = []
    
    # 섹션을 입력
    section = input('"정치", "경제", "사회", "생활", "세계", "과학" 중 하나를 입력하세요.\n  > ')
    
    req = get_request(section)
    soup = BeautifulSoup(req.text, "html.parser")
    
    list_href = get_href(soup)
    
    print(list_href)


if __name__ == "__main__" :
    main()

 

 

728x90
반응형
댓글