2020년 7월 1일 수요일

Python Ebook Crolling

1. 사연

여기엔 긴 사연이 있다.

요즘 대학교 도서관 사이트는 외부 사이트를 연결 시켜줘서 유료 자료를 공짜로 보게 해준다. 나는 등록금을 거의 낸 적이 없으므로 진짜 공짜로 외부 자료를 열람할 수 있었다. 별로 보진 않았지만.. 그래도 이번주에 책 하나를 평지에 배달시켜놨긴 했다.

중요한건 그게 아니다. 나는 미션을 받은 것이다. 도서관과 연결된 곳에 있는 e-Book 을 따오라는 미션을 말이다. 이전에 크롤링 몇번 한 적이 있어서 기억 더듬는거 포함해서 한시간이면 끝나겠거니 했는데, 그런데 여기서 문제가 발생했다. 저거 url이 암호환지 뭔지가 걸려있었다.

크롬에는 개발자 도구 라는게 있어서 페이서 소스를 그냥 볼 수 있다. 보통은 이미지 파일의 경우

"http://viewer.igroupnet.com/viewer/service/iglib3/COLB0000801/page/150/1.png" 이러고 만다. 저기에 있는 숫자만 바꿔주면 전체 파일 받는건 일도 아니다. 게다가 다운받는 코드는 매우 짧다. 여러 모듈이 있는데, 잠깐만 검색해도 아래와 같은 코드가 나온다.

1

2

3

4

5

6

7

8

import requests

url='http://viewer.igroupnet.com/viewer/service/iglib3/COLB0000801/page/150/1.png?b7d251a764d8ec82b1687e6ce1e83ada'

savename='1.png'

response=requests.get(url)

with open(savename, "wb") as outfile:

outfile.write(response.content)

근데 저거 보면 알겠지만 ? 나오고 이상한 암호화된 뭔가가 있다. 그래서 저걸로 그대로 하면 검은 이미지 파일만 튀어나온다. 여기에서 data url 이 있길래 그걸로 했더니 되긴 하는데, 자세히 조사는 안했지만 url 자체에 binary로 데이터를 쑤셔박은 비주얼이었다. 아마 페이지 내부 소스를 가공한 뭔가일 것 같다.

그럼 뭐가 남느냐? 서론이 길었다. Selenium 이 있다.

이건 마우스나 키보드가 아니라 코드로 크롬이나 파이어폭스 같은 인터넷 브라우저를 조종하는 라이브러리다. 코드로 마우스나 키보드를 조정하는게 아니라, 브라우저 자체를 조정하기 때문에 인터페이스가 편리하다. 사용처는 원래 크롤링 짓이 아니었는데, 빅데이터가 뜨니까 그런 용도로 많이 사용한다.

2. 본론

4시간 대충 보고 만든거라서 자세히는 모른다.

앞으로 사용하면 더 추가하고 그럴거다.

내용이 복잡한게 없어서 아래 사이트보고 웬만한건 해결된다.

우선 웹브라우저를 다운 받아야한다. 파이썬은(다른언어도 됨) 이 프로그램을 실행시키고 명령을 내리는 중개자에 불과하다.

아래는 내가 크롤링하는데 쓴 전체 코드다. 메소드 설명같은건 뒤에 넣었다.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

!pip install selenium

from selenium import webdriver

from selenium.webdriver.common.keys import Keys

import time

path = "chromedriver"

driver = webdriver.Chrome(path)

driver.get("https://library.korea.ac.kr/login")

driver.find_element_by_name('id').send_keys(아이디)

driver.find_element_by_name('password').send_keys(비밀번호)

driver.find_element_by_name('login')

driver.find_element_by_xpath('//*[@type = "submit"]').click()

driver.get("https://mlibrary.korea.ac.kr:444/search/detail/EBKTOT000020463317#.Xf30yS8R34A")

driver.find_element_by_xpath('//*[@id="divContent"]/div/div/div[1]/ul/li[9]/p[2]/span/a').send_keys(Keys.ENTER) # 클릭으로 해결 안되면 이걸로 하면 된다

driver.switch_to.window(driver.window_handles[1])

driver.find_element_by_name('id').send_keys(아이디)

driver.find_element_by_name('password').send_keys(비밀번호)

driver.find_element_by_name('login')

driver.find_element_by_xpath('//*[@type = "submit"]').click()

time.sleep(3)

driver.find_element_by_xpath('/html/body/main/div[2]/div[3]/a[1]').send_keys(Keys.ENTER)

driver.switch_to.window(driver.window_handles[2])

defaultUrl = input('문자열을 입력하세요: ')

leftUrl = input('문자열을 입력하세요: ')

driver.execute_script('''window.open("http://google.com","_blank");''')

driver.switch_to.window(driver.window_handles[3])

driver.set_window_size(1843, 2925)

for page in range (1, 350):

time.sleep(2) # 필요 없는데 혹시나 해서 넣었다.

driver.get(defaultUrl + str(page) + leftUrl)

screenshot_name = "book/" + str(page) + ".png"

driver.save_screenshot(screenshot_name)

내가 다운받을 데이터의 url 구조는 3부분으로 이루어져 있다.

'http://viewer.igroupnet.com/viewer/service/iglib3/COLB0000801/page/150/1.png?b7d251a764d8ec82b1687e6ce1e83ada - 전체

http://viewer.igroupnet.com/viewer/service/iglib3/COLB0000801/page/150/ -고정된 거

1.png - 페이지 번호와 데이터 확장자

?b7d251a764d8ec82b1687e6ce1e83ada - 로그인 해서 viewer 를 들어갈 때 마다 갱신되는 무언가.

저 무언가 때문에 도서관 로그인을 하지 않으면 다운이 안된다. request 같은 모듈이 작동하지 않은 이유가 이거일 것이다. 먼저 로그인 해서 켜놔도 웹브라우저에서 따로 로그인을 안하면 같은 주소라도 안열린다. 그렇기 때문에 로그인 작동 방식은 잘 모르니까, 크롬을 켜서 도서관에 들어가서 로그인을 하고 원하는 e-book 사이트에 들어간다. 간혹 클릭 명령어에 에러가 뜨기도 하는데, 엔터 명령어로 하면 된다.

로그인해서 무사히 viewer 에 접속했다면 갱신되는 그 무언가를 따주자. 당연하게도 html 소스에 데이터가 없다. 여기서 기존의 크롤링 방식이 또 안먹힌다. 그러니까 Sources 에서 직접 로딩된 이미지 url 을 찾아줘야한다. Selenium 에 이 기능이 있는지 한시간을 찾아봤는데 없었다. 있으면 누가 알려줬으면 좋겠다.

url에서 갱신되는 그 무언가를 찾으면 내가 직접 입력한다. 여기서 내가 삽질을 한 부분이 있다. viewer 에서 접속을 해제하면 이미지 10장을 찾고 난 후, 그 무언가가 무효화된다. 여기에 주의하자. 나는 그것도 모르고 무조건 10번 갱신인줄 알고 절망에 빠져 있었다. 만약 그런 구조였으면 이거 던졌다. 새 탭을 열고 거기서 url 을 조합해서 캡쳐를 하나하나 하자.

끝.

3. 사용한 것들

webdriver.Chrome(path) 에서 path 은 웹 브라우저의 경로이다. 웹 브라우저를 실행 시키고 직접 명령을 내리는 것이므로 당연한 코드이다. 결과로 나온 객체를 이제부터 driver 라고 하겠다. 이름은 당연히 제각각이다.

driver.get(주소) - 현재 선택된 탭에서 주소 열기

driver.find_element_by_name(이름) - 아래의 html 코드? 저기에서 name = 이름 인 element 를 찾아준다.

driver.find_element_by_xcode(경로) - 경로 나름 문법이 있는데, 크롬은 원하는 섹터에서 왼쪽 클릭하면 알아서 경로 복사 해준다.

driver.execute_script('''window.open("http://google.com","_blank");''') - 새 탭을 열어준다. 내가 스크립트를 공부 안해서 모른다.

driver.switch_to.window(driver.window_handles[3]) - 탭 포커스를 바꿔준다. 인덱스 값은 0부터 차례대로 탭들을 가리킨다.

driver.save_screenshot(경로) - 스샷, 경로에 알아서 저장시킨다.

댓글 없음:

댓글 쓰기

List