python으로 네이버 사설 크롤링하기 1

moon-dad·2024년 2월 15일

파이썬을 사용하여 네이버의 사설을 크롤링하고 mysql 에 저장합니다. https://news.naver.com/opinion/editorial 페이지를 분석해 보면 스크롤을 내릴 때 마다 페이징 처리가 되고 있습니다. 개발자도구의 네트워크를 통해 보니 json 파일이 들어오며 페이징 처리가 되고 있습니다. 직접 json 파일을 요청하여 리턴된 json 데이터를 DB에 Insert 합니다.

requests
requests 는 HTTP 요청을 보내고 응답을 받는 라이브러리로 간단하고 직관적인 API를 제공하여 HTTP 요청을 쉽게 만들고 보낼 수 있습니다.
requests를 사용하면 GET, POST, PUT, DELETE 등의 다양한 HTTP 메서드를 사용하여 서버에 요청을 보낼 수 있습니다. 또한 URL 매개변수, 헤더, 쿠키, 인증 등을 설정할 수 있으며, 파일 업로드, 세션 관리, 리다이렉션 처리 등의 기능도 제공합니다.
requests는 Python의 표준 라이브러리인 urllib보다 사용하기 쉽고 강력한 기능을 제공하여, 많은 개발자들이 사용하고 있습니다. 따라서, 웹 스크래핑, API 호출, 웹 서비스 개발 등 다양한 웹 개발 작업에 유용하게 사용됩니다.

pymysql
pymysql 라이브러리는 MySQL 데이터베이스를 핸들링 하기 위한 라이브러리입니다.
먼저 connect() 메서드를 사용하여 MySQL 데이터베이스에 연결합니다. 이 함수는 호스트, 사용자 이름, 비밀번호, 데이터베이스 이름 등의 연결 정보를 인자로 받아 MySQL 서버에 연결합니다. 연결이 성공하면 Connection 객체가 반환되며, 이 객체를 사용하여 쿼리를 실행하고 데이터를 가져올 수 있습니다.
쿼리를 실행하려면 execute() 메서드를 사용합니다. 이 메서드는 SQL 쿼리를 인자로 받아 실행하고, 실행 결과를 반환합니다. SQL인젝션 공격을 방지하기 위해 SQL 쿼리는 직접 입력하지 않고 반드시 매개 변수를 사용하여 입력해야 합니다.

# SQL 인젝션 공격 예 (사용자명에 넣어 봅니다.)
' OR 1#

datetime
datetime 은 날짜와 시간을 다루기 위한 라이브러리입니다. datetime 모듈은 date, time, datetime, timedelta 등의 클래스를 포함하고 있어 다양한 날짜와 시간 연산을 수행할 수 있습니다.
datetime 모듈을 사용하여 현재 날짜와 시간을 가져오거나, 특정 날짜와 시간을 생성할 수 있습니다. datetime 클래스는 연도, 월, 일, 시, 분, 초, 마이크로초 등의 속성을 가지고 있어 날짜와 시간을 자세히 표현할 수 있습니다.
또한, strftime() 메서드를 사용하여 날짜와 시간을 원하는 형식의 문자열로 만들거나, strptime() 메서드를 사용하여 문자열을 날짜와 시간 형식으로 만들 수 있습니다.

time
time 라이브러리는 시간과 관련된 기능을 제공하는 라이브러리로 sleep(초수) 함수를 사용하면 프로그램이 일정시간 동안 멈춥니다.

sys
sys 라이브러리는 시스템 관련된 정보나 동작을 활용할 때 사용되며 sys.exit() 를 만나면 프로그램은 종료됩니다.

DB 접속정보는 별도의 파일(setting.py)에 저장하여 다른 파일들도 참조할 수 있도록 하였습니다. 개별파일마다 접속 정보를 넣을 경우 만약 접속 정보가 바뀌면 모든 파일을 수정해야 하기 때문에 별도로 저장하는 것이 좋습니다. 불러올때는 아래 예제처럼 import setting 또는 from setting import [변수명] 형식으로 불러오면 됩니다.

[setting.py]

db_cfg = {
    'host':'localhost',
    'port':'3306',
    'user':'******',
    'password':'*****',
    'db':'*****',
    'charset':'utf8',
}
# pip install requests pymysql

import requests
import pymysql
from hashlib import md5
from time import sleep
from datetime import datetime
import sys
from setting import db_cfg

# ondate 요청할 날짜 : 비어 있으면 오늘 , 만약 특정 날짜를 지정하려면 ondate = '20240215'

ondate = ''

if ondate == '':
    dt_now = datetime.now()
    ondate = dt_now.strftime('%Y%m%d')

# pubdate : 발행일. 각 기사마다 날짜를 넣어도 되지만 어제 저녁 올린 것이 오늘 날짜로 나타나므로 ondate 를 그대로 넣는다.
pubdate = ondate[0:4] + '-' + ondate[4:6] + '-' + ondate[6:]

print('가져올 날짜: ', pubdate)
# sys.exit()


def getNewsData(ondate, page):

    listUrl = f'https://news.naver.com/opinion/editorial/api?officeId=&date={ondate}&page={page}'
    headers = {
        'accept': 'application/json, text/javascript, */*; q=0.01'
    }

    jsonData = requests.get(listUrl, headers=headers).json()
    
    return jsonData['message']['contents']

with pymysql.connect(host=db_cfg['host'], user=db_cfg['user'], password=db_cfg['password'], db=db_cfg['db'], charset=db_cfg['charset'], autocommit=True, cursorclass=pymysql.cursors.DictCursor) as conn:
    with conn.cursor() as cursor:
        
        # range(이상, 미만)
        for page in range(1,6):
            articles = getNewsData(ondate, page);
            sleep(2)

            for article in articles:
                
#                 print(article['title'], article['linkUrl'], article['serviceTime']['yearMonthDay'], article['officeId'], article['officeName'], article['subContent'])
#                 print()
#                 continue                

                md5link = md5(article['linkUrl'].encode()).hexdigest()

                sql = 'INSERT IGNORE INTO tbopinion (titlestr, md5link, linkstr, pubdate, mediacode, mediastr, summary, crawldate) VALUES (%s, %s, %s, %s, %s, %s, %s, now())'
                result = cursor.execute(sql, (article['title'], md5link, article['linkUrl'], pubdate, article['officeId'], article['officeName'], article['subContent']))
                
                # insert id(insertid) 가져오려면
                insertid = cursor.lastrowid
        
profile
나는 아무것도 아닙니다.

0개의 댓글