조회 수 2169 추천 수 0 댓글 1
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
Extra Form
라이선스 기타(따로 작성)

안녕하세요?


humit 님의 도움으로 싸이월드 미니홈피 백업 스크립트를 허접하게나마 완성했습니다.


원래 의도는 최대한 selenium을 사용하지 않고 작성하는 것이었지만


'더 보기'를 클릭하는 부분 등 여러 부분에서 javascript가 사용된 관계로 부득이 selenium에 많은 부분을 의존하였습니다.


짧은 시간에 완성하다보니 부족한 점이 많은 스크립트이지만


싸이월드 도메인 만료를 앞두고 급히 필요하신 분들이 계실 것 같다는 생각에 일단 올립니다.



from bs4 import BeautifulSoup
from selenium import webdriver
import urllib, time, os
import urllib.request
from urllib.parse import unquote

driver = webdriver.Firefox(executable_path='geckodriver')
driver.implicitly_wait(15)
waiting_time = 3 # time.sleep()의 대기시간을 지정합니다.

def parse():
    html = driver.page_source
    soup = BeautifulSoup(html, 'html.parser')
    return soup

def naming(filename, extension):
    full_filename = filename + extension
    add_number = 1
    while os.path.isfile(path + '\\' + full_filename) == True: # 파일명이 중복되는 경우를 처리합니다.
        full_filename = filename + '-' + str(add_number) + extension
        add_number += 1
    full_path = path + '\\' + full_filename
    return full_path

url = '미니홈피 URL을 입력하세요!!!'
driver.get(url)
time.sleep(waiting_time)
if driver.current_url == 'http://www.cyworld.com/error/error.html' or driver.title == '싸이홈 | 에러메세지':
    print("Page doesn't exist.")
    quit()

# '더보기'를 마지막까지 반복 실행합니다.
while True:
    soup = parse()
    button = soup.find('p', attrs = {'class' : 'btn_list_more'})
    if button['style'] == '':
        driver.execute_script("getPostList('more','');")
        time.sleep(1)
    else:
        break

# 미니홈피의 작성자 이름으로 폴더를 생성합니다.
path = os.getcwd() + '\\' + soup.select_one('input#homenm')['value']
if not os.path.exists(path):
    print('New directory "%s" was created.' % path)
    os.mkdir(path)

count, count_image, count_swf = 0, 0, 0
while True:
    try:
        driver.execute_script("viewDetail(" + str(count) + ",'Y');") # 게시글로 이동합니다.
        time.sleep(waiting_time)
        frame = driver.find_element_by_xpath('/html/body/div[1]/article[2]/iframe')
        driver.switch_to.frame(frame) # 게시글의 프레임으로 이동합니다.
        time.sleep(1)
        soup = parse()
        date = soup.select_one('div.view1 p') # 태그에 작성일이 들어있습니다.
        # 게시글을 작성한 날짜를 추출하여 파일명으로 지정합니다.
        unwanted = date.find('strong')
        unwanted.extract() # p 태그 내부의 strong 태그(글 작성자)를 제거합니다.
        filename = date.text.replace('\n', '').split()[0].replace('.', '-')
        if soup.select_one('figure img') != None: # 이미지 파일을 처리합니다.
            try:
                image = soup.select_one('figure img')
                extension = '.' + image['src'].split('.')[-1] # 확장자를 추출합니다.
                full_path = naming(filename, extension)
                urllib.request.urlretrieve(unquote(image['src']), full_path)
                if os.path.getsize(full_path) < 1024: # 1kb 이하의 파일인 경우 삭제합니다.
                    os.remove(full_path)
                else:
                    count_image += 1
            except:
                pass
        if soup.select_one('div.webPage object param') != None: # swf 파일을 처리합니다.
            try:
                image = soup.select_one('div.webPage object param')
                extension = '.' + image['value'].split('.')[-1] # 확장자를 추출합니다.
                full_path = naming(filename, extension)
                req = urllib.request.Request(image['value'])
                req.add_header('Referer', url)
                sourcecode = urllib.request.urlopen(req).read()
                with open(full_path, 'wb') as f:
                    f.write(sourcecode)
                if os.path.getsize(full_path) < 1024: # 1kb 이하의 파일인 경우 삭제합니다.
                    os.remove(full_path)
                else:
                    count_swf += 1
            except:
                pass
        driver.switch_to.default_content() # 원래의 프레임으로 돌아갑니다.
        time.sleep(1)
        count += 1
    except:
        break

print('Total downloaded images : %d files' % count_image)
print('Total downloaded flashes : %d files' % count_swf)
driver.quit()



참고로 예전에 올려놓은 이미지가 뜨지 않는 경우도 있더군요.

(이미지 링크가 깨진 것인지, 싸이월드 측에서 백업하는 과정에서 파일 자체가 삭제된 것인지는 모르겠습니다)


이런 경우에 이미지 파일이 흰색으로 뜨는 경우가 있어서 파일 사이즈를 확인한 후 삭제하도록 처리했습니다.

(사이즈보다는 RGB로 판단하는 것이 정확하겠지만, swf 파일의 경우에 어떻게 처리해야 되는지 모르겠네요)


그리고 78~80행에서 swf 파일을 다운로드 하려면 referer가 필요한데 이 부분에서 막혀서 고생했네요.


이 부분에 결정적 도움을 주신 humit 님께 다시 한 번 감사드립니다.


최대한 안정적으로 구동하게 하려고 노력했는데 그 결과 테스트 결과 무난하게 구동되지만


스크립트 자체만 놓고보면 전반적으로 여러 군데에 군더더기가 있네요 ㅠㅠ


함수로 처리해서 좀 더 간결하게 대략 80행 정도로 작성하면 좋겠지만, 제가 실력도 없고 요새 시간이 부족했습니다.



이것으로 추억의 싸이월드도 굿바이네요~


추억을 오래 간직하려면 역시 아마존 라이트세일을 활용해야 되는 것일까요? ㅎㅎ


그럼 스포어 회원님들께서도 감기 조심하시고 굿밤 되세요! ^-^

  • profile
    이니스프리 2021.03.13 22:24

    오오~ 제 스크립트를 더욱 발전시키신 분이 계시네요 ^-^
    https://godpeople.or.kr/mopds/4971280

    "로그인 작업 및 안정성 작업을 추가하였습니다."라고 하시는군요!


List of Articles
번호 분류 제목 글쓴이 날짜 조회 수
63 코드 AWSCLI, in a single file (portable, linux) file Seia 2021.04.10 166
62 코드 c 이진트리 전,중,후위 알고리즘 2 title: 대한민국 국기gimmepoint 2018.04.24 495
61 코드 Cmd 에서 서비스 시작 / 종료하기 1 ProjectSE 2018.02.18 644
60 코드 CMD로 로컬 연결 고정 IP 설정하기 1 title: 황금 서버 (30일)humit 2018.02.06 1038
59 코드 C언어 삼중자를 이용한 코드 title: 황금 서버 (30일)humit 2018.07.22 410
58 코드 Git 저장소에서 자동으로 받아 업데이트하는 쉘 스크립트 5 NoYeah 2017.09.16 651
57 코드 Hello, World!를 출력해보자 18 네모 2018.04.21 568
56 코드 HEX를 RGB로, RGB를 HEX로 바꾸는 PHP 코드 1 네모 2018.05.05 507
55 코드 html 초보가 만든 자소서 4 title: 대한민국 국기gimmepoint 2018.04.21 652
54 코드 JavaScript에서 파이썬 문자열 처리 함수 중 하나 (바인딩)를 구현 7 Seia 2020.01.20 464
53 코드 Koa에서 자동으로 라우팅 채워주기 Seia 2020.01.22 438
52 코드 [JS] http를 https로 리디렉션! 3 Hanam09 2018.12.30 674
51 코드 [JS] 클라이언트단 GET Parameter Hanam09 2019.11.16 467
50 코드 [JS]클라이언트에서 Ip를 얻어보자 2 Hanam09 2019.01.21 625
49 코드 [PHP/Javascript] 아미나에 자동으로 게시글을 생성하고 Ajax로 전송하여 결과를 표시하기 2 file 이니스프리 2019.07.09 777
48 코드 [PHP] 간단한 캐싱 클래스 3 title: 황금 서버 (30일)humit 2018.12.06 605
47 코드 [PHP] 그누보드 자동 게시글 작성 - 일본기상협회의 우리나라 날씨를 크롤링한 후 파파고로 번역하여 글 작성 4 file 이니스프리 2018.11.15 657
46 코드 [PHP] 기상청 RSS 시간별 예보 위젯 - cache 적용(?) 9 file 이니스프리 2018.10.28 850
45 코드 [PHP] 기상청 중기예보를 캐러셀로 보여주는 위젯 (매우 허접합니다 ㅠㅠ) 10 file 이니스프리 2018.09.28 647
44 코드 [PHP] 이미지를 원하는 크기(원본비율 유지)로 리사이즈 하여 출력 (원본 이미지는 수정하지 않습니다) 6 이니스프리 2018.12.20 7714
Board Pagination Prev 1 2 3 4 Next
/ 4