ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [ 파이썬] requests 모듈을 이용해 네이버 뉴스토픽 크롤링!
    코딩/PYTHON 2020. 12. 1. 14:26

    네이버 뉴스토픽을 크롤링 해보곘습니다.

     

    네이버뉴스 토픽은 보통 네이버에서 검색했을때 좌측하단에 실검 밑에 뜨고 있습니다

     

    이런식으로 보이는 UI인데요 

     

    패킷캡쳐툴로 떠본후에 호출해서 가져올려했으나,  네이버측에서 잘 막아놓은것 같아

     

    일반 검색 후 beautifulsoup로 긁어서 사용해보겠습니다.

     

    일단 파이썬 requests 모듈이 필요합니다

     

    pip install requests

     

    백문의 불여일견 전체 코드 들어갑니다.

    import requests
    import json
    from bs4 import BeautifulSoup
    
    def getTopic():
        params = {
            'where': 'nexearch',
            'sm': 'tab_htk.nws',
            'ie': 'utf8',
            'query': 'today'
        }
    
        url = 'https://search.naver.com/search.naver?'
        headers = {
            'host': 'www.naver.com:443',
            'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
            'accept-encoding': 'gzip, deflate, br',
            'accept-language': 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7',
            'sec-fetch-mode': 'nested-navigate',
            'sec-fetch-site': 'same-origin',
            'Upgrade-Insecure-Requests': '1',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36',
            'referer': 'https://m.datalab.naver.com/realtimeList.naver?where=main'
        }
    
    
        try:
            r = requests.get(url, params=params, headers=headers)
            html = r.text
            #print(html)
            # 뷰티풀소프의 인자값 지정
            soup = BeautifulSoup(html, 'html.parser')
            time = soup.select('.time > time')[0].text
            hotKeyword= soup.select('.list_wrap')
            newsTopic = []
            enterTopic = []
            for tagIndex,tag in enumerate(hotKeyword):
                for index, liTag in enumerate(tag.select('li > a')):
                    if tagIndex == 0:
                        #link_text = liTag['href']
                        newsTopic.append({'rank': index + 1, 'keyword': liTag.text,  'keywordSynonyms': []})
                    if tagIndex == 1:
                        enterTopic.append({'rank': index + 1, 'keyword': liTag.text, 'keywordSynonyms': []})
    
            topic = {
                'newTopic': newsTopic,
                'enterTopic': enterTopic,
                'sm': time,
                'ts': ''
            }
    
            resData = {
                'message' : 'success',
                'statusCode' : '200',
                'ranks' : topic
            }
            jsonString = json.dumps(resData)
            return jsonString
    
        except:
            resData = {
                'message': 'error',
                'statusCode': '400',
                'ranks': []
            }
            jsonString = json.dumps(resData)
            return jsonString
    
    if __name__ == "__main__":
        response = getTopic()
        print(response)

    코드를 하나씩 설명드리자면, 

     

       params = {
            'where': 'nexearch',
            'sm': 'tab_htk.nws',
            'ie': 'utf8',
            'query': 'today'
        }
    
        url = 'https://search.naver.com/search.naver?'
        headers = {
            'host': 'www.naver.com:443',
            'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
            'accept-encoding': 'gzip, deflate, br',
            'accept-language': 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7',
            'sec-fetch-mode': 'nested-navigate',
            'sec-fetch-site': 'same-origin',
            'Upgrade-Insecure-Requests': '1',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36',
            'referer': 'https://m.datalab.naver.com/realtimeList.naver?where=main'
        }
    
    
        try:
            r = requests.get(url, params=params, headers=headers)

    우리가 브라우저에서 데이터가 보여지는건 사실상 데이터를 요청하고 , 

     

    리턴된 데이터를 기반으로 

    자바스크립트 같은 코드같은 브라우저단 코드가 작동하면서 view를 렌더링하는 것입니다

     

    결국 get방식으로 데이터를 요청하고, 리턴 받는게 가장 첫번째입니다. 

     

    get 방식은 python requests 모듈로 사용해서 요청하곘습니다. 

     

    requests 모듈에 get방식에서 필요한 값은  url, params, headers 세가지 값이 필요합니다.

     

    params에서 query 값이 우리가 검색할 문장입니다.

     

    저는 today라고 적었는데 여러분들이 검색창에 오늘날씨가 궁금해서 

     

    '오늘날씨' 라고 검색했다면

     

    params 의 query값에 '오늘날씨'가 넣어진 것이나 마찬가지라니다. ㅎ

     

    그리고 그 외에 headers값은 제가 네이버를 돌아다니면서 사용했던 값을 넣어줬습니다. 

     

    타 게시글들을보니 user-agent만 넣어주면 동작 한다는 얘기도 있습니다.

     

    저런 headers값으로 사람인지, 봇인지를 판단하고 있기 때문에 헤더값을 필히 넣어주어야 합니다. 

     

    위 코드처럼 작성후 요청을 보내면 r변수값에 리턴된 값이 들어가게 됩니다. 

     

    		r = requests.get(url, params=params, headers=headers) //요청
            html = r.text 
            #print(html)
            # 뷰티풀소프의 인자값 지정
            soup = BeautifulSoup(html, 'html.parser') # beautifulsoup 객체로 전환
            time = soup.select('.time > time')[0].text # 시간 긁어옴
            hotKeyword= soup.select('.list_wrap') #list_wrap 이라는 classname을 가진 객체 찾아서 반환
            newsTopic = []
            enterTopic = []
            for tagIndex,tag in enumerate(hotKeyword): 
                for index, liTag in enumerate(tag.select('li > a')): // li 태그의 a 태그 찾기
                    if tagIndex == 0:
                        #link_text = liTag['href']
                        newsTopic.append({'rank': index + 1, 'keyword': liTag.text,  'keywordSynonyms': []})
                    if tagIndex == 1:
                        enterTopic.append({'rank': index + 1, 'keyword': liTag.text, 'keywordSynonyms': []})
    
    		#반환 객체 조립 
            topic = {
                'newTopic': newsTopic,
                'enterTopic': enterTopic,
                'sm': time,
                'ts': ''
            } 
    		#조립
            resData = {
                'message' : 'success',
                'statusCode' : '200',
                'ranks' : topic
            }
           
            jsonString = json.dumps(resData) //json으로 변환
            return jsonString //return; 

    다음과 같이 beautifulsoup에서 값을 가져올수가 있는데

     

    beautiful soup에서 html tag값을 긁을때 보통 classname 또는 id값으로 태그를 가져오곤합니다

     

    많은 함수가있으나 저는 select 함수를 써서 가져왔습니다.

     

    제가 원하는건, 시간이랑 1~10위까지 순위 값이기 때문에 해당 클래스 네임을 찾아서  

     

    데이터를 조립했습니ㅏㄷ. 

     

    그리고 json 형태의 데이터가 필요해서

     

    string을 json 형태로 조립할때 

     

       jsonString = json.dumps(resData) //json으로 변환
    

    이런식으로 사용합니다.

     

    제가 저 파이썬을 node.js에서 특정 url 진입시 호출되게 만들어놓아서

     

    호출을 해보면 

     

    {
        "message": "success",
        "statusCode": "200",
        "ranks": {
            "newsTopic": [
                {
                    "rank": 1,
                    "keyword": "신규확진 451명",
                    "keywordSynonyms": []
                },
                {
                    "rank": 2,
                    "keyword": "정부과제 선정",
                    "keywordSynonyms": []
                },
                {
                    "rank": 3,
                    "keyword": "대웅제약 코로나19 치료제",
                    "keywordSynonyms": []
                },
                {
                    "rank": 4,
                    "keyword": "사흘째 400명대",
                    "keywordSynonyms": []
                },
                {
                    "rank": 5,
                    "keyword": "코로나19 신규확진 451명",
                    "keywordSynonyms": []
                },
                {
                    "rank": 6,
                    "keyword": "11월 수출 4.0%↑",
                    "keywordSynonyms": []
                },
                {
                    "rank": 7,
                    "keyword": "LG에너지솔루션 공식 출범",
                    "keywordSynonyms": []
                },
                {
                    "rank": 8,
                    "keyword": "추미애 윤석열 국정조사",
                    "keywordSynonyms": []
                },
                {
                    "rank": 9,
                    "keyword": "코로나19 확진자 발생",
                    "keywordSynonyms": []
                },
                {
                    "rank": 10,
                    "keyword": "국내발생 420명",
                    "keywordSynonyms": []
                }
            ],
            "enterTopic": [
                {
                    "rank": 1,
                    "keyword": "코로나 음성",
                    "keywordSynonyms": []
                },
                {
                    "rank": 2,
                    "keyword": "코로나19 검사",
                    "keywordSynonyms": []
                },
                {
                    "rank": 3,
                    "keyword": "한국판 리메이크",
                    "keywordSynonyms": []
                },
                {
                    "rank": 4,
                    "keyword": "철인왕후 신혜선",
                    "keywordSynonyms": []
                },
                {
                    "rank": 5,
                    "keyword": "방탄소년단 MIC Drop",
                    "keywordSynonyms": []
                },
                {
                    "rank": 6,
                    "keyword": "악뮤 트레저",
                    "keywordSynonyms": []
                },
                {
                    "rank": 7,
                    "keyword": "보아 데뷔 20주년",
                    "keywordSynonyms": []
                },
                {
                    "rank": 8,
                    "keyword": "새해전야 김강우",
                    "keywordSynonyms": []
                },
                {
                    "rank": 9,
                    "keyword": "아침마당 존 리",
                    "keywordSynonyms": []
                },
                {
                    "rank": 10,
                    "keyword": "아내의맛 함소원",
                    "keywordSynonyms": []
                }
            ],
            "sm": "2020.12.01. 08:30 ~ 11:30",
            "ts": "",
            "message": "none"
        }
    }

    이런 이쁘장한 JSON 데이터를 리턴 받을 수 있게 되었습니다. ㅎㅎ

    '코딩 > PYTHON' 카테고리의 다른 글

    Node.js에서 python 실행하기  (2) 2020.11.27

    댓글

Designed by Tistory.