링크에 있는 컨텐츠를 전부 내려 받는 방법

|

Python 3.x 기반의 코드입니다.

상대 경로 사용 방법

소스 코드

from urllib.parse import urljoin

baseUrl = "http://snowdeer.github.io/blog/categories/"

print(urljoin(baseUrl, "/python/2017/05/01/difference-between-python-2-7-x-and-python-3-x/"))
print(urljoin(baseUrl, "/python/2017/11/03/download-file-from-network/"))
print(urljoin(baseUrl, "/python/2017/11/04/get-html-body/"))


실행 결과

http://snowdeer.github.io/python/2017/05/01/difference-between-python-2-7-x-and-python-3-x/
http://snowdeer.github.io/python/2017/11/03/download-file-from-network/
http://snowdeer.github.io/python/2017/11/04/get-html-body/

위의 예제와 같이 baseUrl 변수를 기본 URL 아래의 하위 카테고리 경로까지 지정했음에도, urljoin을 이용해서 만들어진 상대 경로들은 올바르게 만들어지는 것을 확인할 수 있습니다.


재귀적으로 하위 링크들의 컨텐츠를 모두 내려받는 코드

아래의 코드를 활용하면 특정 웹 페이지의 하위 링크들을 재귀적으로 방문하면서 모두 저장하게 됩니다. 단, BeautifulSoup 라이브러리를 이용하여 웹페이지 파싱을 통해 하위 링크들을 검색하기 때문에 저장하려는 대상 페이지에 따라 파싱 코드를 따로 작성을 해야 합니다.

소스 코드

from bs4 import BeautifulSoup
from urllib.request import *
from urllib.parse import *
from os import makedirs
import os.path, time, re

# 이미 처리가 끝난 파일인지 확인하기 위한 용도
finished_files = {}

# HTML 문서 내부의 링크 추출
def get_links_in_html(html, base):
    soup = BeautifulSoup(html, "html.parser")
    links = soup.select("link[rel='stylesheet']")
    links += soup.select("a[href]")
    result_list = []

    for a in links:
        href = a.attrs['href']
        url = urljoin(base, href)   # 링크를 절대 경로로 변환
        result_list.append(url)

    return result_list

# URL로부터 파일 다운로드
def download_file(url):
    out = urlparse(url)
    file_path = "./" + out.netloc + out.path
    if re.search(r"/$", file_path):
        file_path += "index.html"

    folder_path = os.path.dirname(file_path)

    if os.path.exists(file_path):
        return file_path

    if not os.path.exists(folder_path):
        print("make folder: ", folder_path)
        makedirs(folder_path)

    try:
        print("download file: ", url)
        urlretrieve(url, file_path)
        time.sleep(1)
        return file_path

    except:
        print("download failed: ", url)
        return None

def analyze_html(url, root_url):
    file_path = download_file(url)

    if file_path is None:
        return

    if file_path in finished_files:
        return

    finished_files[file_path] = True
    print("analyze_html: ", url)

    html = open(file_path, "r", encoding="utf-8").read()
    links = get_links_in_html(html, url)

    for link_url in links:
        if link_url.find(root_url) != 0:
            if not re.search(r".css$", link_url):
                continue

            if re.search(r".(html|htm)$", link_url):
                analyze_html(link_url, root_url)
                continue

            download_file(link_url)

if __name__ == "__main__":
    url = "https://docs.python.org/3.7/library/"
    analyze_html(url, url)


실행 결과

make folder:  ./docs.python.org/3.7/library
download file:  https://docs.python.org/3.7/library/
analyze_html:  https://docs.python.org/3.7/library/
make folder:  ./docs.python.org/3.7/_static
download file:  https://docs.python.org/3.7/_static/pydoctheme.css
download file:  https://docs.python.org/3.7/_static/pygments.css

BeautifulSoup 라이브러리 활용 웹페이지 파싱(Parsing)

|

Python 3.x 기반의 코드입니다.

BeautifulSoup 라이브러리 설치

pip를 이용해서 설치합니다. 콘솔창에서 다음 명령어를 입력합니다.

> pip install beautifulsoup4


예제 코드

기본적인 사용법

from bs4 import BeautifulSoup

html = """

    
        

Hello, BeautifulSoup

This is a example.

BeautifulSoup helps to scrap web page easily.

</heml> """ soup = BeautifulSoup(html, "html.parser") h1 = soup.html.body.h1 p1 = soup.html.body.p p2 = p1.next_sibling.next_sibling print("h1 = " + h1.string) print("p1 = " + p1.string) print("p1 = " + p2.string) </pre>
## id 요소를 활용한 파싱
from bs4 import BeautifulSoup

html = """

    
        

Hello, BeautifulSoup

This is a example.

BeautifulSoup helps to scrap web page easily.

</heml> """ soup = BeautifulSoup(html, "html.parser") h1 = soup.find(id="title") p1 = soup.find(id="first") print("h1 = " + h1.string) print("p1 = " + p1.string) </pre>
또한 아래의 코드를 이용하여 파싱이 잘 되었는지 확인할 수 있습니다.
soup = BeautifulSoup(html, "html.parser")
print(soup.prettify())

## 기상청 페이지 정보 파싱하기
import urllib.request as req
from bs4 import BeautifulSoup

REST_API = "http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp"
values = {
    'stnId': '108'
}
url = REST_API + "?" + "stnId=108"
res = req.urlopen(url)

soup = BeautifulSoup(res, "html.parser")

title = soup.find("title")
wf = soup.find("wf")

print("title = " + title.string)
print("wf = " + wf.string)

기상청 날씨 정보를 HTML 형태로 가져오기

|

Python 3.x 기반의 코드입니다. 기상청 페이지의 HTML 데이터를 가져오는 예제입니다. 중간에 stnId라는 변수가 나오는데, 지역 코드입니다.

지역 지역 코드
전국 108
서울, 경기도 109
강원도 105
충청북도 131
충청남도 133
경상북도 143
전라북도 146
전라남도 156
경상남도 159
제주도 184


예제 코드

import urllib.request
import urllib.parse

REST_API = "http://www.kma.go.kr/weather/forecast/mid-term-rss3.jsp"

values = {
    'stnId': '108'
}
params = urllib.parse.urlencode(values)

url = REST_API + "?" + params

data = urllib.request.urlopen(url).read()

text = data.decode("UTF-8")
print(text)

HTML 문서 본문 가져오기

|

Python 3.x 기반의 코드입니다. 웹페이지의 HTML 본문을 가져오는 코드입니다.


예제 코드

import urllib.request

url = "http://snowdeer.github.io/"

res = urllib.request.urlopen(url)
data = res.read()

text = data.decode("UTF-8")
print(text)

네트워크 상의 파일 다운로드

|

Python 3.x 기반의 코드입니다. 인터넷 등 네트워크 상에 있는 파일을 다운로드하는 샘플 코드입니다.


예제 코드

urlretrieve() 함수를 이용하여 바로 파일에 저장

import urllib.request

url = "http://snowdeer.github.io/public/img/hello_page.jpg"
filename = "snowdeer.jpg"

urllib.request.urlretrieve(url, filename)
print("Saving image is successful.")


urlopen() 함수를 이용하여 메모리에 저장한 다음 파일에 저장

import urllib.request

url = "http://snowdeer.github.io/public/img/hello_page.jpg"
filename = "snowdeer.jpg"

image = urllib.request.urlopen(url).read()

with open(filename, mode="wb") as f:
    f.write(image)
    print("Saving image is successful.")