json으로 저장할때 이미 있는 내용은 패스 하고싶어요

조회수 914회

크롤링해서 얻은값을 json에 저장할때 중복으로 저장되는걸 막고싶어요

크롤러가 돌아가다 자주 멈춰서 계속 재실행 해주는데요

크롤러가 멈춰있을때부터 다시 시작하기전까지 내용을 놓칠수있어서 다시 실행할때

조금 뒤부터 크롤러가 돌아가게 했는데 같은내용의 메세지 리스트가 들어가면 똑같이 2번

저장이 되어버려서 메세지 리스트가 들어가면 고유번호('1_no' : num)가 json 파일에 있는지 보고

있으면 저장을 안하고 넘어가게 하고싶은데 어떻게 해야할지 모르겠네요

#메세지 리스트 형식
# 아이디 / 고유번호 / 닉네임/ 시간 / 방제 / 영상링크

['dlehg1346<!>51297273<!>B도*<!>2020-01-19 13:02:02<!>먹방 동생게스트  꿀잼먹방 부산 <!>http://vod-/v1/video123213_1.smil/playlist.m3u8<?>http://vod-/v1/video123213_2.smil/playlist.m3u8'
, 'thsej9805<!>51297276<!>the905<!>2020-01-19 13:02:16<!>꼬마2<!>http://vod-/v1/video12312321_2.smil/playlist.m3u8',
'kej95<!>51297279<!>hsej<!>2020-01-19 13:03:46<!>방송2<!>http://vod-/v1/video132321_1.smil/playlist.m3u8']

위의 메세지리스트로 받은값들을 json 파일로 저장하는 함수를 만들었는데요

def savetojson(msgList):

    for tosave in msgList:
        bjid, num, bjNick, date, title, links = tosave.split('<!>')
        links = links.split('<?>')

        sv = [{
            '1_no' : num,
            '2_bj': bjNick,
            '3_date' : date,
            '4_title': title,
            '5_links': links,

            }]

        with open('data.json', 'r', encoding='utf-8') as json_file:  
            data = json.load(json_file)

            if bjid in dict(data).keys():    # bj 아이디 있으면 그곳에 추가
                data[bjid].append(sv[0])

            else:                            # 없으면 만들어서 추가
                data[bjid] = sv
            json_file.close()

        with open('data.json', 'w', encoding='utf-8') as json_file: 
            json_file.write(json.dumps(data, sort_keys=True, indent=4, ensure_ascii=False))
            json_file.close()

아래는data. json 파일이 저장되어있는 형태

#BJ 아이디별로 묶어져있고 그안에 sv형태
{
    "00000v": [        
        {
            "1_no": "39059686",
            "2_bj": "뚱가_뚱가",
            "3_date": "2018-11-29 00:37:00",
            "4_title": "[생]로스트아크 시리우스 아르카나육성",
            "5_links": [
               "http://183.111085_1.mp4/playlist.m3u8"
            ],

        }
    ],
    "01072593019": [
        {
            "1_no": "39058930",
            "2_bj": "흑징이",
            "3_date": "2018-11-29 00:17:10",
            "4_title": "[생][흑징이]스타팀플 ",
            "5_links": [
                "http://125.209.223_209120452_1.mp4/playlist.m3u8",
                "http://101.9120452_2.mp4/playlist.m3u8",

            ],

        }
    ]
}

1 답변

  • 좋아요

    1

    싫어요
    채택 취소하기

    좋은 생각이 아닌 것이 json 파일을 데이터베이스 같이 사용하고 싶은 것 같네요?

    중복되는 것은 pass하고 신규는 bj별로 저장하고 그런데 잘 생각해보면 제목을 바꿀 수도 있잖아요? 1_no 만 unique 하지 나머지 값들은 변경이 될 수 있는데...update 되면 어떻해 할 것인가요?

    이런 경우는 별도의 database 를 사용하는 편이 낫습니다.

    import os
    import json
    from collections import namedtuple
    
    
    SAVE_FILENAME = 'data.json'
    
    msgList = ['dlehg1346<!>51297273<!>B도*<!>2020-01-19 13:02:02<!>먹방 동생게스트  꿀잼먹방 부산 <!>http://vod-/v1/video123213_1.smil/playlist.m3u8<?>http://vod-/v1/video123213_2.smil/playlist.m3u8'
    , 'thsej9805<!>51297276<!>the905<!>2020-01-19 13:02:16<!>꼬마2<!>http://vod-/v1/video12312321_2.smil/playlist.m3u8',
    'kej95<!>51297272<!>hsej<!>2020-01-19 13:03:46<!>방송2<!>http://vod-/v1/video132321_1.smil/playlist.m3u8']
    
    BS = namedtuple('BS', 'id, no, bj, date, title, links')
    
    L = [BS(*tosave.split('<!>')) for tosave in msgList]
    D = {bs.id:[{'1_no':bs.no, '2_bj':bs.bj, '3_date':bs.date, '4_title':bs.title, '5_links':bs.links.split('<?>')}] for bs in L}
    
    
    
    if os.path.isfile(SAVE_FILENAME):    # 파일 존재하면 update
        with open(SAVE_FILENAME, 'r', encoding='UTF-8') as f:
            loaded_json = json.load(f)
    
        exist_bs = [bs for bs in D.items() 
                                    if bs[0] in loaded_json.keys() 
                                        if bs[1][0]['1_no'] not in (bs['1_no'] for bs in loaded_json[bs[0]])]    # bj 존재 and no가 중복되지 않는 경우
        new_bs = [bs for bs in D.items() 
                                  if bs[0] not in loaded_json.keys()]   # 신규
    
        for bs in exist_bs: # 존재하므로 기존 리스트에 추가
            loaded_json[bs[0]].append(*bs[1])
        for bs in new_bs:  # 신규추가
            loaded_json[bs[0]] = bs[1]
    
        with open(SAVE_FILENAME, 'w+', encoding='UTF-8') as f:
            json.dump(loaded_json, f, ensure_ascii=False)
    else:    # 파일이 없으면 신규
        with open(SAVE_FILENAME, 'w', encoding='UTF-8') as f:
            json.dump(D, f, ensure_ascii=False)
    
    • 매번 감사합니다 저 고유번호가 실시간 주소가 아닌 방송이 종료되어야 생성되는 다시보기에 부여되는 번호라 저 번호로만 구별해도 될듯해서요, 데이터베이스는 제가 아직 공부를 안했는데 추천해주신대로 데이터 베이스를 사용하고싶으면 책 뒤쪽에있는 mysql을 공부하면 될까요? nyw123 2020.1.19 18:47
    • 크롤링 결과를 json 파일에 계속 쌓는건 관리도 어렵고 불편한 일입니다. python 에는 기본적으로 sqlite 가 내장되어 있으니 그것을 활용해도 됩니다. 관계형 데이터베이스를 다뤄본 적이 없다면...시간이 걸리더라도 우선 학습부터 해야지요. 정영훈 2020.1.19 18:56
    • 유니코드라는 겁니다. 그것이 한글이에요. 그것이 보기 싫으면 json.dumps 사용시 ensure_ascii = False 옵션을 주면 됩니다. 정영훈 2020.1.19 20:17

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)