import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin, urlparse
import sqlite3
import threading
import queue
import tkinter as tk
from tkinter import ttk, messagebox
# データベース設定
DB_NAME = "gui_search_engine.db"
conn = sqlite3.connect(DB_NAME, check_same_thread=False)
cursor = conn.cursor()
# テーブル作成
cursor.execute("""
CREATE TABLE IF NOT EXISTS pages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
url TEXT UNIQUE,
title TEXT,
description TEXT,
content TEXT
)
""")
conn.commit()
# グローバル変数
visited = set()
visited_lock = threading.Lock()
task_queue = queue.Queue()
MAX_THREADS = 5
# ページをデータベースに保存
def save_page_to_db(url, title, description, content):
try:
cursor.execute("INSERT INTO pages (url, title, description, content) VALUES (?, ?, ?, ?)",
(url, title, description, content))
conn.commit()
except sqlite3.IntegrityError:
pass # URL重複時は無視
# URL正規化
def normalize_url(base, link):
return urljoin(base, link).split('#')[0]
# クローラー
def crawl(url, domain, status_label):
with visited_lock:
if url in visited:
return
visited.add(url)
try:
response = requests.get(url, timeout=10)
soup = BeautifulSoup(response.content, "html.parser")
# メタデータ収集
title = soup.title.string if soup.title else "No Title"
description_tag = soup.find("meta", attrs={"name": "description"})
description = description_tag["content"] if description_tag else "No Description"
content = soup.get_text()
# データベースに保存
save_page_to_db(url, title, description, content)
# ステータス更新
status_label.config(text=f"Crawling: {url}")
# 次のURLを収集
for link in soup.find_all('a', href=True):
full_url = normalize_url(url, link['href'])
if urlparse(full_url).netloc == domain:
task_queue.put(full_url)
except Exception as e:
print(f"Error crawling {url}: {e}")
# 並列クローリング
def start_crawling(start_url, domain, status_label):
visited.clear()
task_queue.put(start_url)
def worker():
while not task_queue.empty():
url = task_queue.get()
crawl(url, domain, status_label)
status_label.config(text="Crawling Complete")
threads = []
for _ in range(MAX_THREADS):
thread = threading.Thread(target=worker)
threads.append(thread)
thread.start()
for thread in threads:
thread.join()
# 検索機能
def search(query, results_box):
cursor.execute("SELECT url, title, description FROM pages WHERE content LIKE ?", (f"%{query}%",))
results = cursor.fetchall()
results_box.delete(*results_box.get_children()) # 結果をクリア
if not results:
messagebox.showinfo("検索結果", "該当する結果はありませんでした。")
else:
for url, title, description in results:
results_box.insert("", "end", values=(title, url, description[:100]))
# GUI設計
def create_gui():
root = tk.Tk()
root.title("クローラー型検索エンジン")
# フレーム構成
frame_crawl = ttk.Frame(root, padding=10)
frame_crawl.grid(row=0, column=0, sticky="ew")
frame_search = ttk.Frame(root, padding=10)
frame_search.grid(row=1, column=0, sticky="nsew")
# クローリングセクション
ttk.Label(frame_crawl, text="スタートURL:").grid(row=0, column=0, padx=5, pady=5, sticky="w")
url_entry = ttk.Entry(frame_crawl, width=50)
url_entry.grid(row=0, column=1, padx=5, pady=5, sticky="w")
status_label = ttk.Label(frame_crawl, text="Status: Ready", foreground="blue")
status_label.grid(row=1, column=0, columnspan=2, padx=5, pady=5, sticky="w")
def on_crawl():
start_url = url_entry.get().strip()
if not start_url:
messagebox.showerror("Error", "スタートURLを入力してください。")
return
# スキーム補完
if not start_url.startswith(("http://", "https://")):
start_url = "https://" + start_url
# ドメインを取得
domain = urlparse(start_url).netloc
status_label.config(text="Crawling in Progress...")
threading.Thread(target=start_crawling, args=(start_url, domain, status_label)).start()
ttk.Button(frame_crawl, text="クローリング開始", command=on_crawl).grid(row=0, column=2, padx=5, pady=5)
# 検索セクション
ttk.Label(frame_search, text="検索クエリ:").grid(row=0, column=0, padx=5, pady=5, sticky="w")
query_entry = ttk.Entry(frame_search, width=30)
query_entry.grid(row=0, column=1, padx=5, pady=5, sticky="w")
results_box = ttk.Treeview(frame_search, columns=("Title", "URL", "Description"), show="headings")
results_box.heading("Title", text="タイトル")
results_box.heading("URL", text="URL")
results_box.heading("Description", text="説明")
results_box.grid(row=1, column=0, columnspan=3, padx=5, pady=5, sticky="nsew")
def on_search():
query = query_entry.get().strip()
if not query:
messagebox.showerror("Error", "検索クエリを入力してください。")
return
search(query, results_box)
ttk.Button(frame_search, text="検索", command=on_search).grid(row=0, column=2, padx=5, pady=5)
# ウィンドウサイズ調整
root.columnconfigure(0, weight=1)
frame_search.rowconfigure(1, weight=1)
root.mainloop()
# GUI起動
if __name__ == "__main__":
create_gui()
# データベース接続を閉じる
conn.close()
カテゴリー: programming
Java メソッド
public class MyApp {
private static int triple(int num) { // 仮引数
return num * 3;
}
public static void main(String[] args) {
System.out.println(triple(10)); // 実引数
System.out.println(triple(4) * 3); // 実引数
}
}
PHP トレイト
<?php
trait LogTrait
{
public function log()
{
echo "Instance created" . PHP_EOL;
}
}
abstract class Score
{
use LogTrait;
private $subject;
protected $points;
public function __construct($subject, $points)
{
$this->subject = $subject;
$this->points = $points;
$this->log();
}
abstract protected function getResult();
public function getInfo()
{
return "{$this->subject}, {$this->points}, {$this->getResult()}";
}
}
class MathScore extends Score
{
public function __construct($points)
{
parent::__construct("Math", $points);
}
protected function getResult()
{
echo "MathScore method" . PHP_EOL;
return $this->points >= 50 ? "Pass" : "Fail";
}
}
class EnglishScore extends Score
{
public function __construct($points)
{
parent::__construct("English", $points);
}
protected function getResult()
{
echo "EnglishScore method" . PHP_EOL;
return $this->points >= 95 ? "Pass" : "Fail";
}
}
class User
{
use LogTrait;
private $name;
private $score;
public function __construct($name, $score)
{
$this->name = $name;
$this->score = $score;
$this->log();
}
public function getInfo()
{
return "{$this->name}, {$this->score->getInfo()}";
}
}
$user1 = new User("Taro", new MathScore(70));
$user2 = new User("Jiro", new EnglishScore(90));
echo $user1->getInfo() . PHP_EOL;
echo $user2->getInfo() . PHP_EOL;
PHP logメソッド
<?php
interface Loggable
{
public function log();
}
abstract class Score implements Loggable
{
private $subject;
protected $points;
public function __construct($subject, $points)
{
$this->subject = $subject;
$this->points = $points;
$this->log();
}
public function log()
{
echo "Instance created: {$this->subject}" . PHP_EOL;
}
abstract protected function getResult();
public function getInfo()
{
return "{$this->subject}, {$this->points}, {$this->getResult()}";
}
}
class MathScore extends Score
{
public function __construct($points)
{
parent::__construct("Math", $points);
}
protected function getResult()
{
echo "MathScore method" . PHP_EOL;
return $this->points >= 50 ? "Pass" : "Fail";
}
}
class EnglishScore extends Score
{
public function __construct($points)
{
parent::__construct("English", $points);
}
protected function getResult()
{
echo "EnglishScore method" . PHP_EOL;
return $this->points >= 95 ? "Pass" : "Fail";
}
}
class User implements Loggable
{
private $name;
private $score;
public function __construct($name, $score)
{
$this->name = $name;
$this->score = $score;
$this->log();
}
public function log()
{
echo "Instance created: {$this->name}" . PHP_EOL;
}
public function getInfo()
{
return "{$this->name}, {$this->score->getInfo()}";
}
}
$user1 = new User("Taro", new MathScore(70));
$user2 = new User("Jiro", new EnglishScore(90));
echo $user1->getInfo() . PHP_EOL;
echo $user2->getInfo() . PHP_EOL;
神と対話するAI
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>神と対話するAI</title>
<style>
/* 神秘的な背景とエフェクト */
body {
font-family: 'Georgia', serif;
background-color: #1a1a2e;
color: #d1d1e9;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
overflow: hidden;
}
.chat-container {
width: 100%;
max-width: 600px;
background-color: rgba(43, 43, 63, 0.9);
border-radius: 10px;
box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.6);
padding: 20px;
position: relative;
overflow: hidden;
}
.messages {
height: 300px;
overflow-y: auto;
margin-bottom: 10px;
padding-right: 10px;
}
.message {
margin: 10px 0;
line-height: 1.5;
}
.user-message {
text-align: right;
color: #00aaff;
}
.ai-message {
text-align: left;
color: #e6e6fa;
font-style: italic;
}
.typing-indicator {
font-size: 1.5em;
color: #e6e6fa;
}
.input-container {
display: flex;
}
input[type="text"] {
flex: 1;
padding: 10px;
border-radius: 5px;
border: 1px solid #555;
background-color: #444;
color: #e6e6fa;
margin-right: 10px;
}
button {
padding: 10px 20px;
border: none;
border-radius: 5px;
background-color: #5a5adb;
color: white;
cursor: pointer;
}
/* 背景アニメーション */
.background-animation {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: radial-gradient(circle, rgba(255,255,255,0.1), rgba(0,0,0,0) 70%);
animation: glow 5s infinite alternate;
pointer-events: none;
}
@keyframes glow {
from {
opacity: 0.4;
}
to {
opacity: 0.7;
}
}
</style>
</head>
<body>
<div class="chat-container">
<h2>神と対話するAI</h2>
<div class="messages" id="messages"></div>
<div class="input-container">
<input type="text" id="userInput" placeholder="質問を入力してください...">
<button onclick="sendMessage()">送信</button>
</div>
<div class="background-animation"></div>
</div>
<script>
const messagesContainer = document.getElementById("messages");
function addMessage(content, className) {
const message = document.createElement("div");
message.className = "message " + className;
message.innerHTML = content;
messagesContainer.appendChild(message);
messagesContainer.scrollTop = messagesContainer.scrollHeight;
}
function getAIResponse(userMessage) {
const responses = {
"目的": [
"あなたの目的はあなたの選択の中にあります。心を澄まし、その小さな声に耳を傾けなさい。",
"目的は定まっているものではなく、あなたが形作るものです。勇気を持って探し続けなさい。"
],
"未来": [
"未来は揺れ動く霧のようなもの…手の中にありながら捉えられぬもの。だが、あなたの意思がその霧を晴らすだろう。",
"未来は、あなたの内にある希望が灯し出すもの。信じる道を歩みなさい。"
],
"愛": [
"愛とは、無限に与えること。光のようにあなたを包み、他者を受け入れるものです。",
"愛とは、心の中の静けさと繋がり、他者の存在をただあるがままに受け入れること。"
],
"default": [
"その問いの答えは、あなた自身が見つけ出すもの。内なる声を信じなさい。",
"すべての答えは既にあなたの心の中にあります。耳を澄まし、その声に従いなさい。"
]
};
const keywords = Object.keys(responses);
for (let keyword of keywords) {
if (userMessage.includes(keyword)) {
const possibleResponses = responses[keyword];
return possibleResponses[Math.floor(Math.random() * possibleResponses.length)];
}
}
const defaultResponses = responses["default"];
return defaultResponses[Math.floor(Math.random() * defaultResponses.length)];
}
function sendMessage() {
const userInput = document.getElementById("userInput").value.trim();
if (userInput === "") return;
addMessage(userInput, "user-message");
document.getElementById("userInput").value = "";
const aiResponse = getAIResponse(userInput);
// タイピングエフェクトを表示
setTimeout(() => {
addMessage(`<span class="typing-indicator">...</span>`, "ai-message");
setTimeout(() => {
messagesContainer.lastChild.remove();
addMessage(aiResponse, "ai-message");
}, 2000); // タイピングエフェクト表示後の応答
}, 800); // 遅延で自然な応答
}
</script>
</body>
</html>
PHP クラスメソッド
<?php
class User
{
public $name;
public $score;
private static $count = 0;
public function __construct($name, $score)
{
$this->name = $name;
$this->score = $score;
User::$count++;
}
public static function getUserCount()
{
return User::$count;
}
}
$user1 = new User("Taro", 70);
$user2 = new User("Jiro", 90);
//User::$count++;
//echo User::$count . PHP_EOL;
echo User::getUserCount() . PHP_EOL;
PHP クラスプロパティ
<?php
class User
{
public $name;
public $score;
public static $count = 0;
public function __construct($name, $score)
{
$this->name = $name;
$this->score = $score;
User::$count++;
}
}
// $count = 0;
$user1 = new User("Taro", 70);
// $count++;
$user2 = new User("Jiro", 90);
// $count++;
// echo $count . PHP_EOL;
echo User::$count . PHP_EOL;
PHP setScoreメソッド
<?php
class User
{
public $name;
public $score;
public function __construct($name, $score)
{
$this->name = $name;
$this->score = $score;
}
public function getInfo()
{
return "{$this->name}, {$this->score}";
}
}
$user1 = new User("Taro", 70);
$user2 = new User("Jiro", 90);
$user1->score = 900;
echo $user1->getInfo() . PHP_EOL;
echo $user2->getInfo() . PHP_EOL;
PHP getInfoメソッド
<?php
class User
{
public $name;
public $score;
public function __construct($name, $score)
{
$this->name = $name;
$this->score = $score;
}
public function getInfo()
{
return "{$this->name}, {$this->score}";
}
}
$user1 = new User("Taro", 70);
$user2 = new User("Jiro", 90);
echo $user1->getInfo() . PHP_EOL;
echo $user2->getInfo() . PHP_EOL;
NekoNekodouga.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ねこねこ動画 - 動画共有サイト</title>
<style>
/* ベーススタイル */
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f4f4f4;
}
header {
background-color: #333;
color: white;
padding: 10px;
text-align: center;
position: fixed;
width: 100%;
top: 0;
z-index: 100;
}
header h1 {
margin: 0;
font-size: 24px;
}
nav ul {
list-style-type: none;
padding: 0;
margin: 10px 0 0 0;
text-align: center;
}
nav ul li {
display: inline-block;
margin-right: 15px;
}
nav ul li a {
color: white;
text-decoration: none;
font-size: 16px;
}
#searchBar {
margin-top: 10px;
padding: 5px;
width: 300px;
max-width: 80%;
border: none;
border-radius: 4px;
}
.container {
margin-top: 100px;
padding: 20px;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
}
.upload-container, .video-info, .description, .comments, .related-videos, .gallery {
background-color: white;
padding: 20px;
margin-top: 20px;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.upload-container h2, .video-info h2, .description h2, .comments h2, .related-videos h2, .gallery h2 {
margin-top: 0;
}
.upload-container form input[type="file"],
.upload-container form input[type="text"],
.upload-container form textarea,
.upload-container form select {
width: 100%;
padding: 10px;
margin-bottom: 10px;
border-radius: 4px;
border: 1px solid #ccc;
}
.upload-container form button {
padding: 10px 20px;
background-color: #333;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.upload-container form button:hover {
background-color: #555;
}
.video-container {
position: relative;
text-align: center;
width: 100%;
max-width: 800px;
margin: 0 auto;
}
.video-container video {
width: 100%;
height: auto;
border-radius: 10px;
}
.comment-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 10;
}
.comment {
position: absolute;
white-space: nowrap;
font-size: 20px;
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
animation: moveComment linear forwards;
}
@keyframes moveComment {
from {
left: 100%;
}
to {
left: -100%;
}
}
.description p, .comments p, .gallery p {
margin: 10px 0;
}
.comments form textarea {
width: 100%;
padding: 10px;
border-radius: 4px;
border: 1px solid #ccc;
resize: vertical;
margin-bottom: 10px;
}
.comments form select {
width: 100%;
padding: 10px;
margin-bottom: 10px;
border-radius: 4px;
}
.comments form button {
padding: 10px 20px;
background-color: #333;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.comments form button:hover {
background-color: #555;
}
.comment-list .comment {
background-color: #f9f9f9;
padding: 10px;
margin-bottom: 10px;
border-radius: 5px;
}
.like-button, .dislike-button {
background-color: #333;
color: white;
border: none;
padding: 5px 10px;
margin: 5px;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.like-button:hover, .dislike-button:hover {
background-color: #555;
}
footer {
background-color: #333;
color: white;
text-align: center;
padding: 20px;
margin-top: 40px;
}
footer p {
margin: 0;
}
@media (max-width: 768px) {
nav ul li {
display: block;
margin: 10px 0;
}
#searchBar {
width: 80%;
}
.video-container {
max-width: 100%;
}
}
</style>
</head>
<body>
<!-- ヘッダー開始 -->
<header>
<h1>ねこねこ動画</h1>
<nav>
<ul>
<li><a href="#">ホーム</a></li>
<li><a href="#">人気動画</a></li>
<li><a href="#">カテゴリ</a></li>
<li><a href="#">ログイン</a></li>
</ul>
</nav>
<input type="text" id="searchBar" placeholder="動画を検索..." />
</header>
<!-- ヘッダー終了 -->
<div class="container">
<!-- 動画アップロードエリア -->
<div class="upload-container">
<h2>動画をアップロード</h2>
<form id="uploadForm" enctype="multipart/form-data">
<input type="file" id="videoFile" name="video" accept="video/*" required><br>
<input type="text" id="videoTitle" name="title" placeholder="動画タイトル" required><br>
<textarea id="videoDescription" name="description" rows="4" placeholder="動画の説明" required></textarea><br>
<button type="submit">アップロード</button>
</form>
<div id="uploadStatus"></div>
</div>
<!-- プレビューエリア -->
<div class="video-container" id="previewContainer" style="display: none;">
<h2 id="previewTitle">プレビュー: 動画タイトル</h2>
<video controls id="videoPreview"></video>
<div class="comment-overlay" id="commentOverlay"></div>
<p id="previewDescription">プレビュー: 動画の説明</p>
</div>
<!-- コメント投稿エリア -->
<div class="comments">
<h2>コメントを投稿</h2>
<form id="commentForm">
<textarea id="commentText" rows="4" cols="50" placeholder="コメントを追加..." required></textarea><br>
<label for="commentTime">表示タイミング (秒):</label>
<input type="number" id="commentTime" placeholder="0" min="0" required><br>
<label for="commentColor">コメントの色:</label>
<select id="commentColor">
<option value="white">白</option>
<option value="red">赤</option>
<option value="blue">青</option>
<option value="green">緑</option>
<option value="yellow">黄色</option>
</select><br>
<label for="commentFontSize">フォントサイズ:</label>
<select id="commentFontSize">
<option value="20px">小</option>
<option value="24px">中</option>
<option value="28px">大</option>
</select><br>
<label for="commentSpeed">表示速度 (秒):</label>
<input type="number" id="commentSpeed" placeholder="10" min="5" max="20" required><br>
<button type="submit">投稿</button>
</form>
<div id="commentList" class="comment-list"></div>
</div>
<!-- 評価機能 -->
<div class="rating">
<button class="like-button" id="likeButton">👍 いいね</button>
<span id="likeCount">0</span>
<button class="dislike-button" id="dislikeButton">👎 バッド</button>
<span id="dislikeCount">0</span>
</div>
</div>
<!-- フッター開始 -->
<footer>
<p>© 2023 ねこねこ動画. All Rights Reserved.</p>
</footer>
<!-- フッター終了 -->
<script>
let comments = [];
// 動画のアップロードとプレビュー処理
document.getElementById("uploadForm").addEventListener("submit", function(event) {
event.preventDefault();
const fileInput = document.getElementById("videoFile");
const file = fileInput.files[0];
const title = document.getElementById("videoTitle").value;
const description = document.getElementById("videoDescription").value;
if (!file) {
alert("動画ファイルを選択してください。");
return;
}
const reader = new FileReader();
reader.onload = function(e) {
const videoData = e.target.result;
document.getElementById("previewContainer").style.display = "block";
document.getElementById("videoPreview").src = videoData;
document.getElementById("previewTitle").textContent = "プレビュー: " + title;
document.getElementById("previewDescription").textContent = "プレビュー: " + description;
};
reader.readAsDataURL(file);
});
// コメント投稿処理
document.getElementById("commentForm").addEventListener("submit", function(event) {
event.preventDefault();
const commentText = document.getElementById("commentText").value;
const commentTime = parseInt(document.getElementById("commentTime").value);
const commentColor = document.getElementById("commentColor").value;
const commentFontSize = document.getElementById("commentFontSize").value;
const commentSpeed = parseInt(document.getElementById("commentSpeed").value);
if (commentText && commentTime >= 0) {
const comment = {
text: commentText,
time: commentTime,
color: commentColor,
fontSize: commentFontSize,
speed: commentSpeed
};
comments.push(comment);
displayCommentInList(comment);
document.getElementById("commentForm").reset();
}
});
// コメントリストに表示
function displayCommentInList(comment) {
const commentList = document.getElementById("commentList");
const commentDiv = document.createElement("div");
commentDiv.classList.add("comment");
commentDiv.textContent = `タイミング: ${comment.time}秒 - ${comment.text}`;
commentList.appendChild(commentDiv);
}
// 動画の再生に合わせてコメントを表示
const videoElement = document.getElementById("videoPreview");
videoElement.addEventListener("timeupdate", function() {
const currentTime = Math.floor(videoElement.currentTime);
comments.forEach(comment => {
if (comment.time === currentTime) {
displayCommentOnVideo(comment);
}
});
});
// 動画上にコメントを流す
function displayCommentOnVideo(comment) {
const overlay = document.getElementById("commentOverlay");
const commentElement = document.createElement("div");
commentElement.classList.add("comment");
commentElement.textContent = comment.text;
commentElement.style.color = comment.color;
commentElement.style.fontSize = comment.fontSize;
commentElement.style.animationDuration = `${comment.speed}s`;
commentElement.style.top = Math.random() * 80 + "%"; // ランダムな位置
overlay.appendChild(commentElement);
// 一定時間後にコメントを削除
setTimeout(() => {
commentElement.remove();
}, comment.speed * 1000);
}
// いいね・バッド機能
document.getElementById("likeButton").addEventListener("click", function() {
let likeCount = parseInt(document.getElementById("likeCount").textContent);
likeCount++;
document.getElementById("likeCount").textContent = likeCount;
});
document.getElementById("dislikeButton").addEventListener("click", function() {
let dislikeCount = parseInt(document.getElementById("dislikeCount").textContent);
dislikeCount++;
document.getElementById("dislikeCount").textContent = dislikeCount;
});
</script>
</body>
</html>