무료로 e-Book을 제공하는 해외 사이트 중에서 GoalKicker.com이라는 곳이 있습니다. 프로그래밍 관련 질문과 답변을 주고받는 웹사이트인 스택 오버플로우의 사람들이 집단지성으로 작성한, 각 프로그래밍 언어의 요점노트 정도 되는 내용을 PDF로 편집해서 공짜(정확히는 CC BY-SA 라이센스)로 배포하는 곳이지요. 물론 모두 영어로 된 자료입니다만, 어차피 요즘 세상에 프로그래밍을 하려는데 영어로 된 기술 문서를 못 읽는다는 것은 말이 되지 않지요. 하여튼, 양질의 자료들을 무료로 제공하는 고마운 곳입니다.
그런데, 이곳에서 제공하는 책들이 한두 권이 아닌데(이 글을 작성하는 현 시점에서는 총 47권에 달합니다.) 좋은 자료가 많으니 이걸 몽땅 다운받고 싶다고 생각할 수도 있지 않겠습니까? 네, 바로 제가 그랬습니다. 처음에는 손으로 일일히 한 권씩 다운로드를 했는데, 곰곰히 생각해보니 프로그래밍을 안다는 놈이 이런 반복 작업을 컴퓨터에게 시키지 않는 것은 대단한 삽질에 불과하다는 결론이 나더군요. 그래서 혹시 이곳의 책들을 모두 다운받을 수 있는 스크립트를 다른 사람이 짜서 공개해두지는 않았나 잠깐 구글 검색을 하였고, 잠시 후 다음과 같은 코드를 발견했습니다.
https://www.reddit.com/r/PowerShell/comments/8aujts/free_powershell_pdf_book/dx2uile/
$Books = (Invoke-WebRequest -Uri "http://books.goalkicker.com" -UseBasicParsing).Links.href | Where-Object { $_ -match 'Book$' } "Found $($Books.Count) books to download." ForEach ($Book in $Books) { $PdfName = (Invoke-WebRequest -Uri "http://books.goalkicker.com/$Book" -UseBasicParsing).Links.href | Where-Object { $_ -match '\.pdf$' } "Downloading $PdfName" Invoke-WebRequest -Uri "http://books.goalkicker.com/$Book/$PdfName" -OutFile $PdfName " Finished downloading $PdfName" }
당연히 저는 희희낙락하며 룰루랄라 이 코드를 실행시켜 보았지만, 어쩐 일인지 이 코드는 제대로 동작하지 않았습니다. 살펴보니, 사이트의 URI 구조가 그 사이에 바뀐 모양이더라고요. 시무룩… 그래서, 제가 이 웹사이트의 무료 e-Book들을 일괄 다운로드하는 스크립트를 직접 짜 보기로 하였습니다.
이건 여담인데, 위 원본 코드의 언어인 PowerShell은 실은 대단히 강력한 객체지향 인터프리터 언어입니다. 기본적으로 .Net 프레임워크의 모든 기능을 가져다 쓸 수 있는 것은 물론이고, 화면에 출력되거나 혹은 파이프라인을 통해 리다이렉트되는 거의 모든 실행 결과물이 실은 단순한 텍스트 스트림이 아니라 하나의 .Net 객체라는 놀라운 물건이지요. 심지어는 PowerShell 자체의 능력이 모자라다 싶으면, C# 코드를 인라인으로 삽입하여 바로 사용할 수조차 있습니다. 이런 엄청난 것을 왜 이제서야 알았나 싶을 정도더라고요. 참고로, PowerShell의 최신 버전은 MS에서 오픈소스로 공개하면서 리눅스나 MacOS에서도 사용할 수 있게끔 바뀌었습니다.
어쨌든, 처음에는 위에서 발견한 코드를 기반으로 조금만 수정을 해서 쓰려고 했었습니다. 근데 이 새로 접한 언어에 익숙해지고자 일부러 여러 요소들을 이것저것 추가해보다 보니 대략 마흔 줄 정도 되는 코드가 나와 버렸네요. 제가 작성한 최종 코드는 다음과 같습니다.
# A PowerShell script for downloading free e-books from goalkicker.com in bulk. $uri = "https://goalkicker.com/" $errCount = 0 function pressToContinue { "Press any key to continue...`n" [System.Console]::ReadKey($true) | Out-Null } "This is a PowerShell script that automatically downloads all free e-books provided by goalkicker.com." "Trying to access $uri..." try { $Books = (Invoke-WebRequest -Uri $uri).Links.href -match ".*Book/$" } catch { "Unable to access website." pressToContinue Break } "Successful website access. Found $($Books.Count) books to download." foreach ($book in $Books) { try { $PdfFile = ((Invoke-WebRequest -Uri "$uri/$book" -ErrorAction SilentlyContinue).Links.href -match ".*\.pdf$")[0] $fullLink = "$uri$book$PdfFile" Write-Host -NoNewline "$PdfFile downloading... " Invoke-WebRequest -Uri $fullLink -OutFile $PdfFile -ErrorAction SilentlyContinue Write-Output "Done." } catch { "Failed to download $book" $errCount += 1 } } if ($errCount -eq 0) { "All books have been downloaded." } else { "$($Books.Count - $errCount) Books have been downloaded. $errCount books are missing." } pressToContinue # End of file
이 코드의 사용 방법은 최신 윈도우 기준으로 다음과 같습니다.
- 탐색기에서 적당한 이름의 빈 폴더를 하나 만듭니다. 저는 폴더 이름을
eBooks_goalkicker.com
이라고 지었습니다.
- 해당 폴더 안에
.ps1
확장자를 가진 빈 텍스트 파일을 하나 만듭니다. 저는 이 파일의 이름을_allDownload.ps1
이라고 지었습니다. 굳이 파일 이름 맨 앞에_
(밑줄, Underscore)을 붙인 이유는, 나중에 pdf 파일들이 다운로드되었을 때도 항상 이 스크립트 파일이 탐색기에서 맨 앞에 보이기를 원했기 때문입니다. 어쨌든 이 파일 이름은 스크립트의 실행에 아무런 영향도 주지 않습니다.
- 방금 만든 텍스트 파일을 선호하는 텍스트 편집기로 열고, 위 코드를 복사해서 편집기에 붙여넣고 저장합니다. 사용하는 편집기는 메모장도 좋고, VS Code와 같은 프로그래밍용 에디터도 좋습니다. 다만, 기글하드웨어 사이트에서는 글을 복사할 때 자동으로 맨 밑에 출처 관련 내용이 같이 복사되는데, 이게 그대로 있으면 실행시에 에러가 나니까 직접 지워줘야 합니다.
- 방금 저장한
.ps1
파일을 탐색기에서 마우스 오른쪽 버튼으로 클릭하면, 아마도 메뉴의 [열기] 바로 아래에 [PowerShell에서 실행]이라는 항목이 있을 것입니다. 제가 알기로는 윈도우 7 SP1부터 PowerShell이 윈도우와 함께 설치되어 나온다고 합니다. 요즘 시대에 윈도우 XP나 비스타를 쓰는 사람은 많지 않…겠죠? 여튼, 클릭해 줍니다.
- 스크립트가 실행되면, 스크립트가 있는 폴더에 자동으로 PDF 파일이 다운로드되기 시작합니다. 동시에 화면에는 지금 어느 파일을 다운받고 있는지도 함께 뜹니다. 만약에 인터넷이 연결되어 있지 않다거나 하면, 웹사이트에 접속할 수 없다는 오류 메시지가 뜹니다.
- 모든 작업이 끝나면, 아무 키나 누르라는 영문 메시지가 뜹니다. 만약에 일부 PDF 파일 다운로드에 문제가 있었다면, 몇 개나 그랬는지 표시해주는 기능도 있습니다. 아무 키나 누르면 창이 사라지고, 프로그램이 종료됩니다.
이 코드의 사용/수정/재배포는 완전 자유입니다. 다만, 저는 이 코드의 실행결과를 보증하지 않습니다. 만약에 미래에 위 웹사이트의 주소체계가 다시 바뀌면, 이전의 코드처럼 이 코드도 제대로 작동하지 않겠지요. 참고로 위 웹사이트는 종종 e-Book의 내용을 업데이트하거나 새 e-Book을 추가하는 모양이니, 이 코드를 저장해뒀다가 생각날 때마다 주기적으로 실행해주는 것도 좋을 듯 합니다. 그럼 이만!