Malicious-URL-Detection-ML / OldCode / Content based feature detecting Malicious URL DS.py
Content based feature detecting Malicious URL DS.py
Raw
import pandas as pd
import numpy as np
import re
import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin, urlparse
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import classification_report

def is_valid_url(url):
    """ Check if the URL contains a scheme, if not, it is likely a relative URL. """
    parsed_url = urlparse(url)
    return bool(parsed_url.scheme)

def get_links_from_webpage(url):
    """ Fetch and extract absolute links from the given webpage. """
    try:
        response = requests.get(url)
        response.raise_for_status()
        soup = BeautifulSoup(response.text, 'html.parser')
        return [urljoin(url, tag['href']) for tag in soup.find_all('a', href=True) if is_valid_url(urljoin(url, tag['href']))]
    except requests.RequestException as e:
        print(f"Error fetching webpage: {e}")
        return []

def get_html_content(url):
    """ Fetch the HTML content from the given URL if it's valid. """
    if not is_valid_url(url):
        print(f"Invalid URL detected: {url}")
        return ""
    try:
        response = requests.get(url)
        response.raise_for_status()
        return response.text
    except requests.RequestException as e:
        print(f"Error fetching webpage content: {e}")
        return ""

def extract_content_features(html_content):
    soup = BeautifulSoup(html_content, 'html.parser')
    features = {
        'presence_iframe': int(bool(soup.find('iframe'))),
        'count_eval': sum(1 for script in soup.find_all('script') if 'eval(' in script.text),
        'count_escape': sum(1 for script in soup.find_all('script') if 'escape(' in script.text),
        'count_unescape': sum(1 for script in soup.find_all('script') if 'unescape(' in script.text),
        'count_find': sum(1 for script in soup.find_all('script') if 'find(' in script.text),
        'count_exec': sum(1 for script in soup.find_all('script') if 'exec(' in script.text),
        'count_search': sum(1 for script in soup.find_all('script') if 'search(' in script.text),
        'count_link': sum(1 for script in soup.find_all('script') if 'link(' in script.text),
        'count_all_functions': sum(1 for script in soup.find_all('script') if any(func in script.text for func in ['eval(', 'escape(', 'unescape(', 'find(', 'exec(', 'search(', 'link('])),
        'presence_windows_open': int(bool(sum(1 for script in soup.find_all('script') if 'window.open(' in script.text))),
        'lines_count': sum(len(script.text.splitlines()) for script in soup.find_all('script'))
    }
    return list(features.values())

def tokenizer(url):
    tokens = re.split('[/:?=&]', url)
    tokens = filter(lambda token: token.strip() != '', tokens)
    enhanced_tokens = []
    for token in tokens:
        subtokens = re.split('[.-@]', token)
        enhanced_tokens.extend([sub for sub in subtokens if sub not in ['com', 'www', 'http', 'https']])
    return enhanced_tokens

def vectorize_data(data_frame, vectorizer, content_features, fit=False):
    if fit:
        X = vectorizer.fit_transform(data_frame['URLs'])
    else:
        X = vectorizer.transform(data_frame['URLs'])
    X = np.hstack([X.toarray(), content_features])
    return X

def train_model(data_frame):
    vectorizer = TfidfVectorizer(tokenizer=tokenizer, lowercase=False)
    content_features = [extract_content_features(get_html_content(url)) for url in data_frame['URLs']]
    X = vectorize_data(data_frame, vectorizer, content_features, fit=True)
    model = MultinomialNB()
    model.fit(X, data_frame['Class'])
    return model, vectorizer

def predict(model, vectorizer, urls):
    content_features = [extract_content_features(get_html_content(url)) for url in urls]
    X = vectorize_data(pd.DataFrame(urls, columns=['URLs']), vectorizer, content_features)
    return model.predict(X)

url_df = pd.read_csv('Dataset/Malicious URLs.csv')
train_df, test_df = train_test_split(url_df, test_size=0.2, random_state=42)
model, vectorizer = train_model(train_df)
test_urls = get_links_from_webpage(input("Enter the URL to analyze: "))
predictions = predict(model, vectorizer, test_urls)

result_df = pd.DataFrame({
    'URL': test_urls,
    'Prediction': ['Malicious' if pred == 1 else 'Benign' for pred in predictions]
})

print(result_df)