데이터 분석

악성 사이트 탐지 모델링

lhg010524 2024. 11. 15. 13:12

 

이런 식으로 html_code와 악성 사이트 의심 여부가 있다고 하자. Beautifulsoup를 사용해 html_code로부터 악성 사이트 여부를 알아내는 모델을 만들어 보자.

 

1. html 에서 <script>...</script> 길이 계산

우리가 해야 하는 사항은 다음과 같다.

- BeautifulSoup으로 html소스를 python 객체로 변환

- 이걸 함수로 구현하기

- float으로 return 받기

import pandas as pd
import numpy as np
from bs4 import BeautifulSoup
from urllib.parse import urlparse

# 
def html_script_characters(soup):
    # soup > script
    html_len = str(soup.script) # soup 객체에서 <script> 태그를 문자열로 변환
    return float(len(html_len.replace(' ', ''))) # 공백 제거 후 문자열 길이 반환

script_len = []  # 먼저 script 길이 리스트 생성 

for index, row in df.iterrows():     # iterrows 로 df의 인덱스와 열 내용을 series 형태로 반환
    soup = BeautifulSoup(row.html_code, 'html.parser')  # row의 html_code를 'html.parser' 형태로 변환
    # soup 객체 생성
    script_len.append(html_script_characters(soup)) 
    # script_len 리스트에 하나씩 길이 추가

df['html_script_characters'] = script_len # 열 추가, 피처 생성

이렇게 데이터 정리.

2. html 에서 공백 수 계산하기

def html_num_whitespace(soup):
    try:
    	# soup > body > text 로 들어가서 안에 공백이 얼마나 있는지 확인  
        NullCount = soup.body.text.count(' ')
        return float(NullCount)
    except:
        return 0.0
        
 
num_whitespace = []  # 리스트 생성 

for index, row in df.iterrows():
    soup = BeautifulSoup(row.html_code,'html.parser')
    num_whitespace.append(html_num_whitespace(soup))

df['html_num_whitespace'] = num_whitespace

 

3. html 에서 body 길이 계산

def html_num_characters(soup):
    try:
        #soup > body > text
        bodyLen = len(str(soup.body.text))
        return float(bodyLen)
    except:
        return 0.0
        
        
html_body = []


for index, row in df.iterrows():
    soup = BeautifulSoup(row.html_code, 'html.parser')
    html_body.append(html_num_characters(soup))

df['html_body_len'] = html_body

대충 이렇게 나온다.

 

4. script 에서 scr, href 속성을 가진 태그 수

def html_link_in_script(soup):
    numOfLinks = len(soup.findAll('script', {"src": True}))
    numOfLinks += len(soup.findAll('script', {"href": True}))
    return float(numOfLinks)

html_script_link_num = []

for index, row in df.iterrows():
    soup = BeautifulSoup(row.html_code, 'html.parser')
    html_script_link_num.append(html_link_in_script(soup))

df['html_script_link_num'] = html_script_link_num

 

 

이렇게 전처리를 계속 해 준다.

 

5. Confusion Matrix 만들기

from sklearn.metrics import classification_report as creport
from sklearn.metrics import confusion_matrix, accuracy_score, precision_score, recall_score

def plot_confusion_matrix(ax, matrix, labels = ['malicious','benign'], title='Confusion matrix', fontsize=9):
    ax.set_xticks([x for x in range(len(labels))])
    ax.set_yticks([y for y in range(len(labels))])

    # Place labels on minor ticks
    ax.set_xticks([x + 0.5 for x in range(len(labels))], minor=True)
    ax.set_xticklabels(labels, rotation='90', fontsize=fontsize, minor=True)
    ax.set_yticks([y + 0.5 for y in range(len(labels))], minor=True)
    ax.set_yticklabels(labels[::-1], fontsize=fontsize, minor=True)

    # Hide major tick labels
    ax.tick_params(which='major', labelbottom='off', labelleft='off')

    # Finally, hide minor tick marks
    ax.tick_params(which='minor', width=0)

    # Plot heat map
    proportions = [1. * row / sum(row) for row in matrix]
    ax.pcolor(np.array(proportions[::-1]), cmap=plt.cm.Blues)

    # Plot counts as text
    for row in range(len(matrix)):
        for col in range(len(matrix[row])):
            confusion = matrix[::-1][row][col]
            if confusion != 0:
                ax.text(col + 0.5, row + 0.5, int(confusion),
                        fontsize=fontsize,
                        horizontalalignment='center',
                        verticalalignment='center')

    # Add finishing touches
    ax.grid(True, linestyle=':')
    ax.set_title(title, fontsize=fontsize)
    ax.set_xlabel('prediction', fontsize=fontsize)
    ax.set_ylabel('actual', fontsize=fontsize)

    plt.show()

 

6. Decision Tree 모델링

# 1. import 
from sklearn.tree import DecisionTreeClassifier
# 2. 선언
dtc = DecisionTreeClassifier()
# 3. fit()
dtc.fit(train_x,train_y)
# 4. predict()
dtc_pred = dtc.predict(val_x)

# train 및 val 데이터 정확도 확인 : score()
dtc.score(train_x, train_y), dtc.score(val_x, val_y)

#Confusion Matrix 확인
confusion = confusion_matrix(val_y, dtc_pred)
fig, ax = plt.subplots(figsize=(10,3))
plot_confusion_matrix(ax, confusion, fontsize=30)

plt.figure(figsize=(20,12))
plt.barh(y=Train_Data.columns[:-1],
        width = dtc.feature_importances_)
plt.show()

6. 앙상블(Ensemble) - Random Forest

# 1. import
from sklearn.ensemble import RandomForestClassifier
# 2.선언
rfc = RandomForestClassifier()
# 3. fit()
rfc.fit(train_x,train_y)
# 4. predict()
rfc_pred = rfc.predict(val_x)

# train 및 val 데이터 정확도 확인 :score()
rfc.score(train_x,train_y), rfc.score(val_x, val_y)

# Confusion Matrix 확인
confusion = confusion_matrix(val_y, rfc_pred)
fig, ax = plt.subplots(figsize=(10,3))
plot_confusion_matrix(ax, confusion, fontsize=30)

# feature_importances_ 활용 Feature별 가중치 확인
plt.figure(figsize=(20,12))
plt.barh(y=Train_Data.columns[:-1],
        width = rfc.feature_importances_)

rfc.feature_importances_)
plt.show()

7. AdaBoost 모델

: 약한 학습기(weak learner)의 오류 데이터에 가중치를 부여하면서 부스팅을 수행하며 학습

# 1. import
from sklearn.ensemble import AdaBoostClassifier

# 2.선언
abc = AdaBoostClassifier()

# 3. fit()
abc.fit(train_x,train_y)

# 4. predict()
abc_pred = abc.predict(val_x)

# train 및 val 데이터 정확도 확인 : score()
abc.score(train_x, train_y), abc.score(val_x, val_y)

#Confusion Matrix 확인
confusion = confusion_matrix(val_y, abc_pred)
fig, ax = plt.subplots(figsize=(10,3))
plot_confusion_matrix(ax, confusion, fontsize=30)

# feature_importances_ 활용 Feature별 가중치 확인
plt.figure(figsize=(20,12))
plt.barh(y=Train_Data.columns[:-1],
        width = abc.feature_importances_)

plt.show()

8. Gradient Boost 모델

: 이전 예측기가 만든 잔여오차에 새로운 예측기를 학습

# 1. import
from sklearn.ensemble import GradientBoostingClassifier

# 2.선언
gbc = GradientBoostingClassifier()

# 3. fit()
gbc.fit(train_x,train_y)

# 4. predict()
gbc_pred = gbc.predict(val_x)

# train 및 val 데이터 정확도 확인 : score()
gbc.score(train_x, train_y), gbc.score(val_x,val_y)

#Confusion Matrix 확인
confusion = confusion_matrix(val_y, gbc_pred)
fig, ax = plt.subplots(figsize=(10,3))
plot_confusion_matrix(ax, confusion, fontsize=30)

# feature_importances_ 활용 Feature별 가중치 확인
plt.figure(figsize=(20,12))
plt.barh(y=Train_Data.columns[:-1],
        width = gbc.feature_importances_)
plt.show()

9. 최적화

RandomForest GridSearchCV

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV

param_grid = [ {'n_estimators':[30,40,50,60,100], 'max_depth':[30,40,50,60,100]}]

rfc = RandomForestClassifier()

rfc_grid = GridSearchCV(rfc, 
                        param_grid, # 
                        cv=2, 
                        scoring='accuracy', # Classification일때  'accuracy','f1' ...
                                            # Regression 일때 'neg_mean_squared_error','r2'...
                        n_jobs=-1,          
                        verbose=1           # Log 출력 Level 조정
                       )
                       
rfc_grid.fit(train_x, train_y)

rfc_model = rfc_grid.best_estimator_

print('최적의 파라미터 값 : ', rfc_grid.best_params_)
print('최고의 점수 : ', rfc_grid.best_score_)

rfc_grid_pred = rfc_model.predict(val_x)

# train 및 val 데이터 정확도
rfc_model.score(train_x, train_y), rfc_model.score(val_x, val_y)

'데이터 분석' 카테고리의 다른 글

가입 고객 유형 예측 모델링  (0) 2024.11.15
네비게이션 도착시간 예측 모델링  (0) 2024.11.15
데이터 전처리 python 코드  (0) 2024.11.14