Skip to content
ย 
ย 

Repository files navigation

header

ํ”„๋กœ์ ํŠธ ์†Œ๊ฐœ

์„œ์šธ์‹œ ์•„ํŒŒํŠธ ๋งค๋งค๊ฐ€ ์˜ˆ์ธก


์ตœ๊ทผ, ๋ถ€๋™์‚ฐ ๊ฐ€๊ฒฉ์ด ๊ธ‰๋“ฑ๋ฝํ•˜๋ฉฐ ๊ฐ€๊ฒฉ์˜ˆ์ธก์ด ํž˜๋“ค์–ด์ง€๋Š” ์‹ค์ •์ด๋ฉฐ ์•„ํŒŒํŠธ ๋ถ€๋™์‚ฐ ๋งค๋งค์˜ ํƒ€์ด๋ฐ์— ๋Œ€ํ•œ ๊ณ ๋ฏผ๋„ ๋Š˜์–ด๊ฐ€๊ณ  ์žˆ๋‹ค.

์ด์— ์ •ํ™•ํ•œ ์•„ํŒŒํŠธ ๊ฐ€๊ฒฉ์„ ์˜ˆ์ธกํ•˜์—ฌ ์ด๋Ÿฐ ์ด๋“ค์—๊ฒŒ ๋„์›€์ด ๋˜๊ณ ์ž ํ•˜๋Š” ๋งˆ์Œ์—์„œ ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•˜์˜€๋‹ค.

๐Ÿ•˜ ํ”„๋กœ์ ํŠธ ๊ธฐ๊ฐ„

START : 2024.02.21
END : 2024.03.07

๐Ÿง‘โ€๐Ÿ’ป ํŒ€ ๊ตฌ์„ฑ

  • ๊น€์„ธ์—ฐ - ํ”„๋กœ์ ํŠธ ๊ตฌ์ƒ, EDA, ๋ฐ์ดํ„ฐ ์ „์ฒ˜๋ฆฌ, ๋ชจ๋ธ๋ง
  • ์ด๊ตฌํ˜‘ - ์กฐ์žฅ, ๋ฐœํ‘œ, ํ”„๋กœ์ ํŠธ ๊ตฌ์ƒ, EDA, ๋ฐ์ดํ„ฐ ์ „์ฒ˜๋ฆฌ, ์ด์ƒ์น˜ ํ™•์ธ, ๋ชจ๋ธ๋ง, ์•™์ƒ๋ธ”, ํ•˜์ดํผํŒŒ๋ผ๋ฏธํ„ฐ ์ตœ์ ํ™”, GUI ๊ตฌํ˜„
  • ์ •์šฐ์„ฑ - ํ”„๋กœ์ ํŠธ ๊ตฌ์ƒ, EDA, ๋ฐ์ดํ„ฐ ์ „์ฒ˜๋ฆฌ, ์ด์ƒ์น˜ ํ™•์ธ, ๋ชจ๋ธ๋ง, ์•™์ƒ๋ธ”, ํ•˜์ดํผํŒŒ๋ผ๋ฏธํ„ฐ ์ตœ์ ํ™”
  • ์ตœํ•œ์†” - ํ”„๋กœ์ ํŠธ ๊ตฌ์ƒ, ๋ฐœํ‘œ ์ž๋ฃŒ ์ค€๋น„, EDA, ๋ฐ์ดํ„ฐ ์ „์ฒ˜๋ฆฌ, ๋ชจ๋ธ๋ง

โŒจ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ

Language



IDE



์ „์ฒด์ ์ธ ๋ชจ๋ธ๋ง ํ”„๋กœ์„ธ์Šค

๋ฐ์ดํ„ฐ ๋ถ„์„ ๋ฐ EDA, ์ „์ฒ˜๋ฆฌ


๋ฐ์ดํ„ฐ ์ถ”์ถœ

[์„œ์šธ์‹œ ๋ถ€๋™์‚ฐ ์‹ค๊ฑฐ๋ž˜๊ฐ€ ์ •๋ณด] (https://data.seoul.go.kr/dataList/OA-21275/S/1/datasetView.do)

ํ•ด๋‹น ๋ฐ์ดํ„ฐ์…‹์—์„œ 2020๋…„ 1์›” 1์ผ๋ถ€ํ„ฐ 2024๋…„ 2์›” 28์ผ๊นŒ์ง€ ๊ฑฐ๋ž˜๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์˜€์Œ.

์›๋ณธ ๋ฐ์ดํ„ฐ์—์„œ๋Š” 1,332,702๊ฐœ์˜ Row๊ฐ€ ์กด์žฌํ–ˆ์œผ๋ฉฐ, ์ด๋ฅผ 2020๋…„ ์ดํ›„ ๋ฐ์ดํ„ฐ๋กœ ์ž˜๋ผ๋‚ด์–ด ์•ฝ 180,000๊ฐœ์˜ ๋ฐ์ดํ„ฐ๋งŒ์„ ์‚ฌ์šฉํ•จ

  • ์ž์น˜๊ตฌ๋ช…
  • ๋ฒ•์ •๋™๋ช…
  • ๋ณธ๋ฒˆ
  • ๋ถ€๋ฒˆ
  • ๊ฑด๋ฌผ๋ช…
  • ๊ณ„์•ฝ์ผ
  • ๋ฌผ๊ฑด๊ธˆ์•ก
  • ๊ฑด๋ฌผ๋ฉด์ 
  • ์ธต
  • ๊ฑด์ถ•๋…„๋„

Geocoding

๋„ค์ด๋ฒ„ ์ง€๋„ API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›๋ณธ ๋ฐ์ดํ„ฐ์— ์กด์žฌํ•˜๋Š” '๋ณธ๋ฒˆ', '๋ถ€๋ฒˆ'์„ ์ด์šฉํ•ด ์ง€๋ฒˆ์ฃผ์†Œ๋ฅผ ๋งŒ๋“  ๋’ค, ์ง€๋ฒˆ ์ฃผ์†Œ๋ฅผ ์ง€์˜ค์ฝ”๋”ฉํ•˜์—ฌ ์œ„๋„, ๊ฒฝ๋„๋กœ ๋ณ€ํ™˜ํ•จ.

์ถ”๊ฐ€์ ์ธ ๋ฐ์ดํ„ฐ

  • ์„œ์šธ์‹œ ๋ณ‘์›์˜ ์œ„์น˜์™€ ์ •๋ณด
  • ์„œ์šธ์‹œ ํ•™๊ต์˜ ์œ„์น˜์™€ ์ •๋ณด
  • ์„œ์šธ์‹œ ์ง€ํ•˜์ฒ ์—ญ์˜ ์œ„์น˜์™€ ์ •๋ณด
  • ์„œ์šธ์‹œ ๋ฒ„์Šค ์ •๋ฅ˜์†Œ์˜ ์œ„์น˜์™€ ์ •๋ณด
  • ์„œ์šธ์‹œ ํŽธ์˜์‹œ์„ค(์ƒ์—…์‹œ์„ค, ๋ณ‘์˜์›, ๊ณต์› ๋“ฑ)์˜ ์œ„์น˜์™€ ์ •๋ณด
  • ์ „์„ธ๊ฐ€๊ฒฉ์ง€์ˆ˜
  • ์†Œ๋น„์ž ๋ฌผ๊ฐ€์ง€์ˆ˜
  • ์›”๋ณ„ ๊ธฐ์ค€ ๊ธˆ๋ฆฌ
  • ์„œ์šธ์‹œ ๋ฒ•์ •๋™๋ณ„ ๋‚˜์ด๋ณ„ ์ธ๊ตฌ ์ž๋ฃŒ
  • ์•„ํŒŒํŠธ ๋งค๋งค๊ฐ€ ์‹ค๊ฑฐ๋ž˜ ๊ฐ€๊ฒฉ ์ง€์ˆ˜
  • etc.

์ธ๊ตฌ ์ •๋ณด ๋ณ€๊ฒฝ

population['์–ด๋ฆฐ์ด์ธ๊ตฌ'] = population[[f"{age}์„ธ๋‚จ์ž" for age in range(13)] + [f"{age}์„ธ์—ฌ์ž" for age in range(13)]].sum(axis=1)
population['์ฒญ์†Œ๋…„์ธ๊ตฌ'] = population[[f"{age}์„ธ๋‚จ์ž" for age in range(13, 25)] + [f"{age}์„ธ์—ฌ์ž" for age in range(13, 25)]].sum(axis=1)
population['์ฒญ๋…„์ธ๊ตฌ'] = population[[f"{age}์„ธ๋‚จ์ž" for age in range(25, 41)] + [f"{age}์„ธ์—ฌ์ž" for age in range(25, 41)]].sum(axis=1)
population['์ค‘์žฅ๋…„์ธ๊ตฌ'] = population[[f"{age}์„ธ๋‚จ์ž" for age in range(41, 66)] + [f"{age}์„ธ์—ฌ์ž" for age in range(41, 66)]].sum(axis=1)
population['๋…ธ๋…„์ธ๊ตฌ'] = population[[f"{age}์„ธ๋‚จ์ž" for age in range(66, 109)] + [f"{age}์„ธ์—ฌ์ž" for age in range(66, 109)]].sum(axis=1)

0์„ธ๋ถ€ํ„ฐ 109์„ธ๊นŒ์ง€ 1์„ธ์”ฉ ์ •๋ฆฌ๋˜์–ด์žˆ๋˜ ๋‚˜์ด๋ฅผ ์–ด๋ฆฐ์ด (012), ์ฒญ์†Œ๋…„(1324), ์ฒญ๋…„(2540), ์ค‘์žฅ๋…„(4165), ๋…ธ๋…„(66~109)์œผ๋กœ ๋‚˜๋ˆ”

ํƒ€๊ฒŸ๋ณ€์ˆ˜ ๋ณ€๊ฒฝ

image

์•„ํŒŒํŠธ ๋งค๋งค๊ฐ€ ๋ฐ์ดํ„ฐ์— ์žˆ๋˜ "๋งค๋งค๊ฐ€"๋ฅผ "๋ฉด์ ๋‹น ๊ฐ€๊ฒฉ"์œผ๋กœ ๋ณ€๊ฒฝ

ํ•œ๊ฐ• ๋ฐ์ดํ„ฐ ํ™œ์šฉ

from scipy.interpolate import interp1d

hangang_sorted = bridge.sort_values(by='Longitude')

# ๋‹ค๋ฆฌ๋ฅผ ์ฐ์„ ์ขŒํ‘œ๋ฅผ ์„ ํ˜•๋ณด๊ฐ„์œผ๋กœ ์ž‡์Šต๋‹ˆ๋‹ค.
interpolate_lon = np.linspace(hangang_sorted['Longitude'].min(), hangang_sorted['Longitude'].max(), 130) #์„  ์ƒ์— ์žˆ๋Š” ์ขŒํ‘œ๋ฅผ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. 130๊ฐœ
linear_interp = interp1d(hangang_sorted['Longitude'], hangang_sorted['Latitude'], kind='linear')
interpolate_lat = linear_interp(interpolate_lon)

selected_coords = np.column_stack((interpolate_lon, interpolate_lat)) 

# ์„ ํƒ๋œ ์ขŒํ‘œ๋ฅผ ๋‹ด์€ ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„ ์ƒ์„ฑ
selected_coords_df = pd.DataFrame(selected_coords, columns=['Longitude', 'Latitude'])

์„ ์šธ ํ•œ๊ฐ•์„ ์ง€๋‚˜๋Š” ๊ต๋Ÿ‰์˜ ์ค‘์‹ฌ์ขŒํ‘œ๋ฅผ ์„ ํ˜•๋ณด๊ฐ„ํ•˜์—ฌ ์ขŒํ‘œ๋ฅผ ์ถ”์ถœํ•œ๋’ค, ์•„ํŒŒํŠธ์™€์˜ ๊ฑฐ๋ฆฌ๋ฅผ Haversine๊ณต์‹์„ ์ด์šฉํ•˜์—ฌ ์ธก์ •ํ•˜์˜€์Œ.

์ด์ƒ์น˜, VIF ๊ฒ€์‚ฌ, P-valueํ™•์ธ

from statsmodels.stats.outliers_influence import variance_inflation_factor
from statsmodels.tools.tools import add_constant

X.astype(float)
X_const = add_constant(X) 

vif = pd.DataFrame()
vif["VIF Factor"] = [variance_inflation_factor(X_const.values, i) for i in range(X_const.shape[1])]
vif["features"] = X_const.columns

vif["VIF Factor"] = vif["VIF Factor"].apply(lambda x: '{:.0f}'.format(x))
vif

์ด์ƒ์น˜๋Š” ์žˆ์—ˆ์ง€๋งŒ, ์‹ค์ œ ๋ฐ์ดํ„ฐ์ด๋ฏ€๋กœ ์ด์ƒ์น˜์— ๋Œ€ํ•œ ์ œ๊ฑฐ๋Š” ์ƒ๋žตํ•˜์˜€์œผ๋ฉฐ, ๋‹ค์ค‘๊ณต์„ ์„ฑ๊ฒ€์‚ฌ๋ฅผ ํ†ตํ•ด VIF๊ฐ’์ด ๋†’์€ ๋ณ€์ˆ˜๋ฅผ ์ œ๊ฑฐํ•˜์˜€์Œ. ์ œ๊ฑฐํ•˜๊ณ ๋‚˜๋‹ˆ P-value๋Š” ๋‚ฎ๊ฒŒ๋‚˜์˜ด

ํ›„์ง„์†Œ๊ฑฐ๋ฒ•, ์ „์ง„์†Œ๊ฑฐ๋ฒ•, ๊ต์ฐจ์„ ํƒ๋ฒ•

#์ „์ง„์„ ํƒ๋ฒ•

def forward_selection(data, target, significance_level=0.05):
    initial_features = data.columns.tolist()
    best_features = []
    aic_values = []
    
    while len(initial_features) > 0:
        remaining_features = list(set(initial_features) - set(best_features))
        new_pval = pd.Series(index=remaining_features)
        for new_column in remaining_features:
            model = sm.OLS(target, sm.add_constant(data[best_features + [new_column]])).fit()
            new_pval[new_column] = model.pvalues[new_column]
        min_p_value = new_pval.min()
        if min_p_value < significance_level:
            best_feature = new_pval.idxmin()
            best_features.append(best_feature)
            aic_values.append(sm.OLS(target, sm.add_constant(data[best_features])).fit().aic)
        else:
            break
    
    return best_features, aic_values

#ํ›„์ง„์†Œ๊ฑฐ๋ฒ•
def backward_elimination(data, target, significance_level = 0.05):
    features = data.columns.tolist()
    while len(features) > 0:
        features_with_constant = sm.add_constant(data[features])
        p_values = sm.OLS(target, features_with_constant).fit().pvalues[1:] 
        max_p_value = p_values.max()
        if max_p_value >= significance_level:
            excluded_feature = p_values.idxmax()
            features.remove(excluded_feature)
        else:
            break 
    return features

#๊ต์ฐจ์„ ํƒ๋ฒ•
def stepwise_selection(data, target, SL_in=0.05, SL_out=0.05):
    initial_features = data.columns.tolist()
    best_features = []
    while len(initial_features) > 0:
        changed=False
        # ์ „์ง„ ์„ ํƒ
        remaining_features = list(set(initial_features) - set(best_features))
        new_pval = pd.Series(index=remaining_features)
        for new_column in remaining_features:
            model = sm.OLS(target, sm.add_constant(data[best_features + [new_column]])).fit()
            new_pval[new_column] = model.pvalues[new_column]
        min_p_value = new_pval.min()
        if min_p_value < SL_in:
            best_features.append(new_pval.idxmin())
            changed=True
        
        # ํ›„์ง„ ์†Œ๊ฑฐ
        model = sm.OLS(target, sm.add_constant(data[best_features])).fit()
        p_values = model.pvalues.iloc[1:]
        max_p_value = p_values.max()
        if max_p_value > SL_out:
            changed=True
            worst_feature = p_values.idxmax()
            best_features.remove(worst_feature)
        
        if not changed:
            break

    return best_features

์ด๋ฏธ VIF ๊ฒ€์‚ฌ๋ฅผ ํ†ตํ•ด ๋ณ€์ˆ˜๋ฅผ ์ œ๊ฑฐํ•ด์„œ, ์œ ์˜๋ฏธํ•œ ๊ฒฐ๊ณผ๋ฅผ ์–ป์ง€ ๋ชปํ•จ.

๋ชจ๋ธ๋ง

์ตœ์ข…๊ฒฐ๊ณผ

๋ชจ๋ธ R^2 MSE RMSE MAE
RF 0.9249 0.0158 0.1256 0.0862
CatBoost 0.9232 0.0161 0.1270 0.0927
KNN ํšŒ๊ท€ 0.8915 0.0228 0.1510 0.1032
MLP ํšŒ๊ท€ 0.9045 0.0201 0.1417 0.1052
XGBoost 0.9293 0.0148 0.1218 0.0879
์Šคํƒœํ‚น ์•™์ƒ๋ธ” 0.9273 0.0153 0.1235 0.0896

์‚ฌ์šฉํ•œ Columns

  • ์œ„๋„, ๊ฒฝ๋„, ์ƒ์œ„ 10๊ฐœ ๊ฑด์„ค์‚ฌ ์—ฌ๋ถ€, ์—ฐ์‹, ์ธต์ˆ˜, ๊ธฐ์ค€๊ธˆ๋ฆฌ, ๋งค๋งค๊ฐ€ ๋Œ€๋น„ ์ „์„ธ๊ฐ€
  • ๋ฒ•์ •๋™ ์ „์ฒด ์ธ๊ตฌ, ๋ฒ•์ •๋™ ์–ด๋ฆฐ์ด, ์ฒญ๋…„, ๋…ธ๋…„ ๋น„์œจ
  • ์ž์น˜๊ตฌ๋ณ„ ์—ฐ๊ฐ„ ์†Œ๋น„์•ก, ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์ข…ํ•ฉ๋ณ‘์›๊ณผ์˜ ๊ฑฐ๋ฆฌ, ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์ง€ํ•˜์ฒ ์—ญ๊ณผ์˜ ๊ฑฐ๋ฆฌ, 0.7km๋‚ด ์ดˆ๋“ฑํ•™๊ต ๊ฐœ์ˆ˜, 2km๋‚ด ๋ช…๋ฌธ ์ผ๋ฐ˜๊ณ  ๊ฐœ์ˆ˜
  • 1km๋‚ด ์ผ๋ฐ˜ ๋ณ‘์˜์›๊ณผ ์ƒ์—…์‹œ์„ค์˜ ๊ฐœ์ˆ˜, 0.8km๋‚ด ๊ณต์› ๋ฐ ํ•˜์ฒœ์˜ ์กด์žฌ ์—ฌ๋ถ€
  • ํ•œ๊ฐ•๋ณ€์—์„œ 0.4km์ด๋‚ด์— ์žˆ๋Š”์ง€ ์—ฌ๋ถ€, 0.5km๋‚ด ๋ฒ„์Šค ์ •๋ฅ˜์žฅ ์ˆ˜์˜ ์ ˆ๋ฐ˜, ๋ผ๋ฒจ ์ธ์ฝ”๋”ฉ ๋œ ์ž์น˜๊ตฌ

ํ•™์Šต ๋ฐ์ดํ„ฐ ๋ถ„ํ• 

2024๋…„ 1์›” 1์ผ ~ 2024๋…„ 2์›” 28์ผ ๋ฐ์ดํ„ฐ๋ฅผ Test Set์œผ๋กœ ๋งŒ๋“ค๊ณ , ์ „์ฒด ๋ฐ์ดํ„ฐ๋ฅผ 8:2๋กœ Train/Val๋กœ ๋‚˜๋ˆ”

์Šค์ผ€์ผ๋ง

์Šค์ผ€์ผ๋ง์ด ํ•„์š”ํ•œ KNN, ์„ ํ˜•ํšŒ๊ท€๋งŒ ์Šค์ผ€์ผ๋ง์„ ์ ์šฉํ•˜์˜€์Œ

ํ•˜์ดํผํŒŒ๋ผ๋ฏธํ„ฐ ํŠœ๋‹

Optuna ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ•˜์—ฌ ์ตœ์ ํ™”ํ•˜์˜€์Œ

์•™์ƒ๋ธ”

base_models = [
    ('Random Forest', RandomForestRegressor(n_estimators=200, random_state=42, n_jobs=-1)),
    ('CatBoost', CatBoostRegressor(iterations=299, depth=10, learning_rate=0.2953026, random_strength=7, bagging_temperature=0.02308666, border_count=130, l2_leaf_reg=0.042969, random_state=42)),
    ('KNN', knn_pipeline),
    ('Decision Tree', DecisionTreeRegressor(random_state=42))
]

meta_model = XGBRegressor(n_estimators=563, max_depth=3, learning_rate=0.0151, min_child_weight=1, subsample=0.8967, colsample_bytree=0.9831, reg_alpha=3.029,reg_lambda=0.9275, random_state=42)

stacking_model = StackingRegressor(estimators=base_models, final_estimator=meta_model)

stacking_model.fit(X_train, y_train)

์„ฑ๋Šฅ์ด ์ข‹์€ ๋ชจ๋ธ๋“ค์„ ์Šคํƒœํ‚น ํ•˜์˜€์Œ

๊ฒฐ๊ณผ

image

์‹ค์ œ๋กœ Test์…‹์— ๊ฐ€์žฅ ์ ํ•ฉํ–ˆ๋˜๊ฑด XGBoost ์˜€์Œ.

์ถ”๊ฐ€๋กœ, ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฅผ ํ†ตํ•œ ์˜ˆ์ธก

GUI

GUI ์„ค๊ณ„

def update_neighborhoods(*args):
    selected_district = district_var.get()
    neighborhoods_menu['menu'].delete(0, 'end')
    for neighborhood in districts[selected_district]:
        neighborhoods_menu['menu'].add_command(label=neighborhood, command=lambda n=neighborhood: neighborhood_var.set(n))
    neighborhood_var.set(list(districts[selected_district])[0])

def search_action():
    search_input = neighborhood_var.get() + ' ' + entry.get()
    result_text.delete(1.0, "end") 
    result_text.insert("end", "๊ฒ€์ƒ‰์–ด: " + search_input + "\n")
    print("๊ฒ€์ƒ‰์–ด:", search_input)
    search_url = f"https://m.land.naver.com/search/result/{search_input}#mapFullList"

    driver.get(search_url)
    html = driver.page_source
    soup = BeautifulSoup(html, 'html.parser')
    
    script = soup.find('script', string=re.compile(r'lat\s*:\s*\'\d+\.\d+\''))
    if script:
        lat_match = re.search(r'lat\s*:\s*\'(\d+\.\d+)\'', script.string)
        lng_match = re.search(r'lng\s*:\s*\'(\d+\.\d+)\'', script.string)
        if lat_match and lng_match:
            lat = lat_match.group(1)
            lng = lng_match.group(1)
            predicted_price = predict_price(lat, lng, search_input, district_var.get(), neighborhood_var.get())
            result_text.insert("end", f"์˜ˆ์ธก๋œ ๊ฐ€๊ฒฉ: {int(predicted_price[0])}๋งŒ์›\n")

        else:
            result_text.insert("end", "์œ„๋„์™€ ๊ฒฝ๋„๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.\n")
    else:
        print("์œ„๋„์™€ ๊ฒฝ๋„ ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๋Š” ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
    result_text.pack() 
    

root = tk.Tk()
root.title("๋„ค์ด๋ฒ„ ๋ถ€๋™์‚ฐ ๊ฒ€์ƒ‰")

result_text = tk.Text(root, height=10, width=50)

district_var = tk.StringVar(root)
district_var.set('์„ ํƒํ•˜์„ธ์š”') 
district_var.trace('w', update_neighborhoods) 
districts_menu = ttk.OptionMenu(root, district_var, *districts.keys())
districts_menu.pack(side=tk.LEFT, padx=10)

neighborhood_var = tk.StringVar(root)
neighborhoods_menu = ttk.OptionMenu(root, neighborhood_var, '')
neighborhoods_menu.pack(side=tk.LEFT, padx=10)
update_neighborhoods()

entry = ttk.Entry(root)
entry.pack(side=tk.LEFT, padx=10)

search_button = ttk.Button(root, text="๊ฒ€์ƒ‰", command=search_action)
search_button.pack(side=tk.LEFT, padx=10)

root.mainloop()

tkinter์™€ selenium์œผ๋กœ ๊ตฌํ˜„ํ•˜์˜€์Œ

๋Œ€๋žต์ ์ธ ๊ตฌ์กฐ

image

๊ธฐ๋ณธ ํ™”๋ฉด

image

๊ตฌ์™€ ๋™์„ ์„ ํƒํ•˜๊ณ  ์•„ํŒŒํŠธ ๊ฐ€๊ฒฉ์„ ์ž…๋ ฅํ•˜๋ฉด ๊ธฐ์กด์— ํ•™์Šต๋œ ๋จธ์‹ ๋Ÿฌ๋‹ ๋ชจ๋ธ์„ ํ†ตํ•ด์„œ ๊ฐ€๊ฒฉ์˜ˆ์ธก์„ ์‹œ์ž‘ํ•จ

image

์‹ค์ œ ๋ฐ์ดํ„ฐ์™€ ํฐ ์ฐจ์ด๊ฐ€ ์—†๋Š” ๋ชจ์Šต์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages