tm-b.hatenablog.com
Open in
urlscan Pro
35.75.255.9
Public Scan
URL:
https://tm-b.hatenablog.com/
Submission: On May 29 via api from US — Scanned from JP
Submission: On May 29 via api from US — Scanned from JP
Form analysis
0 forms found in the DOMText Content
中年プログラマーの息抜き 読者になる 中年プログラマーの息抜き ブログをはじめました。気の向くままにプログラム関連ネタをメモしていきます。 月額900円(税抜)から、高速・多機能・高安定レンタルサーバー『エックスサーバー』 この広告は、90日以上更新していないブログに表示しています。 2023-07-17 PYTHONでスクレイピング(SELENIUM,BEAUTIFULSOUP,OTP) プログラム Python スクレイピング selenium beautifulsoup oathtool ランキング参加中 Python ランキング参加中 プログラミング やりたいこと pythonスクリプトを実行し、以下の順で自動処理するマクロを作る。 1. ブラウザ(Chrome)をシークレットモードで開く 2. amazonショッピングサイトに自分のアカウントでログイン認証 3. あらかじめ選んでおいた商品をカートに入れる 実行環境 Pythonを使いますが、いくつかライブラリを追加しました。 ・chromedriver-binary ・selenium ・beautifulsoup4 ・oathtool 早速、環境を作りましょう。 といっても、簡単に進めたいので、PIPを使います。 PYTHONのバージョン python --version Python 3.9.7 PIPのバージョン pip --version pip 22.2.2 ・・・うーん、では、最新化しておきましょうか。 python -m pip install --upgrade pip pip --version pip 23.2 CHROMEのバージョン ブラウザを開いてバージョンを調べますね。・・115.0.5790.99を確認 ライブラリ「CHROMEDRIVER-BINARY」を追加 pip install chromedriver-binary==115.* ERROR: Could not find a version that satisfies the requirement chromedriver- ・・・ 112.0.5615.49.0, 113.0.5672.24.0, 113.0.5672.63.0, 114.0.5735.16.0, 114.0.5735.90.0) ERROR: No matching distribution found for chromedriver-binary==115.* エラーが出たので、一番近い「114.0.5735.90.0」を追加しましょう。 pip install chromedriver-binary==114.0.5735.90.0 pip list | grep chromedriver-binary chromedriver-binary 114.0.5735.90.0 ライブラリ「SELENIUM」を追加 pip install selenium pip list | grep selenium selenium 4.10.0 ライブラリ「BEAUTIFULSOUP4」を追加 pip install beautifulsoup4 pip list | grep beautifulsoup4 beautifulsoup4 4.12.2 ライブラリ「OATHTOOL」を追加 pip install oathtool pip list | grep oathtool oathtool 2.3.1 pypi.org ちょっと最終更新が古いですが、Amazonの2段階認証はパスできた。ネット調べるとミドル的なoath-toolkitの情報が多く見つかりますね。(今回のネタでは使いません) Python+Seleniumで2段階認証(6桁のパスコード)を突破する全手順 | たぬハック ライブラリ「そのほかすべて」を最新で更新しておこう pip-reviewを導入します。 pip install pip-review pip list | grep pip-review pip-review 1.3.0 パスを通します。(設定していなければ追加します) set path=C:\Users\・・・\AppData\Roaming\Python\Python39\Scripts;%path% まとめて最新で更新してみます。 pip-review --auto 私の環境だと依存がらみでエラーになりました。 RROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts. fabric3 1.14.post1 requires paramiko<3.0,>=2.0, but you have paramiko 3.2.0 which is incompatible. html5print 0.1.2 requires ply==3.4, but you have ply 3.11 which is incompatible. 1つずつ調整します。 まずは「ply」と「fabric3」 pip uninstall ply pip install ply==3.4 pip install -U fabric3 続けて「paramiko」と「html5print」 pip uninstall paramiko pip install paramiko==2.12.0 pip install -U html5print 2段階認証アプリ(OATHTOOL)を登録していきます。 アカウント > ログインとセキュリティ > 2段階認証 > 管理ボタンからバックアップ手段を追加(新しい電話または認証アプリを追加)とリンクをたどります。 バーコードをスキャンできませんか? をクリックするとシークレットが表示されるのでこれを控えておき、OTPで利用します。 python -m oathtool "!!! your secret !!!" 999999 ↑をワンタイムパスワードに入力して「ワンタイムパスワードを確認して次に進む」と2段階認証アプリ(oathtool)がアカウントに紐づきます。 2段階認証アプリ(OATHTOOL)をソースに組み込む。 こんな感じで組み込めます。 totp = oathtool.generate_otp("!!! your secret !!!") 全体のソース(PYTHON)はこんな感じです。 This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters Show hidden characters import time import oathtool from selenium import webdriver def request(url): global driver try: driver.get(url) time.sleep(3) except: pass def click(xpath): global driver try: el1 = driver.find_element(webdriver.common.by.By.XPATH, xpath) el1.click() time.sleep(3) except: pass def input(xpath, text): global driver try: el1 = driver.find_element(webdriver.common.by.By.XPATH, xpath) el1.send_keys(text) except: pass options = webdriver.ChromeOptions() options.add_argument('--incognito') options.add_argument('--headless') driver = webdriver.Chrome(options=options) request('https://www.amazon.co.jp/') click('//*[@id="nav-signin-tooltip"]/a') input('//*[@id="ap_email"]', '!!! your email !!!') click('//*[@id="continue"]') input('//*[@id="ap_password"]', '!!! your password !!!') click('//*[@id="signInSubmit"]') totp = oathtool.generate_otp("!!! your totp secret !!!") input('//*[@id="auth-mfa-otpcode"]', totp) click('//*[@id="auth-signin-button"]') request('https://www.amazon.co.jp/dp/・・・/') click('//*[@id="add-to-cart-button"]') driver.quit() view raw python-selenium-beautifulsoup-oathtool.py hosted with ❤ by GitHub import time import oathtool from selenium import webdriver def request(url): global driver try: driver.get(url) time.sleep(3) except: pass def click(xpath): global driver try: el1 = driver.find_element(webdriver.common.by.By.XPATH, xpath) el1.click() time.sleep(3) except: pass def input(xpath, text): global driver try: el1 = driver.find_element(webdriver.common.by.By.XPATH, xpath) el1.send_keys(text) except: pass options = webdriver.ChromeOptions() options.add_argument('--incognito') options.add_argument('--headless') driver = webdriver.Chrome(options=options) request('https://www.amazon.co.jp/') click('//*[@id="nav-signin-tooltip"]/a') input('//*[@id="ap_email"]', '!!! your email !!!') click('//*[@id="continue"]') input('//*[@id="ap_password"]', '!!! your password !!!') click('//*[@id="signInSubmit"]') totp = oathtool.generate_otp("!!! your totp secret !!!") input('//*[@id="auth-mfa-otpcode"]', totp) click('//*[@id="auth-signin-button"]') request('https://www.amazon.co.jp/dp/・・・/') click('//*[@id="add-to-cart-button"]') driver.quit() casimalu (id:tm-b) 317日前 読者になる 広告を非表示にする * もっと読む コメントを書く 2023-02-23 【C#】キーフック-左CAPSLOCKを無効にして左CTRLキーに偽装してみた C# プログラム グローバルフック キー配置 キーマップ キーボード ランキング参加中 Microsoft .NET ランキング参加中 プログラミング 早速経緯から、 つい最近までHHKBキーボードを使っていましたが、パワポやワードなど資料作成時間が増えたことから矢印キー(↑→↓←)の利用頻度が増えます。 長時間作業すると 右手首が痛いんじゃ 状態 ※HHKBでは、矢印キーは「Fn」割り当て そんな理由から、手元でほこりをかぶっていたRealForce108UBKキーボードを使うようにしたのですが、これCapsLockと左Controlキーの割り当て変更が出来ません。 HHKBキーボードの左Ctrlキーに慣れきっているのでタイピング中の手の位置も中央付近が習慣付けされていて、こうなると左下にある左Ctrlキーを使うときの違和感が半端ないんですよね。さらに、間違えてCapsLockしてしまうことでイライラ そして、長時間作業すると 左手首が痛いんじゃ 状態 キーボード買い換えも考えますが、そんな余裕もないしそもそもこんな理由で買い替えるなんていやだしなぁといった感じで我慢して何日か作業したんですが、どうにも慣れない機材を使うと作業時間に比例してイライラ ※少し使うと慣れてくるかと思いましたが、全然でした。 ということで、プログラム書いてCapsLockキー入力を無効にして使ってます。 ※単に無効化するだけでは面白くなかったので「CtrlLockキー」にしてしまいました。 以下C#ソースコード public static class KeyboardHook { [StructLayout(LayoutKind.Sequential)] private struct KBDLLHOOKSTRUCT { public uint vkCode; public uint scanCode; public uint flags; public uint time; public UIntPtr dwExtraInfo; } [StructLayout(LayoutKind.Sequential)] private struct KEYBDINPUT { public ushort wVk; public ushort wScan; public uint dwFlags; public uint time; public UIntPtr dwExtraInfo; public int dummy1; public int dummy2; }; [StructLayout(LayoutKind.Sequential)] private struct INPUT { public int type; public KEYBDINPUT ki; }; [DllImport("user32.dll")] private static extern IntPtr SetWindowsHookEx(int idHook, KeyboardProc lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll")] private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); [DllImport("kernel32.dll")] private static extern IntPtr GetModuleHandle(string lpModuleName); [DllImport("user32.dll")] private static extern uint SendInput(int nInputs, INPUT pInputs, int cbsize); private const int WH_KEYBOARD_LL = 0x000D; private static readonly IntPtr TRUE = new IntPtr(1); private static readonly IntPtr WM_KEYDOWN = new IntPtr(0x0100); private static readonly IntPtr WM_KEYUP = new IntPtr(0x0101); private static readonly IntPtr WM_SYSKEYDOWN = new IntPtr(0x0104); private static readonly IntPtr WM_SYSKEYUP = new IntPtr(0x0105); private static readonly INPUT CTRL_D = { new INPUT { type = 1, ki = new KEYBDINPUT() { wVk = 162, wScan = 0, dwFlags = 0, time = 0, dwExtraInfo = UIntPtr.Zero } } }; private static readonly INPUT[] CTRL_U = { new INPUT { type = 1, ki = new KEYBDINPUT() { wVk = 162, wScan = 0, dwFlags = 2, time = 0, dwExtraInfo = UIntPtr.Zero } } }; private static readonly int SZ_INPUT = Marshal.SizeOf(typeof(INPUT)); private delegate IntPtr KeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); private static readonly KeyboardProc proc = Proc; private static IntPtr sHookId = IntPtr.Zero; private static bool sHoldCtrl = false; public static void Start() { if (sHookId != IntPtr.Zero) return; using (var p = Process.GetCurrentProcess()) using (var m = p.MainModule) sHookId = SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(m.ModuleName), 0); } public static void Stop() { UnhookWindowsHookEx(sHookId); sHookId = IntPtr.Zero; if (sHoldCtrl) SendInput(1, CTRL_U, SZ_INPUT); } private static IntPtr Proc(int nCode, IntPtr wParam, IntPtr lParam) { if (nCode < 0) return CallNextHookEx(sHookId, nCode, wParam, lParam); if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) { var kb = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT)); var vkCode = kb.vkCode; if (vkCode == 20) { SendInput(1, CTRL_D, SZ_INPUT); sHoldCtrl = true; return TRUE; } else if (vkCode == 240 || vkCode == 242) { if (sHoldCtrl) SendInput(1, CTRL_U, SZ_INPUT); return TRUE; } else if (vkCode == 162) { if (sHoldCtrl) SendInput(1, CTRL_U, SZ_INPUT); } } else if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP) { var kb = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT)); var vkCode = kb.vkCode; if (vkCode == 20 || vkCode == 240 || vkCode == 242) { if (sHoldCtrl) SendInput(1, CTRL_U, SZ_INPUT); return TRUE; } else if (vkCode == 162) { sHoldCtrl = false; } } return CallNextHookEx(sHookId, nCode, wParam, lParam); } } This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters Show hidden characters public static class KeyboardHook { [StructLayout(LayoutKind.Sequential)] private struct KBDLLHOOKSTRUCT { public uint vkCode; public uint scanCode; public uint flags; public uint time; public UIntPtr dwExtraInfo; } [StructLayout(LayoutKind.Sequential)] private struct KEYBDINPUT { public ushort wVk; public ushort wScan; public uint dwFlags; public uint time; public UIntPtr dwExtraInfo; public int dummy1; public int dummy2; }; [StructLayout(LayoutKind.Sequential)] private struct INPUT { public int type; public KEYBDINPUT ki; }; [DllImport("user32.dll")] private static extern IntPtr SetWindowsHookEx(int idHook, KeyboardProc lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll")] private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); [DllImport("kernel32.dll")] private static extern IntPtr GetModuleHandle(string lpModuleName); [DllImport("user32.dll")] private static extern uint SendInput(int nInputs, INPUT[] pInputs, int cbsize); private const int WH_KEYBOARD_LL = 0x000D; private static readonly IntPtr TRUE = new IntPtr(1); private static readonly IntPtr WM_KEYDOWN = new IntPtr(0x0100); private static readonly IntPtr WM_KEYUP = new IntPtr(0x0101); private static readonly IntPtr WM_SYSKEYDOWN = new IntPtr(0x0104); private static readonly IntPtr WM_SYSKEYUP = new IntPtr(0x0105); private static readonly INPUT[] CTRL_D = { new INPUT { type = 1, ki = new KEYBDINPUT() { wVk = 162, wScan = 0, dwFlags = 0, time = 0, dwExtraInfo = UIntPtr.Zero } } }; private static readonly INPUT[] CTRL_U = { new INPUT { type = 1, ki = new KEYBDINPUT() { wVk = 162, wScan = 0, dwFlags = 2, time = 0, dwExtraInfo = UIntPtr.Zero } } }; private static readonly int SZ_INPUT = Marshal.SizeOf(typeof(INPUT)); private delegate IntPtr KeyboardProc(int nCode, IntPtr wParam, IntPtr lParam); private static readonly KeyboardProc proc = Proc; private static IntPtr sHookId = IntPtr.Zero; private static bool sHoldCtrl = false; public static void Start() { if (sHookId != IntPtr.Zero) return; using (var p = Process.GetCurrentProcess()) using (var m = p.MainModule) sHookId = SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(m.ModuleName), 0); } public static void Stop() { UnhookWindowsHookEx(sHookId); sHookId = IntPtr.Zero; if (sHoldCtrl) SendInput(1, CTRL_U, SZ_INPUT); } private static IntPtr Proc(int nCode, IntPtr wParam, IntPtr lParam) { if (nCode < 0) return CallNextHookEx(sHookId, nCode, wParam, lParam); if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) { var kb = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT)); var vkCode = kb.vkCode; if (vkCode == 20) { SendInput(1, CTRL_D, SZ_INPUT); sHoldCtrl = true; return TRUE; } else if (vkCode == 240 || vkCode == 242) { if (sHoldCtrl) SendInput(1, CTRL_U, SZ_INPUT); return TRUE; } else if (vkCode == 162) { if (sHoldCtrl) SendInput(1, CTRL_U, SZ_INPUT); } } else if (wParam == WM_KEYUP || wParam == WM_SYSKEYUP) { var kb = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT)); var vkCode = kb.vkCode; if (vkCode == 20 || vkCode == 240 || vkCode == 242) { if (sHoldCtrl) SendInput(1, CTRL_U, SZ_INPUT); return TRUE; } else if (vkCode == 162) { sHoldCtrl = false; } } return CallNextHookEx(sHookId, nCode, wParam, lParam); } } view raw GlovalHock-KeyboardHook hosted with ❤ by GitHub KEYBOARDHOOKクラスリファレンス CapsLockキー入力を無効化します。 CapsLockキー入力で状態を切り替えます。 → Ctrlキーロック状態をエミュレート → Ctrlキーロック状態をリリース * KEYBOARDHOOK.START() グローバルフック(キーフック)開始 * KEYBOARDHOOK.STOP() グローバルフック(キーフック)停止 casimalu (id:tm-b) 1年前 読者になる 広告を非表示にする * もっと読む コメントを書く 2022-10-19 WORDPRESS の記事を短く表示したい。語尾に三点リーダー(…)を付ける方法 php wordpress プログラム Shopify ランキング参加中 PHP はじめに ブログなどでタイトルや一覧画面のレイアウトを考えるとき、本文が長すぎたり画像が表示されてしまったりと、想定している枠内に文字が収まりきらなくなる場合があります。 PHP(ワードプレス)の投稿一覧画面と投稿内容画面との関係を考えていて投稿一覧画面にも簡単な説明文を表示したいことはありませんか? この場合、例えばカスタムフィールドなどを利用して、一覧表示文と投稿本文とをそれぞれで保存しておくのが簡単です。といっても面白くないので、今回は、投稿本文の中から100文字の一覧表示文を自動作成して、100文字を超えたところで語尾に三点リーダー(…)を付ける方法を紹介します。こうしておくと一覧表示レイアウトから簡単な説明が読み取れますし『あ、まだ続きがあるんだ…。』ということも伝わりますね。 まずは完成イメージ 今手伝っているフェスの準備でWordpressを使ってみました。(期間限定の紹介です)※レイアウトはデザイナーさんがきれいに仕上げてくれます。 onestead.xsrv.jp 目指すこと(実現したいこと) 「PHP(ワードプレス)の投稿本文に設定した内容を一覧画面へ反映する 「テキストを含むタグ以外(img)などは除去する」 「文字数は上限(100文字)を設ける」 「文字数上限を超える場合、語尾に三点リーダーを付与する」 「XSERVER」環境(Wordpress)で動作する PHP(ワードプレス)で語尾に三点リーダー function.phpなどへ作成しておき表示用のPHPファイルから実行するだけです。 <?php echo(strimwidth_post_contents($post->post_content)); ?> This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters Show hidden characters function __strimwidth_post_contents($node, &$count) { $result = 0; $strwidth = 100; if ($node->hasChildNodes() === false) { if (property_exists($node, "nodeValue") === true && $node->nodeValue !== null && $node->nodeType === XML_TEXT_NODE) { if ($count < $strwidth) { $value = preg_replace("/\s/", '', $node->nodeValue); if ($value === null) { $result = 1; } else { $length = mb_strlen($value, 'UTF-8'); if ($length === 0) { $result = 1; } else if (($count + $length) < $strwidth) { $count += $length; } else { $node->nodeValue = mb_substr($node->nodeValue, 0, ($strwidth - $count), 'UTF-8').' ... '; $count = $strwidth + 5; } } } else { $result = 1; } } else { $result = 1; } } else { for ($i = 0; $i < $node->childNodes->length; $i++) if (__strimwidth_post_contents($node->childNodes[$i], $count) === 1) $node->removeChild($node->childNodes[$i--]); if ($node->hasChildNodes() === false) $result = 1; } return $result; } function strimwidth_post_contents($post_content) { if (isset($post_content) === false) return ""; $count = 0; $doc = new DOMDocument('1.0', 'UTF-8'); $doc->loadHTML('<div class="strimwidth_post_contents">'.mb_convert_encoding(str_replace('&','&',$post_content).'</div>','HTML-ENTITIES','UTF-8'),LIBXML_HTML_NOIMPLIED|LIBXML_HTML_NODEFDTD|LIBXML_NOERROR); for ($i = 0; $i < $doc->childNodes->length; $i++) if (__strimwidth_post_contents($doc->childNodes[$i], $count) === 1) $doc->removeChild($doc->childNodes[$i--]); return mb_convert_encoding($doc->saveHTML(), 'UTF-8', 'HTML-ENTITIES'); } view raw strimwidth_post_contents hosted with ❤ by GitHub まとめ ちょっとしたことですがヒューマンエラーを減らすことにもつながりますし、自動処理させるという視点は大切なのかなと感じます。REST化してJS経由から実行すればShopifyなどで活用するなど利用シーンはあるのかな。 DOMDOCUMENTって何者? ここで詳しく説明されてます。とても参考になります、ありがとうございます。 PHPでDOMを使ってHTMLをロード... 能古島フェスの紹介 W@F 福岡ワーケーションフェス2022 日本でもっともチルな島、能古島 casimalu (id:tm-b) 1年前 読者になる 広告を非表示にする * もっと読む コメントを書く 次のページ 月別アーカイブ * ▼ ▶ 2023 (2) * 2023 / 7 (1) * 2023 / 2 (1) * ▼ ▶ 2022 (1) * 2022 / 10 (1) * ▼ ▶ 2021 (5) * 2021 / 9 (1) * 2021 / 8 (3) * 2021 / 2 (1) * ▼ ▶ 2020 (9) * 2020 / 11 (1) * 2020 / 10 (1) * 2020 / 9 (6) * 2020 / 7 (1) * ▼ ▶ 2019 (12) * 2019 / 10 (2) * 2019 / 2 (3) * 2019 / 1 (7) * ▼ ▶ 2018 (1) * 2018 / 6 (1) * ▼ ▶ 2017 (25) * 2017 / 11 (1) * 2017 / 10 (2) * 2017 / 8 (11) * 2017 / 7 (8) * 2017 / 3 (1) * 2017 / 1 (2) * ▼ ▶ 2016 (32) * 2016 / 12 (2) * 2016 / 11 (4) * 2016 / 10 (1) * 2016 / 9 (1) * 2016 / 8 (9) * 2016 / 6 (2) * 2016 / 4 (5) * 2016 / 2 (7) * 2016 / 1 (1) * ▼ ▶ 2015 (5) * 2015 / 10 (4) * 2015 / 8 (1) プロフィール 読者です 読者をやめる 読者になる 読者になる 20 このブログについて 中年プログラマーの息抜き Powered by Hatena Blog | ブログを報告する 引用をストックしました ストック一覧を見る 閉じる 引用するにはまずログインしてください ログイン 閉じる 引用をストックできませんでした。再度お試しください 閉じる 限定公開記事のため引用できません。 読者です 読者をやめる 読者になる 読者になる 20