Post

python 공부 2024.04.08

데이터베이스

gui버전으로 sqlitebrowser.org가 존재하는데 cmd로 다운.
다운받는법 만약 받을거면 이 블로그 참고
일단 sqlite.org이 사이트에 가서 다운로드에 맨 밑에 꺼 다운받고 c드라이버로 옮겨줌 압축해제한거.

  • 쿼리문은 db마다 조금씩 다름

sqlite 문법

  • .open naverDB (데이터베이스이름) 이름이 없다면 생성하고 있으면 db에 접속.

  • CREATE TABLE 테이블이름(열이름1 데이터형식, 열이름2 데이터형식,_) ;

예시

1
CREATE TABLE userTable (id char(4), userName char(15), email char(15), birthYear int); 

앞서 계획한 회원 테이블을 생성하고 확인하는 코드.

  • .table
    테이블 하나 볼 수 있음 s붙이면 테이블들

  • .schema userTable
    특정 테이블의 스키마(구조)를 확인하는 목적으로 사용.

  • INSERT INTO userTable VALUES (‘jon’, ‘John Bann’, ‘john@naver.com’, 1990);
    이건 테이블에 값을 넣는거

  • select * from userTable;
    userTable의 전체를 확인. 조건문으로 특정 부분만 확인도 가능 2024-04-08-093647

연습해보기

2024-04-08-094744

.header on
.mode column (;입력하면 안되고 하나 치고 엔터)

그리고 select * from userTable; 하면 이쁘게 표시됨

1
2
3
4
5
6
.header on
sqlite> .mode column;
Error: mode should be one of: ascii box column csv html insert json line list markdown qbox quote table tabs tcl
sqlite> .mode column
sqlite> select * from productTable;
pCode  pName  price  amount

파이썬과 db연결

  1. 데이터베이스에 적기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import sqlite3  # SQLite3 모듈을 가져옵니다.

## 변수 선언 부분 ##
con, cur = None, None  # SQLite3 연결 객체와 커서 객체를 초기화합니다.
data1, data2, data3, data4 = "","","",""  # 사용자 입력을 저장할 변수를 초기화합니다.
sql = ""  # SQL 쿼리를 저장할 변수를 초기화합니다.

## 메인 코드 부분 ##
con = sqlite3.connect("C:/sqlite-tools-win-x64-3450200/naverDB")  # SQLite3 데이터베이스에 연결합니다.
cur = con.cursor()  # 커서 객체를 생성합니다.

while(True):  # 무한 반복문을 시작합니다.
    data1 = input("사용자ID ==> ")  # 사용자로부터 사용자 ID를 입력받습니다.
    if data1 == "":  # 사용자가 아무 입력도 하지 않으면 반복문을 종료합니다.
        break
    data2 = input("사용자 이름 ==> ")  # 사용자로부터 이름을 입력받습니다.
    data3 = input("이메일 ==> ")  # 사용자로부터 이메일을 입력받습니다.
    data4 = input("출생연도 ==> ")  # 사용자로부터 출생 연도를 입력받습니다.
    sql = "INSERT INTO userTable VALUES('"+ data1 + "', '"+ data2 + "', '"+ data3 + "', '"+ data4 + "')"  # 입력받은 데이터를 이용하여 SQL 쿼리를 생성합니다.
    cur.execute(sql)  # 생성된 SQL 쿼리를 실행합니다.
con.commit()  # 데이터베이스에 반영된 작업을 커밋합니다.
con.close()  # 데이터베이스 연결을 닫습니다.

# 포트번호 password 있어야하는데 이 db는 가볍기 때문에 그냥 경로만 두면 된다? 설정하는 방법이 존재하지 않을까 ? 
  1. 데이터베이스 읽어오기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import sqlite3  # SQLite3 모듈을 가져옵니다.

## 변수 선언 부분 ##
con, cur = None, None  # SQLite3 연결 객체와 커서 객체를 초기화합니다.
data1, data2, data3, data4 = "","","",""  # 사용자 입력을 저장할 변수를 초기화합니다.
sql = ""  # SQL 쿼리를 저장할 변수를 초기화합니다.

## 메인 코드 부분 ##
con = sqlite3.connect("C:/sqlite-tools-win-x64-3450200/naverDB")  # SQLite3 데이터베이스에 연결합니다.
cur = con.cursor()  # 커서 객체를 생성합니다.
cur.execute("SELECT * FROM userTable")  # userTable 테이블에서 모든 열을 선택합니다.

print("사용자ID\t사용자이름\t이메일\t  출생연도")
print("------------------------------------------------")
while True:
    row = cur.fetchone()  # 결과 집합에서 다음 행을 가져옵니다.
    if row == None:  # 행이 더 이상 없으면 반복문을 종료합니다.
        break
    data1 = row[0]  # 각 열의 데이터를 변수에 저장합니다.
    data2 = row[1]
    data3 = row[2]
    data4 = row[3]
    print("%5s %15s %20s %d" % (data1, data2, data3, data4))  # 결과를 출력합니다.
con.close()  # 데이터베이스 연결을 닫습니다.
  1. 데이터베이스 읽고 쓰기
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import sqlite3  # SQLite3 모듈을 가져옵니다.
from tkinter import *  # tkinter 모듈에서 모든 것을 가져옵니다.
from tkinter import messagebox  # messagebox 모듈을 가져옵니다.

# 함수 선언 부분 #
def insertData():
    con, cur = None, None  # SQLite3 연결 객체와 커서 객체를 초기화합니다.
    data1, data2, data3, data4 = "", "", "", ""  # 사용자 입력을 저장할 변수를 초기화합니다.
    sql = ""  # SQL 쿼리를 저장할 변수를 초기화합니다.

    con = sqlite3.connect("C:/sqlite-tools-win-x64-3450200/naverDB")  # SQLite3 데이터베이스에 연결합니다.
    cur = con.cursor()  # 커서 객체를 생성합니다.

    data1 = edt1.get(); data2 = edt2.get(); data3 = edt3.get(); data4 = edt4.get()  # 사용자로부터 입력을 받습니다.
    try:
        sql = "INSERT INTO userTable VALUES('" + data1 + "', '" + data2 + "', '" + data3 + "', '" + data4 + "')"  # 입력받은 데이터로 SQL 쿼리를 생성합니다.
        cur.execute(sql)  # SQL 쿼리를 실행합니다.
    except:
        messagebox.showerror('오류', '데이터 입력 오류가 발생함')  # 예외가 발생하면 오류 메시지를 출력합니다.
    else:
        messagebox.showinfo('성공', '데이터 입력 성공')  # 예외가 발생하지 않으면 성공 메시지를 출력합니다.
        con.commit()  # 데이터베이스에 반영된 작업을 커밋합니다.
    con.close()  # 데이터베이스 연결을 닫습니다.

def selectData():
    strData1, strData2, strData3, strData4 = [], [], [], []  # 결과를 저장할 리스트를 초기화합니다.
    con = sqlite3.connect("C:/sqlite-tools-win-x64-3450200/naverDB")  #  SQLite3 데이터베이스에 연결합니다.
    cur = con.cursor()  # 커서 객체를 생성합니다.
    cur.execute("SELECT * FROM userTable")  # userTable 테이블에서 모든 열을 선택합니다.

    # 열 이름을 리스트에 추가합니다.
    strData1.append("사용자ID"); strData2.append("사용자이름")
    strData3.append("이메일"); strData4.append("출생연도")
    strData1.append("-----------"); strData2.append("-----------")
    strData3.append("-----------"); strData4.append("-----------")

    while (True):
        row = cur.fetchone()  # 결과 집합에서 다음 행을 가져옵니다.
        if row == None:  # 행이 더 이상 없으면 반복문을 종료합니다.
            break
        # 가져온 행의 데이터를 리스트에 추가합니다.
        strData1.append(row[0]); strData2.append(row[1])
        strData3.append(row[2]); strData4.append(row[3])

    # 리스트박스를 초기화합니다.
    listData1.delete(0, listData1.size() - 1); listData2.delete(0, listData2.size() - 1)
    listData3.delete(0, listData3.size() - 1); listData4.delete(0, listData4.size() - 1)

    # 리스트에 있는 데이터를 리스트박스에 추가합니다.
    for item1, item2, item3, item4 in zip(strData1, strData2, strData3, strData4):
        listData1.insert(END, item1); listData2.insert(END, item2)
        listData3.insert(END, item3); listData4.insert(END, item4)

    con.close()  # 데이터베이스 연결을 닫습니다.

# 메인 코드 부분 #
window = Tk()  # tkinter 윈도우를 생성합니다.
window.geometry("600x300")  # 윈도우의 크기를 설정합니다.
window.title("GUI 데이터 입력")  # 윈도우의 제목을 설정합니다.

edtFrame = Frame(window); edtFrame.pack()  # 데이터 입력 프레임을 생성하고 배치합니다.
listFrame = Frame(window); listFrame.pack(side=BOTTOM, fill=BOTH, expand=1)  # 리스트 프레임을 생성하고 배치합니다.

# 데이터 입력용 엔트리 위젯을 생성하고 배치합니다.
edt1 = Entry(edtFrame, width=10); edt1.pack(side=LEFT, padx=10, pady=10)
edt2 = Entry(edtFrame, width=10); edt2.pack(side=LEFT, padx=10, pady=10)
edt3 = Entry(edtFrame, width=10); edt3.pack(side=LEFT, padx=10, pady=10)
edt4 = Entry(edtFrame, width=10); edt4.pack(side=LEFT, padx=10, pady=10)

# 데이터 입력 버튼을 생성하고 배치합니다.
btnInsert = Button(edtFrame, text="입력", command=insertData)
btnInsert.pack(side=LEFT, padx=10, pady=10)
# 데이터 조회 버튼을 생성하고 배치합니다.
btnSelect = Button(edtFrame, text="조회", command=selectData)
btnSelect.pack(side=LEFT, padx=10, pady=10)

# 리스트박스 위젯을 생성하고 배치합니다.
listData1 = Listbox(listFrame, bg='yellow'); listData1.pack(side=LEFT, fill=BOTH, expand=1)
listData2 = Listbox(listFrame, bg='yellow'); listData2.pack(side=LEFT, fill=BOTH, expand=1)
listData3 = Listbox(listFrame, bg='yellow'); listData3.pack(side=LEFT, fill=BOTH, expand=1)
listData4 = Listbox(listFrame, bg='yellow'); listData4.pack(side=LEFT, fill=BOTH, expand=1)

window.mainloop()  # GUI 이벤트 루프를 시작합니다.

웹크롤링

  1. html 가져오기
1
2
3
4
5
6
7
8
import urllib.request
import bs4

nateUrl = "https://www.nate.com"
htmlObject = urllib.request.urlopen(nateUrl)
bsObject = bs4.BeautifulSoup(htmlObject, 'html.parser')

print(bsObject)
  1. csv에 날짜와 시간적기
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
import csv  # CSV 모듈을 가져옵니다.
import time  # 시간 관련 모듈을 가져옵니다.
import datetime  # 날짜 및 시간 관련 모듈을 가져옵니다.

# CSV 파일 경로를 지정합니다.
csvName = 'C:/Users/user123/Desktop/learn-py/basic/source/CSV/datetime.csv'

# CSV 파일을 쓰기 모드로 엽니다.
with open(csvName, 'w', newline="") as csvFp:
    csvWriter = csv.writer(csvFp)  # CSV writer 객체를 생성합니다.
    csvWriter.writerow(['연월일', '시분초'])  # 헤더를 CSV 파일에 씁니다.

count = 10  # 반복 횟수를 지정합니다.
while count > 0:
    count -= 1  # 반복 횟수를 감소시킵니다.

    now = datetime.datetime.now()  # 현재 날짜와 시간을 가져옵니다.
    yymmdd = now.strftime('%Y-%m-%d')  # 연월일 포맷으로 변환합니다.
    hhmmss = now.strftime('%H:%M:%S')  # 시분초 포맷으로 변환합니다.
    time_list = [yymmdd, hhmmss]  # 날짜와 시간을 리스트로 만듭니다.
    print(time_list)  # 리스트를 출력합니다.

    # CSV 파일을 추가 모드로 엽니다.
    with open(csvName, 'a', newline="") as csvFp:
        csvWriter = csv.writer(csvFp)  # CSV writer 객체를 생성합니다.
        csvWriter.writerow(time_list)  # 시간 정보를 CSV 파일에 씁니다.

    time.sleep(3)  # 3초 동안 대기합니다.
  1. 날씨 받아와서 csv에 적기
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
39
40
41
42
43
44
45
46
import csv  # CSV 파일을 다루기 위한 모듈을 가져옵니다.
import time  # 시간을 다루기 위한 모듈을 가져옵니다.
import datetime  # 날짜와 시간을 다루기 위한 모듈을 가져옵니다.
import bs4  # BeautifulSoup 모듈을 가져옵니다. 웹 스크래핑에 사용됩니다.
import urllib.request  # 웹페이지 요청을 보내기 위한 모듈을 가져옵니다.

# CSV 파일 경로를 지정합니다.
csvName = 'C:/Users/user123/Desktop/learn-py/basic/source/CSV/jinju_weather.csv'

# CSV 파일을 쓰기 모드로 엽니다.
with open(csvName, 'w', newline='') as csvFp:
    csvWriter = csv.writer(csvFp)  # CSV writer 객체를 생성합니다.
    csvWriter.writerow(['연월일', '시분초', '온도', '습도', '강수량', '풍향'])  # 헤더를 CSV 파일에 씁니다.

# 네이트 날씨 웹페이지 URL을 지정합니다.
nateUrl = "https://news.nate.com/weather?areaCode=11H20701"

# 무한 반복문을 시작합니다.
while True:
    # 웹페이지에 요청을 보내고 HTML 코드를 가져옵니다.
    htmlObject = urllib.request.urlopen(nateUrl)
    webPage = htmlObject.read()
    # BeautifulSoup 객체를 생성합니다.
    bsObject = bs4.BeautifulSoup(webPage, 'html.parser')
    # 웹페이지에서 속초 날씨 정보를 포함한 태그를 찾습니다.
    tag = bsObject.find('div', {'class': 'right_today'})
    # 온도, 습도, 강수량, 풍향 정보를 추출합니다.
    temper = tag.find('p', {'class': 'celsius'}).text
    humi = tag.find('p', {'class': 'humidity'}).text
    rain = tag.find('p', {'class': 'rainfall'}).text
    wind = tag.find('p', {'class': 'wind'}).text

    # 현재 날짜와 시간을 가져와서 포맷팅합니다.
    now = datetime.datetime.now()
    yymmdd = now.strftime('%Y-%m-%d')
    hhmmss = now.strftime('%H:%M:%S')

    # 날씨 정보를 리스트로 만듭니다.
    weather_list = [yymmdd, hhmmss, temper, humi, rain, wind]
    # CSV 파일에 날씨 정보를 추가합니다.
    with open(csvName, 'a', newline='') as csvFp:
        csvWriter = csv.writer(csvFp)  # CSV writer 객체를 생성합니다.
        csvWriter.writerow(weather_list)  # 날씨 정보를 CSV 파일에 씁니다.
        print(weather_list)
    # 3초 동안 대기합니다.
    time.sleep(3)

영화순위 20웹 크롤러

  1. 단순히 텍스트만 가져오는 버전
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# 영화 순위 크롤러

import requests
from bs4 import BeautifulSoup
import tkinter as tk
from tkinter import ttk

def fetch_movie_data():
    URL = "https://m.moviechart.co.kr/rank/realtime/index/image"
    page = requests.get(URL)
    soup = BeautifulSoup(page.content, 'html.parser')
    
    movie_items = soup.find_all('li', class_='movieBox-item')[:20]  # 상위 20개 영화만 선택

    movie_data = []
    for index, item in enumerate(movie_items, start=1):  # 순위를 1부터 시작
        title = item.find('h3').text.strip()  # 영화 제목
        rate = item.find('li', class_='ticketing').find('span').text.strip()  # 예매율
        release_date = item.find('li', class_='movie-launch').text.strip().replace('개봉일 ', '')  # 개봉일
        movie_data.append((index, title, rate, release_date))  # 순위 정보 추가

    return movie_data

def display_movies(root, movies):
    tree = ttk.Treeview(root, columns=('순위', '제목', '예매율', '개봉일'), show='headings', height=len(movies))
    tree.heading('순위', text='순위')
    tree.heading('제목', text='제목')
    tree.heading('예매율', text='예매율')
    tree.heading('개봉일', text='개봉일')
    
    tree.column('순위', anchor='center', width=40)
    tree.column('제목', anchor='w', width=200)
    tree.column('예매율', anchor='center', width=100)
    tree.column('개봉일', anchor='center', width=100)

    for movie in movies:
        tree.insert('', tk.END, values=movie)

    tree.pack(pady=20, expand=True)

def main():
    root = tk.Tk()
    root.title("실시간 영화 순위")
    
    # 20개의 영화 정보를 표시하기 위해 윈도우 크기와 높이 조절
    window_height = 20 * 25  # 가정하는 영화 한 줄의 높이를 20px로 설정
    root.geometry(f"450x{window_height}")

    movies = fetch_movie_data()
    display_movies(root, movies)

    root.mainloop()

if __name__ == "__main__":
    main()
  1. 포스터도 가져오는 버전
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import sys  # 시스템 관련 모듈을 임포트합니다.
import requests  # 웹페이지 요청을 보내는 모듈을 임포트합니다.
from bs4 import BeautifulSoup  # HTML 파싱을 위한 모듈을 임포트합니다.
from PyQt5.QtWidgets import QApplication, QTableWidget, QTableWidgetItem, QLabel, QVBoxLayout, QWidget  # PyQt5의 위젯 및 레이아웃을 임포트합니다.
from PyQt5.QtGui import QPixmap  # 이미지를 표시하기 위한 모듈을 임포트합니다.
from PyQt5.QtCore import Qt  # PyQt5의 핵심 모듈을 임포트합니다.

# 사용자 에이전트 설정: 일부 웹사이트가 비브라우저 트래픽을 차단하는 것을 방지하기 위해
HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'
}

# 영화 데이터를 가져오는 함수
def fetch_movie_data():
    # 실시간 영화 순위 페이지 URL
    URL = "https://m.moviechart.co.kr/rank/realtime/index/image"
    # 페이지 요청 및 응답 저장
    page = requests.get(URL, headers=HEADERS)
    # BeautifulSoup 객체 생성하여 HTML 파싱
    soup = BeautifulSoup(page.content, 'html.parser')
    # 영화 목록 아이템을 찾음
    movie_items = soup.find_all('li', class_='movieBox-item')[:20]  # 상위 20개 영화 정보만 가져옵니다.
    movie_data = []

    # 영화 목록 아이템을 순회하며 필요한 정보 추출
    for index, item in enumerate(movie_items, start=1):  # 영화 순위를 1부터 시작합니다.
        title = item.find('h3').text.strip()  # 영화 제목을 추출합니다.
        rate = item.find('li', class_='ticketing').find('span').text.strip()  # 예매율을 추출합니다.
        release_date = item.find('li', class_='movie-launch').text.strip().replace('개봉일 ', '')  # 개봉일을 추출합니다.
        img_path = item.find('img')['src'].split('source=')[1]  # 이미지 경로를 추출합니다.
        full_img_path = f"https:{img_path}" if not img_path.startswith('http') else img_path  # 완전한 이미지 경로를 생성합니다.
        movie_data.append((index, title, rate, release_date, full_img_path))  # 영화 데이터를 리스트에 추가합니다.

    return movie_data  # 영화 데이터를 반환합니다.


# 이미지를 다운로드하는 함수
def download_image(url):
    try:
        response = requests.get(url, headers=HEADERS)  # 이미지 다운로드를 위해 요청을 보냅니다.
        response.raise_for_status()  # 요청이 성공적으로 이루어졌는지 확인합니다.
        pixmap = QPixmap()  # QPixmap 객체를 생성합니다.
        pixmap.loadFromData(response.content)  # 이미지 데이터를 QPixmap에 로드합니다.
        return pixmap  # QPixmap 객체를 반환합니다.
    except Exception as e:
        print(f"이미지 다운로드 중 오류 발생: {e}")  # 오류 메시지를 출력합니다.
    return QPixmap()  # 빈 QPixmap 객체를 반환합니다.


# 영화 테이블을 표시하는 클래스
class MovieTable(QTableWidget):
    def __init__(self, data):
        super().__init__()
        self.setRowCount(len(data))  # 테이블의 행 수를 데이터 길이로 설정합니다.
        self.setColumnCount(5)  # 테이블의 열 수를 5로 설정합니다.
        self.setHorizontalHeaderLabels(['순위', '포스터', '제목', '예매율', '개봉일'])  # 가로 헤더 레이블을 설정합니다.
        self.set_data(data)  # 데이터를 테이블에 설정합니다.
        self.resizeColumnsToContents()  # 열의 크기를 콘텐츠에 맞게 조정합니다.

        # 행 번호(왼쪽에 있는 인덱스 숫자)를 숨깁니다.
        self.verticalHeader().setVisible(False)

    # 테이블 데이터 설정 함수
    def set_data(self, data):
        for row, (index, title, rate, release_date, img_path) in enumerate(data):
            self.setItem(row, 0, QTableWidgetItem(str(index)))  # 순위 정보를 셀에 추가합니다.
            self.setItem(row, 2, QTableWidgetItem(title))  # 제목 정보를 셀에 추가합니다.
            self.setItem(row, 3, QTableWidgetItem(rate))  # 예매율 정보를 셀에 추가합니다.
            self.setItem(row, 4, QTableWidgetItem(release_date))  # 개봉일 정보를 셀에 추가합니다.

            pixmap = download_image(img_path)  # 이미지를 다운로드합니다.
            if not pixmap.isNull():  # QPixmap이 유효한 이미지인지 확인합니다.
                label = QLabel()  # QLabel을 생성합니다.
                label.setPixmap(pixmap.scaled(95, 95, Qt.KeepAspectRatio))  # 이미지를 셀에 맞게 크기 조정하여 설정합니다.
                self.setCellWidget(row, 1, label)  # 셀에 QLabel을 추가합니다.



def main():
    app = QApplication(sys.argv)  # PyQt 애플리케이션 객체를 생성합니다.
    movie_data = fetch_movie_data()  # 영화 데이터를 가져옵니다.
    table = MovieTable(movie_data)  # 영화 테이블을 생성합니다.
    layout = QVBoxLayout()  # 수직 레이아웃을 생성합니다.
    layout.addWidget(table)  # 테이블을 레이아웃에 추가합니다.

    window = QWidget()  # 위젯을 생성합니다.
    window.setLayout(layout)  # 레이아웃을 위젯에 설정합니다.
    window.setWindowTitle("실시간 영화 순위")  # 창의 제목을 설정합니다.
    window.resize(606, 975)  # 창의 크기를 설정합니다.
    window.show()  # 창을 표시합니다.

    sys.exit(app.exec_())  # 애플리케이션 이벤트 루프를 시작하고 프로그램을 실행합니다.


if __name__ == "__main__":
    main()  # 메인 함수를 호출하여 프로그램을 실행합니다.

크롤링 하면서 배운것

프스터 없이 크롤링하는건 너무 쉬웠는데 포스터에서 막혔었다.
treeview를 계속 쓰면서 표 안에 이미지 들어가는게 안되는 줄 모르고 삽질했다.
PyQt라이브러리로 바꾸고 코드도 그에 맞춰서 코드도 바꾸니까 정상작동했다.

This post is licensed under CC BY 4.0 by the author.