
はてなキーワード:btnとは
昨日一番肝心なファイルなのにURLとみなされる部分が多いことの関係で投稿できなかったのでそれを小分けにして書く。
小分けというか例のスパムの影響でNGワードに引っかかっていたようなのでそこだけ書き換えた。
suuportと書いていある部分は元のコードでは当然uが一つ少ないので利用するときはそうすること。
fromselenium importwebdriver
fromselenium.webdriver.chrome.options import Options
fromselenium.webdriver.chrome.service import Service
fromwebdriver_manager.chrome importChromeDriverManager # ← 追加
fromselenium.webdriver.common.by importBy
fromselenium.webdriver.suupport.ui importWebDriverWait
fromselenium.webdriver.suupport import expected_conditionsasEC
importtime,json
fromselenium.common.exceptions importTimeoutException
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)
deflogin(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
defadd_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)
returnTrue
except Exceptionas e:
print(f"Bookmark failed: {e}")
returnFalse
def quit(self):
self.driver.quit()
-----BEGINPGP SIGNEDMESSAGE-----
Hash: SHA512
https://anond.hatelabo.jp/20250822131958#
-----BEGINPGP SIGNATURE-----
iHUEARYKAB0WIQTEe8eLwpVRSViDKR5wMdsubs4+SAUCaKfv9AAKCRBwMdsubs4+
SE26AQCkpJE4RdUbFIDIJjOunjFYRQ34zdS1cqV7IX277S7IPAEAshVE/rD8Ggcr
9UKo5yOY6GNrHGYJJtYTYkn3cySu6AA=
=E4vq
-----ENDPGP SIGNATURE-----
ようやく(ほぼ)すべてが自動化された。
あとはローカルサーバーの起動をスタートアップに設定する(方法をAIに聞いて指示に従う)だけの消化試合。
署名時要求してくるパスワードを自動入力するahkファイルはドキュメントのAutoHotkey配下に置いた。
バッチファイル(make.sign.bat)はデスクトップに置いた。
#Persistent#SingleInstance ignoreSetTitleMatchMode, 2WinWaitActive, pinentrySendInput お前のパスワードSleep 100SendInput {Enter}ExitApp
//run-batch-server.jsconsthttp =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 serverrunningathttp://localhost:12345/');});
@echo offsetlocal enabledelayedexpansion::ミリ秒単位のUTC時刻を取得for /f %%a in ('powershell -nologo -command "[int64]::Parse((Get-Date).ToUniversalTime().ToString('yyyyMMddHHmmssfff'))"') doset timestamp=%%a::署名するファイル名set infile=%TEMP%\pgp_input.txtset 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> nulgotosignloop):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 blankline).endlocalexit /b
// ==UserScript==// @namePGP署名自動付加スクリプト(GM_xmlhttpRequest版)// @namespacehttp://tampermonkey.net/// @version 1.0// @description投稿前にPGP署名を付けてから送信(fetch未使用)// @matchhttps://anond.hatelabo.jp/dorawii_31/edit*// @grant GM_xmlhttpRequest// @grant GM_setClipboard// @grant GM_notification// / @connectlocalhost// ==/UserScript==(function () { 'use strict';const submitId = 'submit-button';consttextareaId = 'text-body';const localServer = 'http://localhost:12345/run-batch';constpgpSignatureRegex = /-----BEGINPGPSIGNEDMESSAGE-----[\s\S]+?-----BEGINPGPSIGNATURE-----[\s\S]+?-----ENDPGPSIGNATURE-----/;consthttpRequest = (url) => { return newPromise((resolve,reject) => { GM_xmlhttpRequest({ method: 'GET',url:url, onload: function (response) { resolve(response.responseText); }, onerror: function (error) {reject(error); } }); }); };const interceptClick = () => {constbtn = document.getElementById(submitId); if (!btn ||btn.dataset.pgpIntercepted === 'true') return;btn.dataset.pgpIntercepted = 'true';btn.addEventListener('click', async function (e) {consttextarea = 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 { awaithttpRequest(localServer); //バッチ実行constsignatureText = await navigator.clipboard.readText(); if (!signatureText.includes('BEGINPGPSIGNEDMESSAGE')) { 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すごいなと思うよ。そして思うのは今後重要になってくるのは文法とか自体に詳しいことじゃなくて、そのプログラムの処理内容を指示できるシステムエンジニア的な言語化能力のほうじゃないかなと思った。
-----BEGINPGPSIGNEDMESSAGE-----Hash: SHA51220250609111559680 -----BEGINPGPSIGNATURE-----iHUEARYKAB0WIQTEe8eLwpVRSViDKR5wMdsubs4+SAUCaEbCbwAKCRBwMdsubs4+SLueAPwOv7PBk4voAe5qlcCEvs/PJhmKc5QAb/1R43JMQFuDZgD/UTPEKsL/PhK9jFGv2HDXK1dVjLNwvosgX9uYJh5xxwY==qiOE-----ENDPGPSIGNATURE-----
目が痛かった
textarea,
.message {
background-color: #7f8283 !important;
}
#body,
body,
.box-curve {
color: #c5c8c6 !important;
background-color: #333 !important;
}
.refererlistul {
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 bootstraprailsという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からcoffeescriptと共に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本ぐらいの更新でいく予定です。
アダルトサイト同士の相互リンクでアクセス増やしてなどはしない方向です。
新しいことに挑戦すると得られるものが多いなと感じました。
ウェブサイトを作る際、無意識のうちに自分のできる範囲の技術で構築しがちだと思うんですが、
そうすると成長はないですね。
長文失礼しました。