• 목록
  • 아래로
  • 위로

안녕하세요?


주말 잘 보내고 계시는가요?? ^^


친구의 부탁으로 프로모션 정보가 담긴 네이버 카페를 크롤링 하려다가 막히는 부분이 있어서 질문 드려요~



https://m.cafe.naver.com/ca-fe/web/cafes/25490972/menus/1 


여기에서 '이달의 이벤트'라는 게시글 제목을 찾아서 아래 URL로 들어가는 것까지는 네트워크탭의 XHR에서 의심스러운 전송을 찾아서 구현했어요!


https://m.cafe.naver.com/ca-fe/web/cafes/25490972/articles/1742?fromList=true&menuId=1



그런데 게시글의 내용이 동적 웹페이지로 구현되어 있더군요 ㄷㄷ


XHR 중에 의심스러운 전송이 첫번째 항목에 있던데요.


마지막 파라미터인 buid 항목의 인자값을 찾아낼 수가 없네요.


저번에 humit 님께서 구체적으로 XHR 항목 중에 어떤 Name이 있는지는 프록시 등을 이용하지 않고서는 알 수 없다고 말씀하신 것으로 기억하는데요~






브라우저로 접근을 하면  다음과 같은 JSON 데이터를 얻을 수 있는데요.


보시다시피 json -> image -> url이라는 항목과 json -> originalImage -> originUrl이라는 항목이 존재하는데요 ㄷㄷ


"contentElements":[{"type":"IMAGE","json":{"image":{"url":"https://mcafethumb-phinf.pstatic.net/MjAyMDA0MDJfMTcy/MDAxNTg1Nzk1NjMwOTAy.2lPNDpuQRjUbFdvfPrB5SWLuTzc1r5jtF2BFx8W99gIg.sTxyf_9O9Yb2vj-VErglaujvR6K6mkvQEMQhuAV4ydgg.JPEG/4-5.jpg","service":"CAFE","type":"w740","width":880,"height":922},"originalImage":{"originUrl":"http://cafefiles.naver.net/MjAyMDA0MDJfMTcy/MDAxNTg1Nzk1NjMwOTAy.2lPNDpuQRjUbFdvfPrB5SWLuTzc1r5jtF2BFx8W99gIg.sTxyf_9O9Yb2vj-VErglaujvR6K6mkvQEMQhuAV4ydgg.JPEG/4-5.jpg","originSize":70177,"originName":"4-5.jpg"},"from":"MOBILEWEB"}}



requests로 접근을 하면 request header를 그대로 긁어서 모바일 브라우저의 user-agent로 변경을 해도 다음과 같이 originUrl 항목이 뜨지 않네요 ㅠㅠ


'type': 'IMAGE', 'json': {'image': {'url': 'https://mcafethumb-phinf.pstatic.net/MjAyMDA0MDJfMTQw/MDAxNTg1Nzk1NjMxODA2.eMucvUUm8Rjx6m5NoFtQjN1SIO8Ok6sBADyk00-qmFUg.vMD4Jtiv42q6NN3k6Ol2rWnXQyF2F-UagzJHef4cC8Qg.JPEG/4-3.jpg', 'service': 'CAFE', 'type': 'w740', 'width': 740, 'height': 1046}, 'from': 'MOBILEWEB'}}


그냥 url 항목의 url 값을 긁어서 접근하면 브라우저에서 해당 파일이 not found라고 뜨기 때문에 반드시 originUrl 항목을 긁어서 접근해야 되더군요 ㄷㄷ



이상한 점은 브라우저에서는 buid를 입력하지 않고 접근을 해도 originURL이 뜨더군요.


그래서 referer의 문제라고 생각을 했는데 request header에 referer 항목을 올바로 입력해도 마찬가지로 안 되네요 ㅠㅠ



코로나 때문에 다들 경황이 없으실텐데 장황한 질문을 드려서 죄송하네요~


그럼 즐거운 주말 되시고 항상 건강하세요!


답변 달아주실 분들께 미리 감사드려요 ^-^




작성자
이니스프리 119 Lv. (0%) 1876250/115200000EXP

당분간 일신상의 사정으로 쪽지나 댓글로 답변을 드리기 어렵습니다. 죄송합니다.

 

CSVpuymXAAAVVpd.jpg

댓글 7

이니스프리 작성자
profile image
from requests_html import HTMLSession
import time, re, telegram, json
from bs4 import BeautifulSoup
 
## requests와 BeautifulSoup으로 카페 게시글 목록을 불러오는 함수 ##
def list_parse(url, s):
    headers = {
        'Content-Type': 'application/json; charset=utf-8', 
        'Accept-Language': 'ko-KR,ko;q=0.9,en-US', 
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'
    }
    params = {
        'search.clubid' : '25490972', # 카페 ID
        'search.menuid' : '1', # 메뉴 ID
        'search.boardtype' : 'L', # 보드타입
        'search.page' : '1' # 불러올 페이지
    }
    html = s.get(url, headers = headers, params = params).text
    return html, s

## 이 달의 이벤트인 제목의 게시글번호를 추출하여 해당 게시물을 파싱하는 함수 ##
def article_parse(url):
    s = HTMLSession()
    s.get('https://m.cafe.naver.com/ca-fe/web/cafes/25490972/menus/1')
    temp_json, s = list_parse(url, s)
    article_list = json.loads(temp_json)['message']['result']['articleList']
    for a in article_list:
        if '달의 이벤트' in a['subject']:
            print(a['subject'])
            number = str(a['articleId'])
            break
 
    page_url = 'https://m.cafe.naver.com/ca-fe/web/cafes/25490972/articles/' + number + '?fromList=true&menuId=1'
    s.get(page_url)
    headers = {
    'accept': 'application/json, text/plain, */*',
    'accept-encoding': 'gzip, deflate, br',
    'accept-language': 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7,ja;q=0.6',
    'dnt': '1',
    'origin': 'https://m.cafe.naver.com',
    'referer': page_url,
    'sec-fetch-dest': 'empty',
    'sec-fetch-mode': 'cors',
    'sec-fetch-site': 'same-site',
    'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Mobile/15E148 Safari/604.1'
    }
    article_url = 'https://apis.naver.com/cafe-web/cafe-articleapi/cafes/25490972/articles/' + number + '?fromList=true&menuId=1&useCafeId=true'
    temp_json = s.get(article_url, headers=headers).text
    print(temp_json)
    with open('json.txt', 'w') as f:
        f.write(temp_json)
    image_list = json.loads(temp_json)['article']['contentElements']
    for i in image_list:
        print(i)
        #print(i['json'])['originalImage'])
    return article_url


if __name__ == '__main__':
    url = 'https://apis.naver.com/cafe-web/cafe2/ArticleList.json'
    titles = article_parse(url)



현재까지는 대략 이 정도를 작성했는데 말씀드린 부분에서 막혔네요 ㅠㅠ

comment menu
2020.04.05. 10:20

신고

"이니스프리님의 댓글"

이 댓글을 신고 하시겠습니까?

Hanam09
profile image

buid 는 그냥 js에서 생성한 GUID입니다. 없어도 큰 문제가 없는것을 확인하였습니다.

 

fetch("https://apis.naver.com/cafe-web/cafe-articleapi/cafes/25490972/articles/1742?fromList=true&menuId=1&useCafeId=true&buid=", {"credentials":"omit","headers":{"accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9","accept-language":"ko,en-US;q=0.9,en;q=0.8,ko-KR;q=0.7","sec-fetch-dest":"document","sec-fetch-mode":"navigate","sec-fetch-site":"none","upgrade-insecure-requests":"1"},"referrerPolicy":"no-referrer-when-downgrade","body":null,"method":"GET","mode":"cors"});

 

확인중입니다.

comment menu
2020.04.05. 16:53

신고

"Hanam09님의 댓글"

이 댓글을 신고 하시겠습니까?

이니스프리 작성자 → Hanam09
profile image

오오~ 그렇군요! ㅎㄷㄷ

바쁘신데 확인해주셔서 감사합니다 :)

그럼 즐거운 주말 되세요~!!

comment menu
2020.04.05. 18:02

신고

"이니스프리님의 댓글"

이 댓글을 신고 하시겠습니까?

Hanam09
profile image
# Can We Do? > Yes! We Can Do It!

import requests, json

ARTICLE_LIST_MAIN_PATH = 'https://apis.naver.com/cafe-web/cafe2/ArticleList.json'


def getArticleList(CAFE_UNIQUE_ID, REQUEST_LIST_PAGE_NUM, REQUEST_LIST_SCOPE, MODULE_REQUEST_SESSION):

    requestParameter = {
        "search.clubid": CAFE_UNIQUE_ID,
        "search.menuid": REQUEST_LIST_SCOPE,
        "search.page": REQUEST_LIST_PAGE_NUM
    }
    session = MODULE_REQUEST_SESSION
    request = session.get(ARTICLE_LIST_MAIN_PATH, params=requestParameter)
    resp = request.text
    if request.status_code == 200:
        return json.loads(resp)
    else:
        print("아이고야... 오늘 장날인가 봅니다.")
        return False

def getArticleBody(CAFE_UNIQUE_ID, ARTICLE_UNIQUE_ID, MODULE_REQUEST_SESSION):
    Request_URI = "https://apis.naver.com/cafe-web/cafe-articleapi/cafes/"+CAFE_UNIQUE_ID+"/articles/"+ARTICLE_UNIQUE_ID
    request = MODULE_REQUEST_SESSION
    
    resp = request.get(Request_URI)
    return json.loads(resp.text)["article"]
    

def main():
    MainSession = requests.Session()
    response = getArticleList(25490972, 1, 1, MainSession)
    ArticleList = response['message']['result']['articleList']

    for Article in ArticleList:
        if '달의 이벤트' in Article["subject"]:
            print(Article["subject"])
            number = str(Article["articleId"])
            break
    print(getArticleBody("25490972", number, MainSession))

main()



잘 되는것 같습니다.

comment menu
2020.04.05. 18:25

신고

"Hanam09님의 댓글"

이 댓글을 신고 하시겠습니까?

이니스프리 작성자 → Hanam09
profile image

오오~ 감사합니다!! ^^


그런데 제가 그대로 ctrl+c, v해서 실행해봤는데 제가 뭘 잘못했는지 모르겠지만 그래도 브라우저에서 보는 것과 다른데요 ㅠㅠㅠㅠㅠ



첫번째 짤이 올려주신 소스로 얻은 JSON 값인데요~


image의 url에 있는 URL로 접근하면 404 에러가 뜨거든요 ㅠㅠ


아마도 네이버측에서 막아놓은 것 같아요 ㄷㄷ


두번째 짤이 브라우저에서 긁은 것인데 originalImage의 URL로 접근하면 제대로 된 이미지가 뜨더군요~!



제가 어디에서 잘못한 것일까요오??


역시 크롤링의 세계는 심오하고 어렵군요 ㅜㅜ


그럼 즐거운 주말 저녁 되세요~!




comment menu
2020.04.05. 19:44

신고

"이니스프리님의 댓글"

이 댓글을 신고 하시겠습니까?

title: 황금 서버 (30일)humit
profile image

로그인 여부에 따라서 로그인이 되어 있는 경우에만 originalImage가 노출이 되고, 로그인이 되지 않은 경우에는 originalImage가 노출이 되지 않는 걸로 확인됩니다.

로그인이 안되더라도 이미지를 띄우는 것이 목표라면 image > url 에 있는 주소에다가 type 값을 query string으로 전달을 해주면 됩니다.

 

ex) https://mcafethumb-phinf.pstatic.net/MjAyMDA0MDJfMTcy/MDAxNTg1Nzk1NjMwOTAy.2lPNDpuQRjUbFdvfPrB5SWLuTzc1r5jtF2BFx8W99gIg.sTxyf_9O9Yb2vj-VErglaujvR6K6mkvQEMQhuAV4ydgg.JPEG/4-5.jpg?type=w740


comment menu
2020.04.07. 23:15

신고

"humit님의 댓글"

이 댓글을 신고 하시겠습니까?

이니스프리 작성자 → humit
profile image

코로나 때문에 학사일정이 꼬여서 바쁘실텐데 설명해주셔서 정말 감사합니다!!

이것 때문에 며칠 고민했는데 이렇게 간단히 해결되는 방법이 있을줄은 꿈에도 몰랐네요 ㅎㄷㄷ

그럼 humit 님께서도 좋은 하루 되시고 항상 건강하세요 :)

번번이 큰 도움을 주셔서 진심으로 감사드려요~! ^-^

comment menu
2020.04.08. 10:45

신고

"이니스프리님의 댓글"

이 댓글을 신고 하시겠습니까?

권한이 없습니다.
번호 제목 글쓴이 날짜 조회 수
공지 [작업 완료] 설 명절 맞이 서버 업데이트 안내 3 마스터 24.02.11.17:21 394
공지 [중요] 호스팅 만료와 관련하여 일부 수칙이 변경됩니다. 4 마스터 23.01.14.02:23 4075
공지 [필독] 질문하는 방법 17 마스터 18.02.23.03:09 4465
922 계속 사용중이던 네트워크 공유 폴더가 갑자기 액세스 불가라고 뜹니다. 6 image 장윤서 18.06.07.16:55 34331
921 팀뷰어 대체할 원격 제어 프로그램 추천 부탁드립니다 16 이니스프리 17.11.30.15:38 32325
920 엑셀 그래프의 축 간격 조절 문제입니다. 2 image 국내산라이츄 17.08.10.11:06 12483
919 아이폰/아이패드 충전기 발열 관련 질문 드립니다 9 image 이니스프리 19.05.02.22:52 11105
918 에러 523 해결법 4 입체그림 20.02.21.16:48 6690
917 PyQt 실행시 프리징 현상 관련하여 질문 드립니다! ㅠㅠ 3 이니스프리 19.07.06.03:37 6685
916 프린터가 지 맘대로 프린트를 하네요. 3 곰도리푸 18.04.04.18:20 6018
915 윈도우용 메일 클라이언트가 필요합니다. 9 네모 18.01.11.20:15 5867
914 크롬에서 특정 사이트 접속 문제 관련하여 질문 드립니다 9 이니스프리 17.03.27.18:03 5309
913 오라클 클라우드 프리티어 가입이 안 되네요 ㅠㅠ 20 이니스프리 20.06.26.21:31 4827
912 파이썬 에디터로 어떤 것이 좋나요? 14 NoYeah 20.01.08.21:08 4525
911 라떼판다와 라즈베리 파이 중 어느 쪽을 사는 게 나을까요? 9 제르엘 18.10.14.19:25 3827
910 나무 위키의 수익구조는 무엇일까요? 2 NoYeah 18.03.18.15:56 3808
909 파티션 복구 프로그램 TestDisk 잘 아시는 분 계시나요? 29 이니스프리 17.11.10.14:53 3745
908 IE11에서 이미지가 깨지는 현상을 해결할 수 있을까요? 2 이니스프리 19.08.02.00:01 3702
907 파일질라로 연결하니까 보안되지 않은 서버입니다. TLS를 통한 FTP를 지원하지 않습니다. 이렇게떠요 해결방안좀 1 마카오 16.09.11.00:57 3654
906 자바스크립트 FormData와 관련된 메서드의 IE 호환성과 관련하여 질문 드립니다 ^^ 6 image 이니스프리 19.08.05.14:22 3426
905 선택약정 안 되는 중고폰의 경우에는 어떤 단점이 있는 것인가요?? 6 이니스프리 20.01.21.14:30 3100
904 집에서 시놀로지 NAS로 워드프레스나 미디어위키 돌리면 느릴까요? 10 이니스프리 17.01.16.20:56 2979
903 [Requests] multipart/form-data의 전송에 대해 질문 드립니다 ^^ 4 이니스프리 19.12.18.22:00 2904