본문 바로가기

프로그램 개발일지

[Python] 네이버 블로그 자동 포스팅 만들기 - requests로 글쓰기 2편

 

Instagram

 

www.instagram.com

 
1편:

 

[Python] 네이버 블로그 자동 포스팅 만들기 - requests로 글쓰기 1편

파이썬에 입문을 하고나면 셀레니움을 자주 사용하게 된다. (아님말고) 웹 자동화를 쉽게 할 수 있고, 안되는게 거의 없어서 아주아주 유용하고 좋긴한데 ...? ! 여러가지 단점들이 존재하고 ....

myworld1004.tistory.com

 
 
 
 
네이버 블로그에 requests를 이용해서 게시물을 쓰고 싶었다.
 
사실 계속 해봐도 
 

{"isSuccess":false,"result":{"errorCode":"invalid parameter","errorMessage":""}}

 
 
이거만 리턴을 받아서 ....................
 
 
 
휴... 티스토리 글 빨리 써야하는데 ㅡㅡㅡ .. 하던 오늘
 
 
 

Success = True 반환

 
 
 
글 작성에 성공했다 ... !!!
 
블로그 확인해보니 실제로 글이 잘 작성되어 있었다.
 
 
 
 
 
 
 
autoSaveNo, editorSource, document의 id값과 components안에 있는 id 값
 
두번째 id값은 uuid에 SE-를 붙인거 같고,
첫번째 id값은 아마 글쓰기 요청 이전에 생성된 값 같다.
 
 
 
1편에서 중요할거 같다는 정보들이였다.
 
생각보다 안 중요한애들도 있었다..
 
 
 

data = {
    "blogId": 블로그아이디(네이버아이디X),
    "documentModel": documentModel,
    "populationParams": populationParams
}

 
 
우리가 보낼 데이터 형식은 위와 같다.
 
 

documentModel = {
        "documentId": "",
        "document": {
            "version": "2.8.0",
            "theme": "default",
            "language": "ko-KR",
            "id": "의문의값",
            "components": [
                {
                    "id": "SE-e1ed2dc4-208e-47f0-b7f6-c69aafd4ca33",
                    "layout": "default",
                    "title": [
                        {
                            "id": "SE-9ed3e56c-433e-42a7-921a-b578de4cdb5f",
                            "nodes": [
                                {
                                    "id": "SE-65c8b39a-7278-4fde-bf5b-836e7e0ab508",
                                    "value": "vvv",
                                    "@ctype": "textNode"
                                }
                            ],
                            "@ctype": "paragraph"
                        }
                    ],
                    "subTitle": None,
                    "align": "left",
                    "@ctype": "documentTitle"
                },
                {
                    "id": "SE-7f83e8c8-b8c2-4a3b-b3c4-57fd8b7890c9",
                    "layout": "default",
                    "value": [
                        {
                            "id": "SE-e991ad7d-5627-450f-b0f9-9d9017a21ed2",
                            "nodes": [
                                {
                                    "id": "SE-287ea9fd-04af-41d3-b902-5df1a8c5908c",
                                    "value": "zz",
                                    "@ctype": "textNode"
                                }
                            ],
                            "@ctype": "paragraph"
                        }
                    ],
                    "@ctype": "text"
                }
            ],
            "di": {
                "dif": False,
                "dio": [
                    {
                        "dis": "N",
                        "dia": {"t": 0, "p": 0, "st": 18, "sk": 3}
                    },
                    {
                        "dis": "N",
                        "dia": {"t": 0, "p": 0, "st": 18, "sk": 3}
                    }
                ]
            }
        }
    }

 
documentModel의 구조는 이러한데, 우린 저기 의문의 값을 먼저 구해보자.
 
 
 
 
 

의문의값 있는곳

 
 
의문의값은 service_config
 

https://platform.editor.naver.com/api/blogpc001/v1/service_config

 
위 주소에서 받아올 수 있다 .
 
 
 
 
 

id값

 
 
위에 빨간색 해놓은 부분이 바로 의문의값인데, 
 
 
 
 
 
 
 

 
 
그냥 Get 요청이다. 파라미터도 없고 아무것도 없다.
 
 
의외로 간단하네 했지만 전편에서도 그랬듯 헤더탭을 자세히 봐야한다.
 
 
 
 
 
 

인증값

 
 
 
 
평소에는 없던 Se-Authorization 이라는 항목도 헤더에 넣어서 보내줘야하는걸 확인 했다.
 
 
 
Authorization 는 인증, 허가 이런 뜻인데 저게 있어야만 요청이 될 거 같다는 느낌이 확 온다.
 
 
 
 
 

Authorization

 
 
 
저 값을 그대로 복사해서 컨트롤 F 해서 찾아보면 이 값이 어디서부터 시작됐는지 알 수 있다.
( 이렇게해서 알게되면 진짜 럭키비키고 .... 없는 경우도 허다하다 )
 
 
 
 
 
 
 

토큰

 
 
 
service_config가 호출되기 전 PostWriteFormSeOptions.naver 라는 요청에서 token이 발급되는데
 
그 토큰 값이 service_config를 호출할때 필요한 Se-Authorization 값이라는걸 우린 알게되었다.
 
 
 
 
 
 

def token():
    url = 'https://blog.naver.com/PostWriteFormSeOptions.naver'
    param = {
        'blogId': 블로그아이디,
        'categoryNo': 카테고리넘버
    }
    header = {
        'Referer': 'https://blog.naver.com/PostWriteForm.naver?blogId=블로그아이디&Redirect=Write&categoryNo=카테고리넘버&redirect=Write&widgetTypeCall=true&from=section&topReferer=https%3A%2F%2Fsection.blog.naver.com%2FBlogHome.naver%3FdirectoryNo%3D0%26currentPage%3D1%26groupId%3D0&trackingCode=blog_sectionhome_pc&directAccess=false',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Whale/3.27.254.15 Safari/537.36'
    }

    a = r.get(url=url,headers=header,params=param,cookies=cookies)
    return a.json()['result']['token']

def service_config():
    url = 'https://platform.editor.naver.com/api/blogpc001/v1/service_config'
    header = {
        'Referer': 'https://blog.naver.com/PostWriteForm.naver?blogId=블로그아이디&Redirect=Write&categoryNo=카테고리넘버&redirect=Write&widgetTypeCall=true&from=section&topReferer=https%3A%2F%2Fsection.blog.naver.com%2FBlogHome.naver%3FdirectoryNo%3D0%26currentPage%3D1%26groupId%3D0&trackingCode=blog_sectionhome_pc&directAccess=false',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Whale/3.27.254.15 Safari/537.36',
        'Se-Authorization': token()
    }

    a = r.get(url=url,headers=header,cookies=cookies)
    return a.json()['editorInfo']['id']

 
 
 
 
 
 
service_config를 호출하면 id값이 나오게된다 !
 
 
 
 
 
자 의문의 값은 구했고
 
 
 
 

populationParams = {
        "configuration": {
            "openType": 2,
            "commentYn": True,
            "searchYn": True,
            "sympathyYn": True,
            "scrapType": 2,
            "outSideAllowYn": True,
            "twitterPostingYn": False,
            "facebookPostingYn": False,
            "cclYn": False
        },
        "populationMeta": {
            "categoryId": 1,
            "logNo": None,
            "directorySeq": 0,
            "directoryDetail": None,
            "mrBlogTalkCode": None,
            "postWriteTimeType": "now",
            "tags": "첫글",
            "moviePanelParticipation": False,
            "greenReviewBannerYn": False,
            "continueSaved": False,
            "noticePostYn": False,
            "autoByCategoryYn": False,
            "postLocationSupportYn": False,
            "postLocationJson": None,
            "prePostDate": None,
            "thisDayPostInfo": None,
            "scrapYn": False
        },
        "editorSource": 의문의값
}

 
 
다음은 populationParams에 의문의값을 구해보자.
이건 블로그에서 발행을 누르면 나오는 작은 화면(?)에 설정값들이다.
 
아무튼 에디터 소스를 구해보자.
 
 
 
 

에디터소스

 
 
 
 
에디터 소스는 아까 슬쩍 들여본 PostWriteFormSeOptions.naver의 바로 다음 호출에서 찾을 수 있다.
 
 
 
 
 
 

def editorSource():
    url = 'https://blog.naver.com/PostWriteFormManagerOptions.naver'
    param = {
        'blogId': 블 로 그 아 디,
        'categoryNo': 카테고리넘버
    }
    header = {
        'Referer': 'https://blog.naver.com/PostWriteForm.naver?blogId=블로그아디&Redirect=Write&categoryNo=1&redirect=Write&widgetTypeCall=true&from=section&topReferer=https%3A%2F%2Fsection.blog.naver.com%2FBlogHome.naver%3FdirectoryNo%3D0%26currentPage%3D1%26groupId%3D0&trackingCode=blog_sectionhome_pc&directAccess=false',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Whale/3.27.254.15 Safari/537.36'
    }
    a = r.get(url=url,headers=header,params=param,cookies=cookies)
    return a.json()['result']['formView']['editorSource']

 
사실 url만 다르고 token구하는거랑 똑같다.
 
 
 
 
자 의문의 값들 다 구했다.
 
 
 

def post():
    url = "https://blog.naver.com/RabbitWrite.naver"

    headers = {
        "content-type": "application/x-www-form-urlencoded",
        'Referer': 'https://blog.naver.com/PostWriteForm.naver?blogId=블로그아이디&Redirect=Write&categoryNo=1&redirect=Write&widgetTypeCall=true&topReferer=https%3A%2F%2Fwww.naver.com%2F&trackingCode=naver_etc&directAccess=false',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Whale/3.27.254.15 Safari/537.36'
    }

    data = {
        "blogId": 블로그아이디,
        "documentModel": '{"documentId":"","document":{"version":"2.8.0","theme":"default","language":"ko-KR","id":"' + service_config() + '","components":[{"id":"SE-e1ed2dc4-208e-47f0-b7f6-c69aafd4ca33","layout":"default","title":[{"id":"SE-9ed3e56c-433e-42a7-921a-b578de4cdb5f","nodes":[{"id":"SE-65c8b39a-7278-4fde-bf5b-836e7e0ab508","value":"ㅇ","@ctype":"textNode"}],"@ctype":"paragraph"}],"subTitle":null,"align":"left","@ctype":"documentTitle"},{"id":"SE-7f83e8c8-b8c2-4a3b-b3c4-57fd8b7890c9","layout":"default","value":[{"id":"SE-e991ad7d-5627-450f-b0f9-9d9017a21ed2","nodes":[{"id":"SE-287ea9fd-04af-41d3-b902-5df1a8c5908c","value":"ㅇ","@ctype":"textNode"}],"@ctype":"paragraph"}],"@ctype":"text"}],"di":{"dif":false,"dio":[{"dis":"N","dia":{"t":0,"p":0,"st":18,"sk":3}},{"dis":"N","dia":{"t":0,"p":0,"st":18,"sk":3}}]}}}',
        "populationParams": '{"configuration":{"openType":2,"commentYn":true,"searchYn":true,"sympathyYn":true,"scrapType":2,"outSideAllowYn":true,"twitterPostingYn":false,"facebookPostingYn":false,"cclYn":false},"populationMeta":{"categoryId":1,"logNo":null,"directorySeq":0,"directoryDetail":null,"mrBlogTalkCode":null,"postWriteTimeType":"now","tags":"첫글","moviePanelParticipation":false,"greenReviewBannerYn":false,"continueSaved":false,"noticePostYn":false,"autoByCategoryYn":false,"postLocationSupportYn":false,"postLocationJson":null,"prePostDate":null,"thisDayPostInfo":null,"scrapYn":false},"editorSource":"' + editorSource() + '"}',
        "productApiVersion": "v1"
    }

    a = r.post(url=url, headers=headers, data=data, cookies=cookies)
    print(a.text)

 
 
 
 
 
 
 

성공

 
 
 
 
 
 
 
requests로 블로그글 작성에 성공했다.
 
 
 
사진 넣기와, 제목과 내용을 더 자유자재로 써도 상관없게끔 하는건
 
3편에서 해보자 .... !!!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 

[종합 매크로] 업데이트 / 공지사항

BETA버전        현재 지원하는 매크로:- 뽐뿌 렌탈업체 오토 게시물 /패킷버전- 네이버 플레이스 크롤링 /패킷버전- 네이버 카페 댓글 매크로 /패킷버전 (로그인->크롬)- 올웨이즈 상품리스트

myworld1004.tistory.com