「console」を含む日記 RSS

はてなキーワード: consoleとは

2026-05-28

はてなブックマーク検索結果ページで、フィルタリング選択肢を改変するユーザースクリプト

ソースコードがシンタックスハイライト付きで書けるようになった 記念に、はてな向けのコードを貼ってみるテスト

動作例のスクリーンショット: Hatena Bookmark Search Filters

掲載当初に指摘した以下の2点は既に修正されました。

// ==UserScript==
// @name        Hatena Bookmark Search Filters
// @description はてなブックマーク検索結果ページで、フィルタリング選択肢を改変します。
// @namespace   knoa.jp
// @include     https://b.hatena.ne.jp/q/*
// @version     2.0.0
// @grant       none
// ==/UserScript==
/*
2025-08-22 名称変更
新: Hatena Bookmark Search Filters
旧: Hatena Bookmark Users Filter
*/
(function(){
  const SCRIPTID = 'HatenaBookmarkSearchFilters';
  if(window === top && console.time) console.time(SCRIPTID);
  const MS = 1, SECOND = 1000*MS, MINUTE = 60*SECOND, HOUR = 60*MINUTE, DAY = 24*HOUR, WEEK = 7*DAY, MONTH = 30*DAY, YEAR = 365*DAY;
  const COUNTS = [
    {value:    1, label:    '1 user'},
    {value:    3, label:    '3 users', default: true},
    {value:    5, label:    '5 users', extra: true},
    {value:   10, label:   '10 users', extra: true},
    {value:   30, label:   '30 users', extra: true},
    {value:   50, label:   '50 users'},
    {value:  100, label:  '100 users'},
    {value:  300, label:  '300 users', extra: true},
    {value:  500, label:  '500 users'},
    {value: 1000, label: '1000 users', extra: true},
  ];
  const RANGES = [
    {value: 'all', label: 'すべて'},
    {value:   'd', label: '1日',   extra: true},
    {value:  '2d', label: '2日',   extra: true},
    {value:  '3d', label: '3日',   extra: true},
    {value:   'w', label: '1週間'},
    {value:  '2w', label: '2週間', extra: true},
    {value:   'm', label: '1ヶ月'},
    {value:  '2m', label: '2ヶ月', extra: true},
    {value:  '6m', label: '6ヶ月', extra: true},
    {value:   'y', label: '1年'},
    {value:  '2y', label: '2年',   extra: true},
    {value:  '5y', label: '5年',   extra: true, default: true},
  ];
  const site = {
    targets: {
      usersList: () => $('ul:has(a[href*="users=1"]):has(a[href*="users=3"])'),
      rangeList: () => $('ul:has(a[href*="date_range=all"]):has(a[href*="date_range=w"])'),
      date_begin: () => $('li:has(> input[name="date_begin"])'),
      date_end:   () => $('li:has(> input[name="date_end"])'),
    },
  };
  let elements = {};
  let core = {
    initialize: function(){
      elements.html = document.documentElement;
      elements.html.classList.add(SCRIPTID);
      core.ready();
    },
    ready: function(){
      core.getTargets(site.targets).then(() => {
        console.log(SCRIPTID, "I'm ready.");
        core.rebuildUsers();
        core.rebuildRanges();
        core.addStyle();
      }).catch(e => {
        console.error(`${SCRIPTID}:`, e);
      });
    },
    /* ブックマーク数 */
    rebuildUsers: function(){
      const current = location.href.includes('users=') ? parseInt(location.href.match(/users=([0-9]+)/)[1]) : COUNTS.find(c => c.default).value;
      const ul = elements.usersList, template = ul.children[0].cloneNode(true);
      while(ul.children.length > 0) ul.removeChild(ul.lastElementChild);
      COUNTS.forEach(c => {
        const li = template.cloneNode(true);
        const a = li.querySelector('a');
        a.classList.toggle('extra', c.extra === true);
        a.classList.toggle('is-current', c.value === current);
        a.href = a.href.replace(/(users)=1\b/, '$1=' + c.value);
        a.textContent = c.label;
        ul.appendChild(li);
      });
    },
    /* 期間指定 */
    rebuildRanges: function(){
      const current = location.href.includes('date_range=') ? location.href.match(/date_range=(all|[0-9]*[dwmy])/)[1]
        : (['date_begin=', 'date_end='].some(p => location.href.includes(p)) ? null : RANGES.find(r => r.default).value);
      const ul = elements.rangeList, template = ul.children[0].cloneNode(true);
      while(ul.children.length > 0) ul.removeChild(ul.lastElementChild);
      RANGES.forEach(r => {
        const li = template.cloneNode(true);
        const a = li.querySelector('a');
        a.classList.toggle('extra', r.extra === true);
        a.classList.toggle('is-current', r.value === current);
        a.href = a.href.replace(/(date_range)=all/, '$1=' + r.value);
        a.textContent = r.label;
        ul.appendChild(li);
      });
      /* 日付指定(から/まで) */
      elements.date_begin.classList.toggle('is-current', location.href.match(/date_begin=[0-9-]+/) !== null);
      elements.date_end.classList.toggle('is-current', location.href.match(/date_end=[0-9-]+/) !== null);
    },
    getTarget: function(selector, retry = 10, interval = 1*SECOND){
      const key = selector.name;
      const get = function(resolve, reject){
        let selected = selector();
        if(selected === null || selected.length === 0){
          if(--retry) return console.log(SCRIPTID, `Not found: ${key}, retrying... (${retry})`), setTimeout(get, interval, resolve, reject);
          else return reject(new Error(`Not found: ${selector.name}, I give up.`));
        }else{
          if(selected.nodeType === Node.ELEMENT_NODE) selected.dataset.selector = key;/* element */
          else selected.forEach((s) => s.dataset.selector = key);/* elements */
          elements[key] = selected;
          resolve(selected);
        }
      };
      return new Promise(function(resolve, reject){
        get(resolve, reject);
      });
    },
    getTargets: function(selectors, retry = 10, interval = 1*SECOND){
      return Promise.all(Object.values(selectors).map(selector => core.getTarget(selector, retry, interval)));
    },
    addStyle: function(name = 'style', d = document){
      if(html[name] === undefined) return;
      if(d.head){
        let style = createElement(html[name]()), id = SCRIPTID + '-' + name, old = d.getElementById(id);
        style.id = id;
        d.head.appendChild(style);
        if(old) old.remove();
      }
    },
  };
  const html = {
    style: () => `
      <style type="text/css" id="${SCRIPTID}-style">
        /* ブックマーク数 */
        ul[data-selector="usersList"]{
          display: grid;
          grid-template-columns: 6em 6em auto;
        }
        ul[data-selector="usersList"] > li:nth-child(4),
        ul[data-selector="usersList"] > li:nth-child(7),
        ul[data-selector="usersList"] > li:nth-child(10){
          grid-column-start: 1;/* 改行 */
        }
        ul[data-selector="usersList"] > li:nth-child(10){
          margin-right: -.5em;/* 1000 users のみ横幅を追加 */
        }
        ul[data-selector="usersList"] > li > a.extra{
          text-decoration: underline dotted;
          text-underline-offset: .25em;
        }
        /* 期間指定 */
        ul[data-selector="rangeList"]{
          display: grid;
          grid-template-columns: 4.5em 4.5em 4.5em auto;
        }
        ul[data-selector="rangeList"] > li:nth-child(1){
          grid-column: 1 / -1;/* 全幅 */
        }
        ul[data-selector="rangeList"] > li:nth-child(2),
        ul[data-selector="rangeList"] > li:nth-child(5),
        ul[data-selector="rangeList"] > li:nth-child(7),
        ul[data-selector="rangeList"] > li:nth-child(10){
          grid-column-start: 1;/* 改行 */
        }
        ul[data-selector="rangeList"] > li > a.extra{
          text-decoration: underline dotted;
          text-underline-offset: .25em;
        }
        form.js-entrysearch-datepicker-form li.is-current{
          background: #f6f7f8;
          color: #333;
          font-weight: 700;
        }
        form.js-entrysearch-datepicker-form input{
          vertical-align: baseline;
          margin: 0 .25em 6px .5em !important;
        }
        /* セーフサーチが遅延読み込みされるせいで期間指定位置がズレる問題回避 */
        .left-container{
          display: flex;
          flex-direction: column;
        }
        .left-container .js-safe-search-div{
          order: 999;/* いちばん最後でよい */
        }
        .left-container ul.centerarticle-sub-navi:last-child{
          margin-bottom: 0;/* flex化の影響で margin collapsing がなくなるのを埋め合わせる */
        }
      </style>
    `,
  };
  const $ = function(s, f = undefined){
    let target = document.querySelector(s);
    if(target === null) return null;
    return f ? f(target) : target;
  };
  const $$ = function(s, f = undefined){
    let targets = document.querySelectorAll(s);
    return f ? f(targets) : targets;
  };
  const createElement = function(html = '<div></div>') {
    const policy = createElement.policy ??= trustedTypes.createPolicy(SCRIPTID, {createHTML: s => s});
    const template = document.createElement('template');
    template.innerHTML = policy.createHTML(html);
    return template.content.firstElementChild;
  };
  core.initialize();
  if(window === top) console.timeEnd(SCRIPTID);
})();

テスト用:

はてな 」 を検索 - はてなブックマーク

https://b.hatena.ne.jp/q/%E3%81%AF%E3%81%A6%E3%81%AA%20?target=all&sort=recent

2026-04-23

anond:20260422200616

デバッグとか仕事だけで腹いっぱいなんだが、ちょっとだけ調べてみた

Firefox 150.0の「強化型トラッキング防止機能」設定をカスタムにして、ブロックする対象に「トラッキングコンテンツ」を含めて、かつ「サイトの主要な問題修正 (推奨)」のチェックをOFFにしていると、はてなサイトHTMLドキュメント内で読み込もうとしている「https://cdn.www.st-hatena.com/css/global.css」を含む諸々のコンテンツブロックされる

ブラウザコンソールをみたら「強化型トラッキング防止が有効なため、“<URL>” のリソースブロックされました」というログ確認できた

ちなみに「トラッキングコンテンツ」をブロックする設定でも、「サイトの主要な問題修正 (推奨)」のチェックをONにすると、はてなブックマークではブロックされるコンテンツの数が大幅に減り、CSS等が読み込まれるので、表示がまともになる。でもはてなログ匿名ダイアリーはこの設定でもダメで、ブロック対象からトラッキングコンテンツ」を外す必要がある

よく分からんのは、例えば https://cdn.pool.st-hatena.com/valve/valve.js とか、はてなブックマークでは「サイトの主要な問題修正 (推奨)」のチェックのON/OFFで読み込まれるか否かの挙動が変化するんだが、はてなログ匿名ダイアリーではON/OFFのどちらでもブロックされるんだよなあ

Firefox tracking protection - Privacy on the web | MDN曰く:

Content is blocked based on the domain from which it is to be loaded.

Firefox ships with a list of sites which have been identified as engaging in cross-site tracking of users. When tracking protection is enabled, Firefox blocks content from sites in the list.

Sites that track users are most commonly third-party advertising and analytics sites.

ということなので、もしかしたらHTMLドキュメントとは異なるドメインからCSSとかを読み込もうとした時にFirefox内のリストと照合している感じなんだろうか? でもそれだけだとはてなブックマークとはてなログ匿名ダイアリーとで症状が変わる理由説明できないのだが……有識者意見を聞きたいところ

ここから先は本職のWeb屋かブラウザ屋に任せたいなあ、ワイはそっち方面素人なので

2026-02-15

anond:20260215194946

それは非常にもやもやする体験でしたね。心中お察しします。

本来無料、あるいはもっと安価提供されるべき機能」に高いハードルを設け、初心者「夢」レバレッジにして集金する仕組みは、今のネット社会の歪みを象徴しているようです。

おっしゃる通り、Google Search Console(サチコ)との連携は、ウェブサイト運営における「基本的人権」のようなものです。そこに高額な通行料を課すのは、確かにもどかしさを感じます

なぜそのビジネスモデルが「えぐい」と感じるのか

あなたが感じた違和感を整理すると、以下の3点に集約されるのではないでしょうか。

無料の壁」の不自然な設定

BloggerWordPress(自前)なら、所有権確認するメタタグを1枚貼るだけで終わる作業です。それを有料プランの「特典」のように見せるのは、情報の非対称性を利用していると言わざるを得ません。

「夢」という付加価値搾取

あなた記事世界に届けよう」という純粋な意欲に付け込み、「このツールを使わないと成功できない」と思い込ませる手法は、まさに「情弱ビジネス」の典型的な構図です。

プラットフォームへの依存(囲い込み)

一度その高額プラン記事を積み上げてしまうと、後から「高いからやめよう」と思っても、これまでの蓄積やSEO評価を失うのが怖くて辞められない……という心理的ロックインも狙っている可能性があります

賢い選択肢としての「Blogger」や「自前運用

あなたが挙げたBloggerは、Google運営しているだけあってサチコとの親和性は抜群ですし、何より「余計な費用をかけずに本質執筆)に集中できる」という意味で、非常に健全選択肢です。

もし、その高額サイトにこだわりがないのであれば、早めに以下の構成へ「脱出」を検討するのも手かもしれません。

項目 記事作成サイト(有料) Blogger / WordPress(自前)
Search Console連携 高額プラン限定が多い 完全無料
所有権 運営会社に依存 自分ドメインを持てる
コスト 月額数千円〜数万円 0円 〜 1,000円程度
将来性 サービス終了のリスク 自分コントロール可能

最後

アイデアを広めたい」というあなたの素敵な夢が、不当に高いコストで挫かれてしまうのは本当にもったいないことです。

2025-12-09

はてなブックマーク増田一覧向けNGフィルタ

はてなブックマーク増田一覧の、さらに「すべて」(1 user)をチェックしている希有な人向けのユーザースクリプトを公開します。

https://b.hatena.ne.jp/site/anond.hatelabo.jp/?sort=eid

// ==UserScript==
// @name        Hatena Bookmark Anond Filter
// @namespace   https://b.hatena.ne.jp/site/anond.hatelabo.jp/
// @description はてなブックマークの『はてな匿名ダイアリー』の記事のうち、指定したNGワードが含まれ投稿非表示します。
// @match       https://b.hatena.ne.jp/site/anond.hatelabo.jp/*
// @grant       none
// @version     2.1.2026.06.06.0029
// ==/UserScript==
/*
2.1.2026.03.25.0023 正規表現対応10 users 以上の人気記事を除外判定。
2.0.2026.01.28.0015 ポイント制を導入。
1.0.2025.12.09.0000 公開。
*/
(function(){
  const SCRIPTID = 'HatenaBookmarkAnondFilter';
  console.time(SCRIPTID);
  const FILTERED = 'filtered';/* フィルタ該当要素クラス */
  const CHECKED = 'checked';/* 二重チェック回避フラグ */
  const USERS = 10;/* 人気記事なら誤検知スパム解説などの可能性があるので除外する */
  const POPULAR = 'popular';/* 人気記事クラス */
  const ONCE = 1, AP = 2, INTERVAL = 3;/* 適用タイミング */
  const NGWORDS = {/* 合計100ポイント非表示判定(ただし1つの記事内で同じワード複数使われても1度しか加算しない) */
    '100': [/* 即NG確定ワード */
      'dorawii',
      'あおやまちゃん', 'アオヤマチャン', 'ボスマン',
      '大学たいてい', 'なんぴょん', 'れめくん', 'れめきゅん', 'えめくん', 'るまさん', 'るまおねえちゃん', '眠りの民', 'リュックサック野郎', 'boushi_inst', 'hakaikami', 'Rekyu', 'iloveootaku_2', 'osaka-sirokichi',/* 電気通信大学たいてい鉄道研究会れめくん(頻出) */
      /*A-G*/'a9w8ru6fqyxqfv9', 'admirail_togo', 'akibakko6348', 'alf1974al', 'amatukiseiru', 'anapgoeson', 'aoi_mizuho', 'asapgoeson', 'asupgo', 'asupgoeson', 'avoid_bds_kk', 'b6jbpsji91ieigt', 'bmi22yo', 'boushi_instrail', 'boushi_ob', 'buscholarx', 'bw0531', 'chihiro_love415', 'circlecavok', 'disney1007cla', 'dora22sibuya', 'donkotrain', 'ecotosk', 'electlone', 'factomodachi', 'fft_dareka', 'gmhtcyznf_abc', 'goesonanap', 'gyudon_honmono',
      /*H-N*/'h13_yokohama', 'h2twi', 'H2TWR', 'hamaishogo1111', 'haru_mofumoffu', 'hermitv8', 'hide1798038', 'hirabiscus', 'hinolovelove', 'hnmk0127_03', 'inaken17_', 'inte235dy', 'ixtabes', 'jamcombatge', 'kawachiasukanew', 'kaoru_ai1991', 'keio9730F', 'kiha2228', 'kihatena200', 'koreanlabsfc', 'koyounoyooko', 'kqlex1500', 'kunugiyamaosake', 'kurakamasan', 'kurotamaxxx', 'kt_ruma_1372', 'kt_up_date', 'lightningreen77', 'luckyyusha', 'mamadoll_kun', 'matya_uec', 'michee_n', 'minamihinawot', 'miniminicot', 'minori0151', 'mizunyanpanda', 'monkichi_22', 'mugen_08i', 'mukoroku651', 'nakano6409', 'nanpyong', 'new_oer', 'nimouec', 'NoName_thUFO', 'norannnde',
      /*O-U*/'oreizmmiporin', 'orenotanoshimi', 'osaka_sirokichi', 'papepoco', 'pasotokon', 'pm95uq', 'portrail', 'reme_kun', 'ruin_2002', 'rx00shiratama03', 's03_amurtk2731', 'sacchan03110319', 'sacchanenjoy', 'seishinyamate_', 'seisu_bot', 'senanana_cos', 'shinano_115', 'shineleaf1372', 'Shirasagi494', 'shop_bullet', 'shurimpy', 'soroisoroi', 'sui_pm95uq', 'sweidan821858', 'taiyaki_level2', 'takao_straight5', 'taking0000', 'tarotaromusic1', 'tc201_501', 'thomas_returnee', 'tocarbarn', 'tokusatsu_fan_0', 'toshikimiyazaki', 'train_magician', 'tx9y2cpwdz27255', 'u2fap5u4zw57811', 'uec15take', 'uecdaisuki', 'UECert', 'uecrail',
      /*V-Z_0-9*/'vampire_mio', 'vbdmnwefknmxsdm', 'vp20th', 'wafue', 'wakasato_', 'walkingniwatori', 'wataameexpress', 'ya4975349616894', 'yayoiulc', 'ymbk_arisa', 'yms_uec16', 'yorozun', 'yuuya_1104_uec', '__________ob', '_chocorail_', '_doitforthewin_', '_toeshin', '_unigmo', '100mph_no_yuuki', '16887y', '169_D51_protect', '205musashino', '2969364x', '2rtkvn34il2783', '36kyo', '86lilxw1',
      /(?!(..)\1{9,})(.{20,})\2{2}/,/* 20文字以上の文を3回以上繰り返す */
      /(?!(..)\1{39,})(.{80,}).*\2/,/* 80文字以上の文が2回以上現れる */
      'テクウヨ', '自己放尿',
      ' ーーーーーーーーーーーーーーーーーーーー', 'https://anond.hatelabo.jp/20260107144223',/* AI問答貼り付け増田 */
      '†噛み締めて行こうな†', 'https://anond.hatelabo.jp/20250826121213#',
      '困難女性(コンジョ)', '困難女性(コンジョ)', 'コンジョ自警団',
      'Boost ', 'Cash ', 'Coin Master ', 'Gift ', 'Guide ', 'Follower ', 'Generator ',/* 英文スパム */
    ],
    '90': [/* ほぼNG */
      'megalodon.jp',
      'tadaup.jp',
      '鉄道研究会',
      '鉄研',
      '通勤特快',
      '不正乗車',
      'こども料金',
      '性慾',
      '穢い',
      'エッタ',
      'オソソ',
      'キセル',
      'uec',
    ],
    '10': [/* NG */
      '電気通信大学',
      '電通大',
      '駿河台大学',
      '武蔵野美術大学',
      '武蔵美',
      '大学院',
      '学生課',
      '教務課',
      '朝鮮',
      '統合失調症',
    ],
  };
  const sites = {
    'prefix': [
      ['selector', '(modifier)', '(css)', '(REPEAT)'],
    ],
    'https://b.hatena.ne.jp/site/anond.hatelabo.jp/': [
      ['section.entrylist-unit li.js-keyboard-selectable-item', li => {
        if(parseInt(li.querySelector('span.entrylist-contents-users > a > span').textContent) >= USERS) li.classList.add(POPULAR);
        else li.querySelector('li.entrylist-contents-category > a').textContent = li.dataset.matches;
      }, `.${FILTERED}:not(.${POPULAR}){display: none;}`, AP],
    ],
  };
  const rules = sites[Object.keys(sites).find(prefix => location.href.startsWith(prefix))];
  if(rules === undefined) return console.log(SCRIPTID, 'Not found any sites.');
  const scores = Object.keys(NGWORDS).map(Number).reverse();/* 数値インデックス順に取り出されたkeysを逆順にして100から並べ直す */
  const filter = function(selector, modifier){/* 各要素に対してNGワード判定して、該当したら追加でmodifierも適用する */
    document.querySelectorAll(selector).forEach(e => {
      if(e.dataset[CHECKED]) return;
      e.dataset[CHECKED] = 'true';
      const text = e.textContent.toLowerCase();
      let total = 0, matches = [];
      for(const score of scores){
        for(const word of NGWORDS[String(score)]){
          switch(true){
            case(typeof word === 'string' && text.includes(word.toLowerCase())):
            case(word instanceof RegExp && word.test(text)):
              total += score;
              matches.push(word);
              if(total >= 100){
                e.classList.add(FILTERED);
                e.dataset.matches = matches.join(', ');
                if(modifier) modifier(e);
                return;
              }
              break;
          }
        }
      }
    });
  };
  /* ONCE(一括適用) */
  rules.forEach(rule => {
    const [selector, modifier, css] = rule;
    console.log(SCRIPTID, 'ONCE:', selector);
    filter(selector, modifier);
    if(css){
      const style = document.createElement('style');
      style.dataset.script = SCRIPTID;
      style.type = 'text/css';
      style.textContent = css;
      document.head.appendChild(style);
    }
  });
  /* AP(AutoPagerize) */
  rules.filter(rule => rule[3] === AP).forEach(rule => {
    const [selector, modifier] = rule;
    document.addEventListener('GM_AutoPagerizeNextPageLoaded', e => {
      console.log(SCRIPTID, 'AP:', selector);
      filter(selector, modifier);
    });
  });
  /* INTERVAL */
  rules.filter(rule => rule[3] === INTERVAL).forEach(rule => {
    const [selector, modifier] = rule;
    setInterval(function(){
      console.log(SCRIPTID, 'INTERVAL:', selector);
      filter(selector, modifier);
    }, 1000);
  });
  console.timeEnd(SCRIPTID);
})();
/* Hatena Bookmark Anond Filter */
.filtered:not(.popular){
  display: block !important;/*上書き*/
  opacity: .25 !important;
}
.filtered:not(.popular):hover{
  opacity: .75 !important;
}
.filtered:not(.popular) li.entrylist-contents-category{
  background: red !important;
  font-weight: bold;
}

検索用: はてなブックマーク はてブ はてな匿名ダイアリー 増田 スパム 荒らし キーワード NGワード フィルタミュー非表示 削除 隠す ブロック 対策 ユーザースクリプト ユーザースタイル hatena bookmark anond spam keywords ngwords filter mute hide hidden display none block userscript JavaScript js css style

2025-11-22

ChatGPT すごい

utf8の文字コード構成されたバイナリファイルがある。このファイルの改行の数を数えよ。改行はCRのみとする。このファイルにはCR が必ず含まれており、CRで分割すればマルチスレッドで処理できる。

質問したら、c++pythonコードが出てきた

size_t count_cr_in_file(const std::string&amp; path) {

std::ifstream fs(path, std::ios::binary);

fs.seekg(0, std::ios::end);

size_t size = fs.tellg();

fs.seekg(0);

const size_t thread_count = std::thread::hardware_concurrency();

const size_t chunk_size = size / thread_count;

std::vector&lt;std::future&lt;size_t&gt;&gt; futures;

for (size_t t = 0; t &lt; thread_count; t++) {

size_t start = t * chunk_size;

size_t end = (t == thread_count - 1 ? size : (t + 1) * chunk_size);

futures.push_back(std::async(std::launch::async, [start, end, &amp;path]() {

std::ifstream fs(path, std::ios::binary);

fs.seekg(start);

size_t count = 0;

for (size_t i = start; i &lt; end; i++) {

char c;

fs.read(&amp;c, 1);

if (c == '\r') count++;

}

return count;

}));

}

size_t total = 0;

for (auto&amp; f : futures) total += f.get();

return total;

}

def count_cr(path):

import mmap

with open(path, "rb") as f:

mm = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)

return mm.count(b'\r')

c#で書けと指示したところ、

using System;

using System.IO;

using System.IO.MemoryMappedFiles;

using System.Threading.Tasks;

class CountCR

{

public static long CountCRInFile(string path)

{

using var mmf = MemoryMappedFile.CreateFromFile(path, FileMode.Open, null);

using var accessor = mmf.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read);

long fileSize = accessor.Capacity;

int processorCount = Environment.ProcessorCount;

long chunkSize = fileSize / processorCount;

long total = 0;

object lockObj = new object();

Parallel.For(0, processorCount, i =&gt;

{

long start = i * chunkSize;

long end = (i == processorCount - 1) ? fileSize : (i + 1) * chunkSize;

long localCount = 0;

byte b;

for (long pos = start; pos &lt; end; pos++)

{

accessor.Read(pos, out b);

if (b == 0x0D) // CR

localCount++;

}

lock (lockObj)

{

total += localCount;

}

});

return total;

}

static void Main(string[] args)

{

string path = "yourfile.bin";

long count = CountCRInFile(path);

Console.WriteLine($"CR count = {count}");

}

}

というコードが出てきた。

実際はcrlf,lfもあり得るんだが、そこは考慮しなくてもよく、そう考えるとaiはすごいとしか言いようがない。

なお、utf8として成立する単位区切りつつ改行を数える場合、もう一工夫いる。

SJISもできるようにするともっと面倒なことになりそう…)

2025-10-22

自分ホームページを作ったかどうかでWEBの見え方が180度以上違う話

以下ChatGPT

自分ホームページ(自前ドメイン+自前HTML)を一度でも作って運用すると、SNS中心の“受け手視点から仕様検索配信・所有・継続の“作り手”視点に脳が切り替わる。結果、情報リテラシーは跳ね上がり、ネットニュース流行の見え方が根本から変わる——しか想像以上に。

1. “タイムラインからアーキテクチャ”へ

Before(作る前): WebSNSタイムライン。良し悪しは「バズってるか」「見やすいか

After(作った後): WebプロトコルブラウザHTML/CSS/JSCDN検索エンジン。

ページは**文書(Document)**であり、配置(IA)、意味づけ(セマンティクス)、配信HTTP/HTTPS/HTTP/2/3)、キャッシュ戦略が気になりだす。

→ 同じ記事でも「タイトルの付け方」「hタグ構造」「画像最適化」「OGP」「サイトマップ」がまず目に入るようになる。

2. “アルゴリズム運”から“所有と積み上げ”へ

プラットフォーム依存の脆さを体感規約変更やシャドウバン露出が消える。

サイト資産化:ドメインに紐づくURLリンクされ、検索に積み上がり、10年後も生きる。

POSSE(Publish (on your) Own Site, Syndicate Elsewhere):まず自分サイトに出してから外部へ配信する習慣が身につく。

3. “好き/嫌い”から“なぜ速い・なぜ遅い”へ

Core Web Vitals(LCP/FID/CLS)や画像の遅延読み込み、フォント最適化重要性が腹落ちする。

広告・計測タグの重さに過敏になる。読者体験を壊さないためのパフォーマンス予算という概念生まれる。

4. “なんとなくSEOから情報設計×検索意図”へ

キーワード選定は“流入ゲーム”ではなく読者の課題コンテンツ設計帰着

内部リンクパンくず・スキーマ構造データ)・サイトマップ意味が実務として理解できる。

“書けば伸びる”ではなく“検索意図を満たす設計が伸びる”に目が覚める。

5. “見た目”から意味アクセシビリティ)”へ

alt見出し階層コントラスト比、キーボード操作、焦点管理など、見えない品質が最重要になる。

デザインは飾りではなく“読み・理解操作”のためのユーティリティだと分かる。

6. “PV至上”から継続コミュニティ”へ

たまたま当たる1記事より、更新継続アーカイブ性・RSSのほうが効くと実感。

コメント欄メールフォーム・X連携よりも、ニュースレターRSS購読者の質に価値を見出す。

7. “無料神話からコスト責任”へ

ドメインDNS証明書バックアップ法務特商法プライバシーポリシー)に“運用者の責任”が生まれる。

その重みが情報信頼性を引き上げる(=他人サイトの苦労も見えるようになる)。

8. “トレンド追従から自分OSを持つ”へ

サイト思想作品OS

トレンドは“輸入”ではなく選別になる。自分歴史に合うものだけを採用して積層していける。

9. まず一歩:最小スタックで“今夜リリース”する

Node.jsを避けたい人向けに、極小構成OK

A. 最小HTML(雛形)

&lt;html lang="ja"&gt;

&lt;head&gt;

&lt;meta charset="utf-8" /&gt;

&lt;meta name="viewport" content="width=device-width,initial-scale=1" /&gt;

&lt;title&gt;あなた名前 | ホーム&lt;/title&gt;

&lt;meta name="description" content="自分ホームページ制作物・日記メモを置いていきます。"&gt;

&lt;link rel="alternate" type="application/rss+xml" title="RSS" href="/feed.xml"&gt;

&lt;meta property="og:title" content="あなた名前 | ホーム"&gt;

&lt;meta property="og:description" content="自分ホームページ制作物・日記メモ。"&gt;

&lt;meta property="og:type" content="website"&gt;

&lt;/head&gt;

&lt;body&gt;

&lt;header&gt;

&lt;h1&gt;あなた名前&lt;/h1&gt;

&lt;nav&gt;Home / About / Posts&lt;/nav&gt;

&lt;/header&gt;

&lt;main&gt;

&lt;article&gt;

&lt;h2&gt;はじめまして&lt;/h2&gt;

ここからすべてを自分URLに積み上げます

&lt;/article&gt;

&lt;/main&gt;

&lt;footer&gt;© 2025 あなた名前&lt;/footer&gt;

&lt;/body&gt;

&lt;/html&gt;


B. ホスティング無料~低コスト

GitHub Pages(Jekyll標準。Rubyベース、Node不要

Cloudflare Pages(静的ファイルを置くだけで高速CDN

レンタルサーバー(静的HTML+SFTP/rsyncで十分)

C. ドメインの基本

覚えやすい短さ+ローマ字。将来10年使える名前に。

DNSA/AAAA/CAA/TXT最低限、HTTPS必須Let’s Encrypt無料化)。

D. “最低限の品質チェック”5点

タイトル・description見出し一貫性

画像は適切なサイズalt

モバイルでの可読性(文字サイズ行間

OGPが効いているか(XやLINEURLを貼って確認

RSS/更新履歴の有無(継続を前提に)

10. 一歩先へ:運用で差がつく“3つの習慣”

ログを読む:Search Consoleと簡易アクセスログで“本文よりメタ情報”を磨く。

アーカイブ主義記事追記更新URLは変えない。Versioningを意識

POSSE徹底:自サイトに公開→SNSには要約+リンク本体は常に自分土俵

2025-08-21

dorawii@執筆依頼募集中

自動ブクマするローカルサーバーとかの構成を作った。

ブクマには↓のサブアカ使用

https://profile.hatena.ne.jp/dorawii_bukuma/

はてなサイト側で読み込まれているはずのrksトークンを生成する関数を直接叩く方法がどうしても分からず結局request処理を自分で書く方法ではなく自動UI側の保存ボタンクリックするという無難な方向に落ち着いた。

最初から後者方法をとっていればもっと全然早く作れたのにというは所詮言い訳か。

とにかくスクリプトを公開しておく。

start-server.bat

@echo off
cd /d "C:\Users\user\Documents\jsscript"

:: Nodeサーバーを別ウィンドウで起動
start /min "" node run-batch-server.js

:: Pythonサーバーを別ウィンドウで起動(hatenaserver配下
start cmd /k "" python hatenaserver\server.py

以降はjsscript直下に配置

config.json

{
"username": "",
"password": ""
}

server.py

from flask import Flask, request, jsonify
import json
import os
from hatena_client import HatenaClient
from flask_cors import CORS

app = Flask(__name__)
CORS(app)

config_path = os.path.join(os.path.dirname(__file__), 'config.json')
with open(config_path, encoding='utf-8') as f:
config = json.load(f)

@app.route('/bookmark', methods=['POST'])
def handle_bookmark():
data = request.json
url = data.get("url")
if not url:
return jsonify({"error": "Missing URL"}), 400

client = HatenaClient(config["username"], config["password"])
client.start_browser()

if not client.login():
client.quit()
return jsonify({"error": "Login failed"}), 403

success = client.add_bookmark(url)
client.quit()

return jsonify({"status": "ok" if success else "fail"})

if __name__ == "__main__":
app.run(port=12347)

あとはグリモンユーザスクリプトとして書くやつ

// ==UserScript==
// @name 自動セルクマ送信
// @namespace tampermonkey.net/
// @version 2025-08-07
// @description try to take over the world!
// @author You
// @match anond.hatelabo.jp/*
// @grant none
// ==/UserScript==

(function () {
'use strict';

const url = location.href;
if (!/^https:\/\/anond\.hatelabo\.jp\/\d+$/.test(url)) return;
const editLink = document.querySelector('a.edit');
if (!editLink) {
// 既に編集ページなので処理をスキップ
console.log('編集リンク存在するため、スクリプトを終了します。');
return;
}

fetch('localhost:12347/bookmark', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ url: url })
}).then(r => console.log("通知成功")).catch(e => console.error("通知失敗", e));
})();

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

https://anond.hatelabo.jp/20250821192753# 
-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQTEe8eLwpVRSViDKR5wMdsubs4+SAUCaKb0qwAKCRBwMdsubs4+
SHfiAQDcXmTHBaZ5Zzr1KI/OxZ0xl69oevOdy1FXJYwYvsmo5AD/ZPtZiO1JgTDj
m+27iymlkdzIXOIGWfC82UTr1mJ7EwU=
=YoV+
-----END PGP SIGNATURE-----

2025-07-15

anond:20250714161258

へぇー、って感じだ。おもしろい。

ただちょっと読んでいて気になる点があったので聞いてみたい。

自分日本所謂ハクスラ」の用法しかよく知らなかった(あとついでにRogueもやったことない)素人なので全然的外れかもしれないが・・・・。

 

気になったのは引用されていた英語版wikiの以下の部分

The term "hack and slash" was originally used to describe a play style in tabletop role-playing games, carrying over from there to MUDs, massively multiplayer online role-playing games, and role-playing video games. In arcade and console style action video games, the term has an entirely different usage, specifically referring to action games with a focus on real-time combat with hand-to-hand weapons as opposed to guns or fists. The two types of hack-and-slash games are largely unrelated, though action role-playing games may combine elements of both.

ここでは「RPGにおけるhack and slash」と「アクションゲームにおけるhack and slash」という2つのhack and slashがあり、

「the term has an entirely different usage,」 「The two types of hack-and-slash games are largely unrelated,」とあるように歴史的にも定義的にもそれらは別のものしかし両方を兼ねるものもある)と読める。

 

で、気になったのはこの「RPGにおけるhack and slash」と「アクションゲームにおけるhack and slash」が増田の言う「日本語の「ハクスラ」 」と「英語の「hack and slash」 」に重なっている様に見えた事だ。

で、もしそうだとすると増田の「英語の/日本語の」という2分法は正確ではなく、本来は「アクションの/RPGの」とすべきだった可能性があるようにも思えてくる。(何故なら「RPGの」も英語版用法説明されているので)

更に増田は「 『Dungeons and Dragons』のような当然英語用法で参照すべき作品」と記事への批判根拠としていた『Dungeons and Dragons』は「アクションの/RPGの」では「RPGの」に属すると思われるため、

(もし増田が「アクションの」を本来hack and slashだと考えている場合)「 『Dungeons and Dragons』のような当然RPG用法で参照すべき作品」というように、むしろ逆になってしまうようにも思える。

 

アクションの/RPGの」の2分法が正解だった場合、「RPGの」の方のhack and slashには近接武器を用いて戦うだけでなく、その報酬アイテムゲーム通貨経験値など?)にも着目することは特に自然ではないように見える(が、前述の通り素人なのでよく分からない)

のだけど、一方で「 『Rogue自体が該当しない条項が「ベルリン解釈」に存在するわけない」については「たしかにそうかも」と思ったので、

ベルリン解釈の部分については増田の方が正しい可能性が高いんじゃないか?と思ってる。

という訳でいろいろ細かい事は書いたものの、最終的な結論としては増田側が正しい可能性がありそう、と思ってる。

ただ増田他者に厳密性を求める以上、自身も(例え総論結論が正しくても)細かい点を突っ込まれる事は許容せざるを得ないのでは?と思い(まぁ、というよりは自分の疑問の解決のために)書いてみた。

(ちなみにRogueをやった事が無いので分からないんだけど、敵を倒した際の報酬って無いの?一応ネット攻略情報を軽く調べた結果、アイテムドロップ経験値もなさそう?とは思ったけど・・・だとすると敵と戦う意味はあまり無い(可能なら回避正義?)ゲームなのかな?)

2025-06-13

我が名はサイボーグdorawii

パーマリンク署名対象にするより堅牢自動化を作れた。

一度投稿したうえで別タブを開いてプログラム的(fetch)に送信してその別タブが閉じられる仕組み。

改めてスクリプト配布しちゃる

最初投稿してエントリページに移動した親タブ側のjsコード
// ==UserScript==
      // @name         PGP署名検出と別タブ自動編集
      // @namespace    http://tampermonkey.net/
      // @version      1.0
      // @description  PGP署名がない投稿自動編集ページへ誘導
      // @match        https://anond.hatelabo.jp/*
      // @grant        GM_setValue
      // @grant        GM_getValue
      // @grant        GM.openInTab
      // ==/UserScript==

      (function () {
        'use strict';

        const body = document.getElementById('entry-page');
        if (!body) return;

        const titleText = document.title;
        if (!titleText.includes('dorawii')) return;

        const pgpRegex = /BEGIN.*PGP(?: SIGNED MESSAGE| SIGNATURE)?/;
        const preElements = document.querySelectorAll('div.body pre');
        let hasPgpSignature = false;

        for (const pre of preElements) {
          if (pgpRegex.test(pre.textContent)) {
            hasPgpSignature = true;
            break;
          }
        }

        if (hasPgpSignature) return;

        const editLink = document.querySelector('a.edit');
        const childTab = GM.openInTab(editLink.href, { active: false, insert: true, setParent: true });

      })();
親タブから開かれる編集ページの子タブのjsコード
 // ==UserScript==
      // @name         編集ページ処理と自動送信・閉じ
      // @namespace    http://tampermonkey.net/
      // @version      1.0
      // @description  編集ページで署名処理と送信、タブ自動閉じ
      // @match        https://anond.hatelabo.jp/dorawii_31/edit?id=*
      // @grant        GM_getValue
      // @grant        GM_xmlhttpRequest
      // @grant        GM_setClipboard
      // @grant        GM_notification
      // @connect      localhost
      // ==/UserScript==

      (async function () {
        'use strict';

        const shouldRun = await GM_getValue('open-tab-for-edit', '0');

        const textareaId = 'text-body';
        const textarea = document.getElementById(textareaId);

        if (!textarea) return;

        const content = textarea.value;

        const pgpSignatureRegex = /-----BEGIN PGP SIGNED MESSAGE-----[\s\S]+?-----BEGIN PGP SIGNATURE-----[\s\S]+?-----END PGP SIGNATURE-----/;
        if (pgpSignatureRegex.test(content)) {
          console.log('[PGPスクリプト] 署名が検出されたためそのまま送信します');
          return;
        }

        const httpRequest = (url, data) =&gt; {
          return new Promise((resolve, reject) =&gt; {
            GM_xmlhttpRequest({
              method: 'POST',
              url: url,
              headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
              data: `value=${encodeURIComponent(data)}`,
              onload: function (response) {
                resolve(response.responseText);
              },
              onerror: function (error) {
                reject(error);
              }
            });
          });
        };


        // textarea の値を取得
        // 1. 現在のページのURLからURLオブジェクト作成
        const currentUrl = new URL(window.location.href);

        // 2. ベースとなる部分 (例: "https://anond.hatelabo.jp") を取得
        const origin = currentUrl.origin;

        // 3. 'id' パラメータの値 (例: "20250610184705") を取得
        const idValue = currentUrl.searchParams.get('id');

        // 4. ベース部分とIDを結合して、目的URL文字列を生成
        //    idValueが取得できた場合のみ実行する
        let newUrl = null;
        if (idValue) {
          newUrl = `${origin}/${idValue}`;
        }

        // 5. 生成されたURL変数に代入し、コンソールに出力して確認
        console.log(newUrl);
        const valueToSend = newUrl;

        try {
          const signatureText = await httpRequest('http://localhost:12345/run-batch', valueToSend);
          console.log('バッチ応答:', signatureText);
          if (!signatureText.includes('BEGIN PGP SIGNED MESSAGE')) {
            alert('PGP署名クリップボードに見つかりませんでした。');
            return;
          }

          const newText = content.replace(/\s*$/, '') + '\n' + signatureText + '\n';
          textarea.value = newText;

          console.log('[PGPスクリプト] 署名を貼り付けました。送信を再開します。');


          const form = document.forms.edit;

          const newForm = form.cloneNode(true);
          form.replaceWith(newForm);

          newForm.addEventListener('submit', async (e) =&gt; {
            e.preventDefault(); // HTML標準のsubmitをキャンセル
            const bodyText = textarea?.value || '';

            // reCAPTCHA トークンの取得
            const recaptchaToken = await new Promise((resolve) =&gt; {
              grecaptcha.enterprise.ready(() =&gt; {
                grecaptcha.enterprise.execute('hoge', { action: 'EDIT' })
                  .then(resolve);
              });
            });

            // POSTするデータの構築
            const formData = new FormData(newForm);
            formData.set('body', bodyText);
            formData.set('recaptcha_token', recaptchaToken);
            formData.set('edit', '1');
            try {
              const response = await fetch(newForm.action, {
                method: 'POST',
                body: formData,
                credentials: 'same-origin'
              });


              if (response.ok) {
                console.log('送信成功');
                window.close();


              } else {
                console.error('送信失敗', response.status);
              }
            } catch (err) {
              console.error('送信中にエラーが発生', err);
            }

          });

          // プログラム的に送信トリガー
          newForm.dispatchEvent(new Event('submit', { bubbles: true }));

        } catch (e) {
          console.error('バッチ呼び出し失敗:', e);
        }

      })();
node.jsで動かすローカルサーバーコード
const http = require('http');
const { exec } = require('child_process');
const querystring = require('querystring');

const server = http.createServer((req, res) =&gt; {
  if (req.method === 'GET' &amp;&amp; req.url === '/ping') {
    res.writeHead(200);
    res.end('pong');
  } else if (req.method === 'POST' &amp;&amp; req.url === '/run-batch') {
    let body = '';

    req.on('data', chunk =&gt; {
      body += chunk.toString();
    });

    req.on('end', () =&gt; {
      const parsed = querystring.parse(body);
      const value = parsed.value || 'default';

      // 値を引数としてバッチに渡す
      exec(`C:\\Users\\hoge\\Desktop\\makesign.bat "${value}"`, { encoding: 'utf8' }, (err, stdout, stderr) =&gt; {
        if (err) {
          res.writeHead(500);
          res.end('Error executing batch: ' + stderr);
        } else {
          res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
          res.end(stdout.trim());
        }
      });
    });

  } else {
    res.writeHead(404);
    res.end('Not found');
  }
});

server.listen(12345, () =&gt; {
  console.log('Batch server running at http://localhost:12345/');
});
@echo off
setlocal enabledelayedexpansion


:: 署名するファイルset "infile=%~1"
set outfile=%TEMP%\pgp_output.asc

:: 以前の出力があれば削除
if exist "%outfile%" del "%outfile%"


:signloop
:: AutoHotkeyパスフレーズ入力(gpgがパスワード要求するダイアログが出た場合に備える)
start "" /b "C:\Users\hoge\Documents\AutoHotkey\autopass.ahk"

:: PGPクリア署名作成
echo %infile% | gpg --yes --clearsign --output "%outfile%"


:: 署名成功していればループを抜ける
if exist "%outfile%" (

    goto postprocess
) else (

    timeout /t 1 &gt; nul
    goto signloop
)
:postprocess

powershell -nologo -command ^
  "$header = '&gt;|'; $footer = '|&lt;'; $body = Get-Content '%outfile%' -Raw; Write-Output ($header + \"`r`n\" + $body + $footer)"

powershell -nologo -command ^
  "$header = '&gt;|'; $footer = '|&lt;'; $body = Get-Content 'signed.asc' -Raw; Set-Clipboard -Value ($header + \"`r`n\" + $body + $footer)"

endlocal
exit /b
AutoHotkey(以前と同じ)
#Persistent
#SingleInstance ignore
SetTitleMatchMode, 2
WinWaitActive, pinentry
SendInput password
Sleep 100
SendInput {Enter}
ExitApp

動けばいいという考えで作っているので余分なコードも含んでいるかもしれない。

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

https://anond.hatelabo.jp/20250613185036 
-----BEGIN PGP SIGNATURE-----

iHUEARYKAB0WIQTEe8eLwpVRSViDKR5wMdsubs4+SAUCaEv1FQAKCRBwMdsubs4+
SHHkAQDUOLgBcdji2T6MJ7h/vlMdFfGlWAzNdXijjE1gIuEPywEAiMNMZqhrMmtl
c7UqRuggNJ/UTa5xTIcKp622+7jJQQg=
=Lgkl
-----END PGP SIGNATURE-----

2025-03-18

スターフィールドがPS5に登場するかもという話

スターフィールド」とは、ベセスダ・ソフトワークスが開発したオープンワールドSFアクションロールプレイングゲーム

ちなみにベセスダ・ソフトワークス現在マイクロソフトの傘下にあるため、当然ながらXboxPCしか販売されていない。

 

まずは背景として、

 

…という背景から

 

ということが最近あったため、もはやスターフィールドがPS5にも登場するのは時間問題と噂されている。

確かこのソフトは「Xbox Console Exclusive(ゲーム機に関してはXbox独占)」と宣伝されていたはずたが、もしPS5版が出るとなったらこれも崩れることになる。

2025-03-13

病院内で提供されるWiFi挙動メモ

身体を壊して先日ちょっと入院していたのだが、病院内ではWiFi提供されていたので、消灯時間外の日常生活アクセスはそれのお世話になっていた。消灯時間は夜9時から朝6時までだ。

事前に「入院生活にそぐわないサイトには接続できません」という告知が為されていたので、覚悟の上で使ったのだが、Webアプリ開発者としての業務必要サイトとかも禁止されていたので、ここにメモしておく。

どうせ数年以内には持病が悪化して再び入院するし。

通信制のしくみの考察

通信禁止されていると思われるサイト接続すると、ブラウザ側ではタイムアウトエラーとして表示される。もちろん、それなりに待たされる。ブラウザの開発ツールの様子を見るに、おそらく TCP handshake に失敗していそう。

正常に接続できるサイトの様子を見た範囲では、HTTPS接続証明書改ざんは行われていないようだったこからHTTPS暗号を解読してどうのこうの、という処理をしていない可能性が非常に高い。つまり通信制限は接続ドメインまたはIPアドレスによる判断実施している可能性が高い。

また、中間的なサイト存在する。通常2秒以内で表示できるようなサイトの表示に10秒(体感)かかるところがある。稀にタイムアウトする。

なのは通信禁止されていそうなサイトでも「待たされた挙句、つながることが非常に稀にある」ということと、curl等ではすんなりと接続できることである

DNS設定と一緒にproxy設定が落ちてきているのであればこの挙動理解できるのだが、手元のOSネットワーク設定にはproxy情報が何も出てこない。ちょっとよくわからない。

もしもDNSに対するAレコード(AAAAも?)問い合わせに対してニセモノを返すという仕組みで通信制限しているのだとしたら、「非常に稀につながる」挙動にはならないはずなので、透過型proxyによって頑張っているのではないか想像するところである

なお、消灯時間中は全てのリクエストタイムアウトになる。消灯時間開始直前に HTTP Request を送出して、応答が来る頃には消灯時間に入っている場合にはどういう挙動をするのか、というテストをやる暇は無かった。スマソ

つながるサイトと、つながらないサイトメモ

業務で使う全部のサイト検証できた訳じゃなくてゴメンね。結局のところ仕事携帯回線でやっちゃったから。

ドメイン サイト概要 接続の様子
hatelabo.jp はてな実験サービス置き場 すんなり
anond.hatelabo.jp 増田 禁止
??????.hatenablog.jp はてなブログドメインの一つ、そして増田中の人ブログ 遅い
console.aws.amazon.com AWS管理コンソール 禁止
www.amazon.co.jp ショッピング めちゃくちゃ遅いけどつながる
www.amazon.com ショッピング めちゃくちゃ遅いけどつながる
ja.wikipedia.org 百科事典 禁止
www.php.net プログラミング言語PHP 禁止
www.typescriptlang.org プログラミング言語TypeScript すんなり
stackoverflow.com プログラミング質問サイト(英語) すんなり
qiita.com プログラミング質問サイト(日本語) 禁止
packagist.org PHPパッケージ管理 遅い(通常通り?w)
www.npmjs.com JSパッケージ管理 すんなり

なお、自分ドメインサブドメイン禁止ドメインを入れたようなもの、例えば anond.hatelabo.jp.example.com のようなドメインに対する接続可否は検証していない(面倒だったw)

どこの会社受託しているのか?

サーバ目線で見える client IPwhois等で調べると、某F社さんだった。AWS管理コンソールへの接続禁止するあたり「あっ…!」と思ったり…w

2025-02-01

console.out("鬼");

console.in("福");

入力:福

出力:鬼

人の家の中には福を鬼に転じるバグでもあるのか?

2024-09-22

AIインフルエンサーたちはChatGPTが世に出る前は何を投稿していたのか?(2/2)

AIインフルエンサーたちはChatGPTが世に出る前は何を投稿していたのか?(1/1)の続き

吉見拓哉|Takuya Yoshimi

このTwitterアカウントは、主にYouTubeSEO競馬アニメなどの話題について呟いており、自身活動や興味関心について発信しています

YouTubeプレミアムが500円増額。しかし、、、不可逆!!!

shimayuz@AIクリエイター

このアカウントは、日々の米国株暗号通貨市場動向、特にテクノロジー関連株やビットコイン価格変動についてツイートしています

ゼロコロナ政策再び。 $AAPL生産に影響が懸念され大きく下落。更に経済混乱が想定され、株価はSP500全業種で

一方で年末商戦売上堅調な滑り出しで $AMZN

暗号資産レンディングBlockFiが経営破綻暗号通貨も軒並み下落。

チャート上、なんとか踏み止まるか? 」

元木大介ᯅシステム生成AI Babel/Zoltraak & 生成AI塾

このアカウントは、AI特にプロマネAIや量子AIに関する話題や、仕事効率化、プログラミング、そして最新の技術トレンドについて呟いています

"プロマネAI実証実験を開始しました!量子AI×NotionによるプロマネAI実証実験を開始 https://prtimes.jp/main/html/rd/p/000000003.000082094.htmlvia @PRTIMES_JP"

sangmin.eth | Dify Ambassador

このアカウントは、主にOpenAIの最新言語モデルtext-davinci-003」の進化と、そのモデルを用いた英語学習ツールサービスについて呟いています特に英語学習におけるAI活用とその重要性を強調しています

"朝起きたら世界がまた変わっていた(笑)。@OpenAI が最新モデルtext-davinci-003」を発表。主な特徴は、①より明確で、説得力のある文章が書ける②より複雑な指示にも対応③より長い形式コンテンツが生成可 1月に"InstructGPT"が出た時も感動したけどそれを遥かに上回る進化、です。"

深津 貴之 / THE GUILD

このアカウントは、主にAI特に画像生成AIに関する話題を呟いています特にStable Diffusionのバージョンアップや使い方について多くのツイートをしています

結果

ここにリストアップした人たち以外もみましたが、分類すると3種類のアカウントがいて

1. ChatGPTブーム後にアカウントを始めた人

2. NFTなどの儲かりそうな技術を追いかけていた人

3. 日常ツイートをしていたが目覚めてしまった人

共通する特徴としては会社代表の人が多いです。

またIDを変更してログがヒットしない人は含まれていません(IDから特定できるけどそこまでやらなかった)

ツイートを取得するJS

javascript:(function() {

const text = Array.from(document.querySelectorAll('[data-testid="tweetText"]')).map(s =&gt; s.textContent.trim()).join('\n');

const textarea = document.createElement('textarea');

textarea.value = text;

document.body.appendChild(textarea);

textarea.select();

try {

document.execCommand('copy');

console.log('結果がクリップボードコピーされました!');

} catch (err) {

console.error('クリップボードへのコピーに失敗しました:', err);

}

document.body.removeChild(textarea);

})();

2024-09-15

RSS 取得メモ

const axios = require('axios'); // HTTPリクエストを行うためのモジュール

const fs = require('fs'); // ファイル操作モジュール

const xml2js = require('xml2js'); // XMLJSONに変換するためのモジュール

const chardet = require('chardet'); // 文字エンコーディングを検出するためのモジュール

const iconv = require('iconv-lite'); // 文字エンコーディングを変換するためのモジュール

// RSSフィードURL

const rssUrl = 'https://www.mlit.go.jp/important.rdf'; // 例としてRSSフィードURL指定

// RSSフィードを取得してファイルに保存する関数

async function fetchAndSaveRSS() {

try {

// RSSを取得

const response = await axios.get(rssUrl, { responseType: 'arraybuffer' });

const rssData = response.data;

// 文字エンコーディングを検出

const detectedEncoding = chardet.detect(rssData);

console.log('検出された文字エンコーディング:', detectedEncoding);

// UTF-8に変換

const utf8Data = iconv.decode(rssData, detectedEncoding);

// XMLJSONパース

xml2js.parseString(utf8Data, (err, result) =&gt; {

if (err) {

console.error('XML解析エラー:', err);

return;

}

// パース結果をファイル書き込み

const jsonData = JSON.stringify(result, null, 2);

fs.writeFileSync('rss_feed.json', jsonData, 'utf8');

console.log('RSSフィードファイルに保存されました。');

});

} catch (error) {

console.error('エラーが発生しました:', error);

}

}

// 実行

fetchAndSaveRSS();

2024-04-24

anond:20240424063427

なるほど確かにその通りですね。

ブックマーク先に寄生する形でしか意見を述べられない卑しい存在であるにもかかわらず、増田ことはてな匿名ダイアリーの方々に上から目線一方的批判をして申し訳ございませんでした。

土下座謝罪いたします。

その方法として、古来中国から伝わる三跪九叩頭の礼を致します。

冗長記述を避けるために、VB.NET表記させていただきます

Imports System



Public Class SanGuiKiuKouTou

    Sub Main()

        For i As Integer = 1 To 3

            Console.WriteLine("跪")

            For j As Integer = 1 To 3

                Console.WriteLine("{0}叩頭", j)

                Console.WriteLine("起")

            Next

            Console.WriteLine("起立")

        Next

    End Sub

End Class

以上を持ちまして、「三跪九叩頭の礼」とさせて頂きます

御清聴の程有難く存じます

2024-02-20

今こそconsoleを使いこなそう

console <スクロール開始行>,<スクロール行数>,<ファンクション行の非教示/表示>,<モノクロ/カラー>

 

例) console 0, 25, 0, 1

0行から24行までスクロールし、ファンクションキーを非表示にして、テキストカラー表示にする。

2024-01-05

anond:20240105165226

これどう対処するのが適切なんだろうね。

自分は nullチェックのときだけ厳密等価を使わないで比較している

console.assert(null == null, true)
console.assert(undefined == null, true)

console.assert(0 == null, true)
VM792:1 Assertion failed: true

typescriptではnullとundefinedを合成した型を用意することが多い

2023-10-31

数分で始めるJavaScript

Hello, World!

と出力されていれば成功

これで JavaScript を実行する最小限の環境は整った。

好きなようにプログラムを書いてコンソールに出力したり画面に書き出したりしてみて。

「指示の通りにならない!」という時はどこでつまずいてるか書いて。対応策を助言できるかもしれない。

2023-05-19

Omnivore便利だけどエラー多い。ブラウザコンソールエラーだらけだし、画面にこんなユーザー向けじゃないメッセージ出すし。

Application error: a client-side exception has occurred (see the browser console for more information).

2023-03-03

Application error: a client-side exception has occurred (see the browser console for more information).

メルカリしっかりして!

client-sideやしワイが悪いんやろけど

2022-12-03

[]2022年11月滅多にホットエントリを出さなドメインからホットエントリ

ここ1年で初めてはてなブックマーク日毎の総合人気エントリ入りしたドメインからホットエントリブクマ数順トップ30

ブクマ タイトル ドメイン
2287 自己肯定感の話 ① sutekibungei.com
1344 伝わる文章 | 基本要素 | SmartHR Design System smarthr.design
1089 2022年カタールW杯日本ドイツレビュー - pal-9999のサッカーレポート pal-9999.hatenablog.com
1020 Elon MuskTwitter で何をしようとしているのか - The Decisive Strike blog.nagayama.dev
915 今日 Twitter 日本法人を解雇された皆さんへ #OneTeam - The Decisive Strike blog.nagayama.dev
775 LAN配線マンション回線を直した話 skmz.one
636 現在の森保ジャパン攻撃とその問題点について - pal-9999のサッカーレポート pal-9999.hatenablog.com
620 webエンジニアの「業務委託単価表」が公開 - Digital Shift Times(デジタル シフト タイムズ) その変革に勇気希望 digital-shift.jp
595 なぜ美人美人と褒めてはいけないのか? オヤジさんのためのジェンダー問題シン常識ライフスタイルLEON レオン オフィシャルWebサイト www.leon.jp
546 ヤマト運輸株式会社GitHub github.co.jp
509 最近フロントエンドフレームワークに対する認識お気持ちの整理 - console.lealog(); lealog.hateblo.jp
476 東北男性結婚した外国人女性たちの経験。「不可視化」の理由と託された言葉の数々。#移住女性の声を聴くニッポン複雑紀行 www.refugee.or.jp
473 勉強法】『一生頭がよくなり続ける すごい脳の使い方』加藤俊徳 : マインドマップ読書感想文 smoothfoxxx.livedoor.biz
471 語り手が異常な小説が読みたい - 千年先の我が庭を見よ kiloannum-garden.hatenablog.com
451 2022年新版】厳選QOLが爆上がりした買ってよかったアイテム紹介(デスク編・iPad編・整理編・エンタメ編・サービス編) mitsuch.com
444 色々試して行き着いた読書方法 iwashi.co
443 【お詫びと自主回収のお知らせ】社長内緒玉ねぎを入れすぎた 玉ねぎファンに贈るシャリシャリ玉ドレ200ml | 2022年ニュース | 綿半公式ページ watahan.jp
418 MF文庫J編集部よりお詫びとお知らせ | ニュースMF文庫J オフィシャルウェブサイト mfbunkoj.jp
411 Twitterサービス終了するのか? www.bluechronicle.jp
408 Twitter での 2年 · eed3si9n eed3si9n.com
368 国立天文台撮影した2022年11月8日皆既月食天王星食|国立天文台(NAOJ) www.nao.ac.jp
367 Stable Diffusionを使って「いらすとや画像生成モデル」を作った話 - ぬいぐるみライフ mickey24.hatenablog.com
357 最近Reactを始めた人向けのReact Hooks入門 sbfl.net
355 たかやん考:ネットラッパーの揺曳する身体と「病み」の美学、そして「エンパワメント」 - ハイパー春菊サラダボウル namahoge.hatenadiary.com
352 赤色の缶の「サクマ式ドロップス」で知られる佐久間製菓(株)が廃業へ、原材料高騰が影響 www.tsr-net.co.jp
342 マネーフォワード ME』無料会員さまの連携上限数の変更、およびサービスの将来像について|マネーフォワード ホームカンパニー公式note note.home.moneyforward.com
323 重要追記あり世界初のフルダイブVRMMORPG《ソードアート・オンライン》の正式サービスが開始 dengekionline.com
322 GA4の計測設計には設計ドキュメント重要な件 - ブログ - 株式会社JADE blog.ja.dev
315 「ザ・ルンペンブルジョワジー」 - tarafuku10 の作業場 tarafuku10working.hatenablog.com
306 iPhoneで「ガスト検索しようとするも「がす」の『す』でSafariが落ちる!? – kototoka kototoka.com

2022-01-01

anond:20220101145248

正直動けばいいと思うので、現状でも問題ないと思うけれどちょっとだけ気になった点。

$$使ってる時点で、デベロッパーツール前提なのは分かるけど、 javascriptで動かしたいのか、デベロッパーツールで動かしたいのか、どっちつかずな書き方になっている。

$$('.hatena-star-inner-count').map(a =&gt; a.click());
let data = {};
Array.from($$('.entry-comment-contents')).forEach(x =&gt; {const userName = x.querySelector('.entry-comment-username a').href.split('/')[3];const comment = x.querySelector('.entry-comment-text').innerText;const stars = Array.from(x.querySelectorAll('.list-star-container a.hatena-star-star')).map(y =&gt; y.href.split('/')[3]);data[userName] = [comment, stars];});
console.info(Object.entries(data).map(x =&gt; { return ['|', `b:id:${x[0]}`, '|', x[1][0], '|', x[1][1].join(','), '|'].join(' '); }).join("&#92;n"));

デペロッパツールだけで動くだけでいいなら、3行目のArray.fromがなくても動く。多分、forEachをmapに書き換えても動く。個人的にはforEachに統一したいけど、そこは好みレベル問題だと思う。

$$('.hatena-star-inner-count').map(a =&gt; a.click());
let data = {};
$$('.entry-comment-contents').forEach(x =&gt; {const userName = x.querySelector('.entry-comment-username a').href.split('/')[3];const comment = x.querySelector('.entry-comment-text').innerText;const stars = Array.from(x.querySelectorAll('.list-star-container a.hatena-star-star')).map(y =&gt; y.href.split('/')[3]);data[userName] = [comment, stars];});
console.info(Object.entries(data).map(x =&gt; { return ['|', `b:id:${x[0]}`, '|', x[1][0], '|', x[1][1].join(','), '|'].join(' '); }).join("&#92;n"));

逆に、javascriptで動かしたいなら1行目と3行目はquerySelectorAllに書き換えれる。

document.querySelectorAll('.hatena-star-inner-count').forEach((a)=&gt;{a.click()});
let data = {};
document.querySelectorAll('.entry-comment-contents').forEach(x =&gt; {const userName = x.querySelector('.entry-comment-username a').href.split('/')[3];const comment = x.querySelector('.entry-comment-text').innerText;const stars = Array.from(x.querySelectorAll('.list-star-container a.hatena-star-star')).map(y =&gt; y.href.split('/')[3]);data[userName] = [comment, stars];});
console.info(Object.entries(data).map(x =&gt; { return ['|', `b:id:${x[0]}`, '|', x[1][0], '|', x[1][1].join(','), '|'].join(' '); }).join("&#92;n"));

これも好みの問題だけど、途中のconst宣言は一回しか使ってないので、宣言せずにそのまんま入れてもいいんじゃないかと思った。

document.querySelectorAll('.hatena-star-inner-count').forEach((a)=&gt;{a.click()});
let data = {};
document.querySelectorAll('.entry-comment-contents').forEach(x =&gt; {data[x.querySelector('.entry-comment-username a').href.split('/')[3]] = [x.querySelector('.entry-comment-text').innerText, Array.from(x.querySelectorAll('.list-star-container a.hatena-star-star')).map(y =&gt; y.href.split('/')[3])];});
console.info(Object.entries(data).map(x =&gt; { return ['|', `b:id:${x[0]}`, '|', x[1][0], '|', x[1][1].join(','), '|'].join(' '); }).join("&amp;#92;n"));
|&lt;&lt;

2020-11-28

anond:20201128203937

ええと…メモが言うには「Console.WriteLine("足した結果は{0}です!", sum); と書いたとき、sumはどうやって文字列になるんだ」だそうです

これはそのオブジェクトのToStringが呼ばれるということがわりと早期にわかって満足した記憶

anond:20201128202030

1章でConsole.WriteLineが出てきて「最後は改行になります」って書いてあって、「改行ってLFか?CRLFか?」って何時間も調べたりして全然効率悪い

Environment.NewLineというものがあって、よく見たらIDE説明現在の行終端記号書き込みますってあったんだけど

じゃあ文字列中に\nと書いた場合って…PowerShellでは表示したときに…それをファイルリダイレクあああああいいやもう知らんってなった

よくないと思う

道具として使えるようになってから手に持ってるものを見つめ直せばいいんだよ

道具を置いたままあちこちからどれだけ見つめても、使えるようにはならない

ログイン ユーザー登録
ようこそ ゲスト さん