はてなキーワード: btnとは
昨日一番肝心なファイルなのにURLとみなされる部分が多いことの関係で投稿できなかったのでそれを小分けにして書く。
小分けというか例のスパムの影響でNGワードに引っかかっていたようなのでそこだけ書き換えた。
suuportと書いていある部分は元のコードでは当然uが一つ少ないので利用するときはそうすること。
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager # ← 追加
from selenium.webdriver.common.by import By
from selenium.webdriver.suupport.ui import WebDriverWait
from selenium.webdriver.suupport import expected_conditions as EC
import time, json
from selenium.common.exceptions import TimeoutException
class HatenaClient:
def __init__(self, username, password):
self.username = username
self.password = password
self.driver = None
def start_browser(self):
options = Options()
options.set_capability("goog:loggingPrefs", {"browser": "ALL"})
options.add_argument("--headless=new") # 開発中は消してよい
options.add_argument("--disable-gpu")
# ✅ webdriver-manager を使って ChromeDriver を自動取得・設定
service = Service(ChromeDriverManager().install())
self.driver = webdriver.Chrome(service=service, options=options)
def login(self):
self.driver.get("https://b.hatena.ne.jp/my")
print(self.driver.current_url)
self.driver.get("https://www.hatena.ne.jp/login")
time.sleep(2)
self.driver.find_element(By.NAME, "username").send_keys(self.username)
self.driver.find_element(By.NAME, "password").send_keys(self.password)
self.driver.find_element(By.XPATH, "//button[contains(text(), 'ログイン')]").click()
WebDriverWait(self.driver, 10).until(lambda d: "my" in d.current_url or "login" not in d.current_url)
if "passkeys" in self.driver.current_url:
self.driver.get("https://b.hatena.ne.jp/my")
print(self.driver.current_url)
print(self.driver.title)
return "dorawii" in self.driver.current_url
def add_bookmark(self, target_url):
self.driver.get(f"https://b.hatena.ne.jp/{self.username}/add.confirm?url={target_url}")
time.sleep(2)
try:
# コメントがあれば入力
comment_box = self.driver.find_element(By.CSS_SELECTOR, "textarea.bookmarkadd-comment-form")
comment_box.clear()
comment_box.send_keys("わしが書いた")
# 登録ボタンを押す
save_button = self.driver.find_element(By.CSS_SELECTOR, "input.bookmarkadd-submit-btn")
save_button.click()
time.sleep(2)
return True
except Exception as e:
print(f"Bookmark failed: {e}")
return False
def quit(self):
self.driver.quit()
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
https://anond.hatelabo.jp/20250822131958#
-----BEGIN PGP SIGNATURE-----
iHUEARYKAB0WIQTEe8eLwpVRSViDKR5wMdsubs4+SAUCaKfv9AAKCRBwMdsubs4+
SE26AQCkpJE4RdUbFIDIJjOunjFYRQ34zdS1cqV7IX277S7IPAEAshVE/rD8Ggcr
9UKo5yOY6GNrHGYJJtYTYkn3cySu6AA=
=E4vq
-----END PGP SIGNATURE-----
ようやく(ほぼ)すべてが自動化された。
あとはローカルサーバーの起動をスタートアップに設定する(方法をAIに聞いて指示に従う)だけの消化試合。
署名時要求してくるパスワードを自動入力するahkファイルはドキュメントのAutoHotkey配下に置いた。
バッチファイル(make.sign.bat)はデスクトップに置いた。
#Persistent #SingleInstance ignore SetTitleMatchMode, 2 WinWaitActive, pinentry SendInput お前のパスワード Sleep 100 SendInput {Enter} ExitApp
// run-batch-server.js const http = require('http'); const { exec } = require('child_process'); const server = http.createServer((req, res) => { if (req.url === '/ping') { res.writeHead(200); res.end('pong'); } else if (req.url === '/run-batch') { exec('C:\\Users\\you\\Desktop\\makesign.bat', (err) => { res.writeHead(200); res.end(err ? 'Error' : 'OK'); }) ; } else { res.writeHead(404); res.end('Not found'); } }); server.listen(12345, () => { console.log('Batch server running at http://localhost:12345/'); });
@echo off setlocal enabledelayedexpansion :: ミリ秒単位のUTC時刻を取得 for /f %%a in ('powershell -nologo -command "[int64]::Parse((Get-Date).ToUniversalTime().ToString('yyyyMMddHHmmssfff'))"') do set timestamp=%%a :: 署名するファイル名 set infile=%TEMP%\pgp_input.txt set outfile=%TEMP%\pgp_output.asc :: 以前の出力があれば削除 if exist "%outfile%" del "%outfile%" :: タイムスタンプを原文として保存 echo %timestamp% > "%infile%" :signloop :: AutoHotkeyでパスフレーズ入力(gpgがパスワード要求するダイアログが出た場合に備える) start "" /b "C:\Users\infini\Documents\AutoHotkey\autopass.ahk" :: PGPクリア署名を作成 gpg --yes --clearsign --output "%outfile%" "%infile%" :: 署名が成功していればループを抜ける if exist "%outfile%" ( echo [INFO] 署名成功 goto postprocess ) else ( echo [WARN] 署名失敗、再試行します… timeout /t 1 > nul goto signloop ) :postprocess :: PowerShellで余計な改行なしに |< をつけてクリップボードにコピー powershell -nologo -command ^ "$header = '>|'; $footer = '|<'; $body = Get-Content '%outfile%' -Raw; Set-Clipboard -Value ($header + \"`r`n\" + $body + $footer)" echo Done. signed.asc created and clipboard updated (no extra blank line). endlocal exit /b
// ==UserScript== // @name PGP署名自動付加スクリプト(GM_xmlhttpRequest版) // @namespace http://tampermonkey.net/ // @version 1.0 // @description 投稿前にPGP署名を付けてから送信(fetch未使用) // @match https://anond.hatelabo.jp/dorawii_31/edit* // @grant GM_xmlhttpRequest // @grant GM_setClipboard // @grant GM_notification // / @connect localhost // ==/UserScript== (function () { 'use strict'; const submitId = 'submit-button'; const textareaId = 'text-body'; const localServer = 'http://localhost:12345/run-batch'; const pgpSignatureRegex = /-----BEGIN PGP SIGNED MESSAGE-----[\s\S]+?-----BEGIN PGP SIGNATURE-----[\s\S]+?-----END PGP SIGNATURE-----/; const httpRequest = (url) => { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'GET', url: url, onload: function (response) { resolve(response.responseText); }, onerror: function (error) { reject(error); } }); }); }; const interceptClick = () => { const btn = document.getElementById(submitId); if (!btn || btn.dataset.pgpIntercepted === 'true') return; btn.dataset.pgpIntercepted = 'true'; btn.addEventListener('click', async function (e) { const textarea = document.getElementById(textareaId); if (!textarea) return; const content = textarea.value; if (pgpSignatureRegex.test(content)) { console.log('[PGPスクリプト] 署名が検出されたためそのまま送信します'); return; } e.preventDefault(); e.stopImmediatePropagation(); console.log('[PGPスクリプト] 署名が見つからないため処理を停止し、署名を取得します'); try { await httpRequest(localServer); // バッチ実行 const signatureText = await navigator.clipboard.readText(); if (!signatureText.includes('BEGIN PGP SIGNED MESSAGE')) { alert('PGP署名がクリップボードに見つかりませんでした。'); return; } const newText = content.replace(/\s*$/, '') + '\n' + signatureText + '\n'; textarea.value = newText; console.log('[PGPスクリプト] 署名を貼り付けました。送信を再開します。'); btn.click(); // イベント再発火 } catch (err) { alert('PGP署名の取得または貼り付けに失敗しました。\n' + err); } }, true); }; window.addEventListener('load', () => { setTimeout(interceptClick, 1000); }); })();
プロミスメソッドとか全然まだ理解してなくてそのなかに関数代入したその関数にオブジェクトのプロパティにresponseを?いやまあそのあたりのコードが示すデータの流れが全然理解できないような人間でもここまでできちゃった。
AIすごいなと思うよ。そして思うのは今後重要になってくるのは文法とか自体に詳しいことじゃなくて、そのプログラムの処理内容を指示できるシステムエンジニア的な言語化能力のほうじゃないかなと思った。
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 20250609111559680 -----BEGIN PGP SIGNATURE----- iHUEARYKAB0WIQTEe8eLwpVRSViDKR5wMdsubs4+SAUCaEbCbwAKCRBwMdsubs4+ SLueAPwOv7PBk4voAe5qlcCEvs/PJhmKc5QAb/1R43JMQFuDZgD/UTPEKsL/PhK9 jFGv2HDXK1dVjLNwvosgX9uYJh5xxwY= =qiOE -----END PGP SIGNATURE-----
目が痛かった
textarea,
.message {
background-color: #7f8283 !important;
}
#body,
body,
.box-curve {
color: #c5c8c6 !important;
background-color: #333 !important;
}
.refererlist ul {
color: #c5c8c6 !important;
background-color: #153555 !important;
}
div.body {
border: #15497f 1px solid !important;
}
span.sanchor {
color: #15497f !important;
}
div.btn-standard,
background-color: #15497f !important;
}
#intro p {
color: #c5c8c6 !important;
background-color: #404142 !important;
}
td.gmenu {
background-color: #384d88 !important;
}
span.label {
color: #c5c8c6 !important;
}
a.keyword,
a.okeyword {
color: #c5c8c6 !important;
background-color: #333 !important;
border-bottom: none !important;
}
a {
color: #2ea6c0 !important;
}
td.username,
h2 {
background-color: #404142 !important;
}
システムハンガリアンはIDEの発達や型推論で廃れた。変数にポインタを当てるだけで型がわかる。
アプリケーションハンガリアンは、自分もメンバ変数はbtn~にしたり~Buttonにしたり迷ってたりしてたが、プロパティとして公開するときはハンガリアンにするわけにはいかないので、結局ハンガリアンをやめた。プロパティとメンバ変数が機械的に対応が取れてたほうが便利。"_プロパティ名"とかにしてしまう。
型よりもその変数の意味のほうが重要だという考え方がハンガリアンが廃れた大もとの原因だろう。最近のIDEは中間一致で補完するのが主流なので、Buttonと打てばボタン一覧が出てくる。
Rails3 と jQuery で、真面目にオシャレなエロサイトをつくってみました。 - h300
http://d.hatena.ne.jp/inouetakuya/20120331/1333192327
に触発されて、オシャレエロサイトを作ってみました。
オシャレエロサイトを作ろうと思ったのはいいのですが、デザインは苦手なので途方に暮れていました。
h300の方はペパボのソフトウェアエンジニアらしいのですが、こっちはただの素人プログラマー。
そこで何か裏ワザみたいなものはないかとググっていると、Twitter Bootstrapという文字が目にとまりました。
Bootstrapの名前は知っていましたが、深い内容までは知りませんでした。
ですが、紹介記事を読んでみると自分の理想に近かったので早速使ってみることにしました。
Twitter Bootstrapはある程度有名だと思うんですが知らない方のために説明すると、
CSSフレームワークの一つで、ウェブデザインの作成を手助けしてくれるものです。
色々なCSSフレームワークを見ましたがTwitter Bootstrapが一番完成度が高いと感じました。
ウィキを見ると最初のリリースが2011年8月なので比較的最近のものですね。
普段、みなさんがウェブサイトを作る時、HTML + CSSで作られるかなと思うんですよね。
この時、CSSが事前に用意されているとすごく楽じゃないですか?
CSSフレームワークはCSSの大部分を前もって用意してくれているんですよ。(フレームワークによりますが)
ですので基本的にCSSに合わせてHTMLを記述するだけでウェブサイトが出来てしまいます。
CSSに合わせてHTMLを記述するとはどういうことでしょうか?
この文章は薄い青色でハイライトされていますよね? Bootstrapで似たようなことをする場合 <div class="well"> ハイライトしたい文章 </div> という感じになります。
classにwellと指定しているだけですね。
なぜそうするだけで文章がハイライトされるかというと、
divのclassにwellが付いていたら、いい感じでハイライトしてねっていう指示が
Twitter BootstrapのCSSに書いてあるからです。
BootstrapのCSSには、divのclassにalert alert-errorっていうのがあったら警告文だしてねとか、
button class="btn"ってあったらボタン表示させてねとか色んなことが最初から書いてくれています。
もちろん見栄えがよくなるように記述されていますので、classを指定するだけでモダンなデザインになるわけですよ。
CSSに合わせてHTMLを記述するだけでウェブサイトが出来るというのはこういうことです。
でも、最近のウェブサイトは HTML + CSS + JQueryという場合も多いですよね。
安心してください。Twitter Bootstrapの場合はJQueryの基本的な部分も用意してくれています。
ですのでドロップダウンメニューやタブ、スライドショーなどの実装も簡単にできます。
それに加えてBootstrapはよく使うアイコン数百種類まで用意してくれています。
至れり尽くせりですよ。
神様ですね。
CSSが固定化されていると、HTMLも自動的に固定化されます。
CSSに合わせて記述するので当たり前といえば当たり前ですね。
CSSの記述は一定、HTMLもある程度一定なので、メンテナンスが格段にやりやすくなります。
個人プログラマーの方だと、サイトごとにHTMLもCSSもグチャグチャという方も多いのではないでしょうか?
フレームワークを使えばそういうこともなくなるということです。
Twitter Bootstrapの凄さはそれだけではありません。
現在、ユーザーがどんなデバイスでウェブサイトにアクセスしてくるか分かりません。
PC、スマートフォン、iPad、TV、3dsなど全てのデバイスに合わせてデザインを作るのは時間がかかりすぎます。
でもTwitter Bootstrapならbootstrap-responsive.cssというCSSを選ぶだけで、
デバイスの横幅に合わせてデザインが変わるレスポンシブなウェブサイトができます。
もちろんデメリットもありまして、サイトのデザインが似てしまうというのが難点です。
ですが基本はBootstrapを使って、ちょっと自分でカスタマイズしてオリジナルっぽくすることもできますので、
一度Twitter Bootstrapを使ってみる価値はあると思います。
http://twitter.github.com/bootstrap/
Bootstrapの説明が長くなってしまいましたね…。
1.エロいサイトを巡って、XVIDEOSやFC2動画などのリンク、embedされたものがあれば取得。
3.データベースに登録。
一連の作業をクローラーにやらせるプログラムをRubyで書く。
RailsでBootstrapを使うにはtwitter bootstrap railsというgemを使うらしいです。
しかし、使おうと思ったのですが、windowsでは上手くインストールできませんでした。
仕方なく、代わりにsass-rails-bootstrapというものを使いました。
違いはcssにLESSをつかっているかsass(scss)を使用しているかだと思います。
http://d.hatena.ne.jp/tkawa/20120219/p1
の記事が参考になりました。
ちなみにLESSとかSassってのはcssを効率的に書けるすぐれたものです。
最近、webクリエイターボックスさんでも紹介されていました。
http://www.webcreatorbox.com/tech/css-sass/
railsでは3.1からcoffee scriptと共にsassがデフォルトで使えます。
このあたりがRailsの素晴らしさですね。
Bootstrapは画像を綺麗に並べて表示することにも向いているので、
アダルトサイトと相性がいいなと感じました。
AV女優名とか女子校生、人妻などのジャンルのタグがあれば便利ですよね。
Railsではacts-as-taggable-onというgemを使い実装しました。
動画のタイトルが事前に用意したAV女優名リスト、ジャンルリストと合致すればタグ付けするという感じです。
AV女優リストはDMMから、ジャンルリストは大手アダルトサイトから作成しました。
タグ付けするときに あおいそら-蒼井そら みたいな感じでタグ付けするようにしました。
もっとスマートな方法があるはずですが思いつかなかったので仕方ないです。
ア行、カ行…のように行別にわけて、なおかつアイウエオ順で表記してますので
クッキーを使ってログイン不要のブックマーク機能を作りました。
jquery.cookie.jsを使って、cookieを配列に直してごにょごにょしてという感じで実装しました。
削除ボタンを押すと非同期で通信して…などいろいろ面倒でした。
でも、動画の数はかなり増やしていこうと思っていましたので頑張って実装しました。
動画の下のブックマークするボタンを押していただければブックマークできます。
ブックマークするボタンの表示などにBootstrapの便利さを感じました。
実はこれが一番やりたいことでした。
多くのアダルトサイトは広告だらけで、肝心の動画がポツンと小さくあるだけというのが多いです。
戦場で疲れた兵士たちに、そんなせせこましい画面でアダルト動画見ろって?
そんな野暮なこと言いませんよ。
PCスクリーンの画面いっぱいに、大画面で、ドカーンとエロ動画を楽しんで下さいよ。
動画はできるだけ大きく表示しています。もちろんレスポンシブです。
全画面表示にすりゃいいじゃん…っていうのは違うんですよ。
全画面表示だと逃げれないじゃないですか!
不意に誰かが部屋に入ってきたらどうするんですか?
そう考えております。
Bootstrapでデザイン面はスマホ対応にはなっているのですが、
加えてjpmobileというh300で紹介されていたgemを使って、
CPU 2.66GHz、メモリ 2.2GB HDD200GBです。
Railsは遅いので少しでも速くするためにApacheの代わりにNginx使おうと思ったのですが、
PC用のキャッシュとスマホ用のキャッシュを別々に保存して使う
ということがどうしてもできませんでした。
PC用のキャッシュがある場合、スマホ用のキャッシュがなくてもキャッシュがあると認識されるなど、
もともとNginxとrailsのページキャッシュは相性が悪いようです。
Nginx側でキャッシュする、もしくはスマホ用のアドレスを別にすればできるかもしれないですが、
http://m.サイト名 みたいにするのが嫌だったので最終的にNginxを使うことをやめました。
Nginxに関するネット上の記述も少ないので運用するのは危険かな、ということもあります。
Nginxを少しだけ使ってみた感触はかなり速いというものだったので残念でした。
バージョンが変われば、また挑戦したいですね。
【追記】
やっぱNginxでもいけるかもしれないですね。
紹介しないと終わらないということで紹介します。
http://nukisen.com (エロ注意)
サイト名はオシャレに横文字でNukisenにしました。読み方はヌキセンです。
http://bootswatch.com でダウンロードできるBootstrapのテーマそのままですが、
Bootstrapを使うと自動的に細部まで凝ったデザインになるので最高ですね。
下にスクロールしていくと背景のグラデーションが変化したりとか、とても一人ではできないですよね。
長々と説明してきましたが、
ぜひNukisenで大画面のアダルト動画を体感してほしいです。
しばらくは一日30本ぐらいの更新でいく予定です。
アダルトサイト同士の相互リンクでアクセス増やしてなどはしない方向です。
新しいことに挑戦すると得られるものが多いなと感じました。
ウェブサイトを作る際、無意識のうちに自分のできる範囲の技術で構築しがちだと思うんですが、
そうすると成長はないですね。
長文失礼しました。