メインコンテンツへスキップ

Ruby

radiko APIを使って都道府県ごとのラジオ局一覧を出力する

require 'net/http' require 'uri' require 'rexml/document' prefecture_names = { "1" => "北海道", "2" => "青森県", "3" => "岩手県", "4" => "宮城県", "5" => "秋田県", "6" => "山形県", "7" => "福島県", "8" => "茨城県", "9" => "栃木県", "10" => "群馬県", "11" => "埼玉県", "12" => "千葉県", "13" => "東京都", "14" => "神奈川県", "15" => "新潟県", "16" => "富山県", "17" => "石川県", "18" => "福井県", "19" => "山梨県", "20" => "長野県", "21" => "岐阜県", "22" => "静岡県", "23" => "愛知県", "24" => "三重県", "25" => "滋賀県", "26" => "京都府", "27" => "大阪府", "28" => "兵庫県", "29" => "奈良県", "30" => "和歌山県", "31" => "鳥取県", "32" => "島根県", "33" => "岡山県", "34" => "広島県", "35" => "山口県", "36" => "徳島県", "37" => "香川県", "38" => "愛媛県", "39" => "高知県", "40" => "福岡県", "41" => "佐賀県", "42" => "長崎県", "43" => "熊本県", "44" => "大分県", "45" => "宮崎県", "46" => "鹿児島県", "47" => "沖縄県" } prefectures = (1..47).map(&:to_s) prefectures.each do |pref_code| url = "https://radiko.jp/v2/station/list/JP#{pref_code}.xml" uri = URI.parse(url) begin response = Net::HTTP.get_response(uri) if response.is_a?(Net::HTTPSuccess) document = REXML::Document.new(response.body) puts "## #{prefecture_names[pref_code]}(#{pref_code})" document.elements.each('stations/station') do |station| station_name = station.elements['name'].text station_id = station.elements['id'].text puts "- #{station_name}(#{station_id})" end puts "" else puts "Failed to retrieve data for prefecture code #{pref_code}" end rescue => e puts "Error: #{e.message} for prefecture code #{pref_code}" end end 北海道(1) # HBCラジオ(HBC) STVラジオ(STV) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) AIR-G’(FM北海道)(AIR-G) FM NORTH WAVE(NORTHWAVE) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(札幌)(JOIK) NHK-FM(東京)(JOAK-FM) 青森県(2) # RAB青森放送(RAB) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) エフエム青森(AFB) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(仙台)(JOHK) NHK-FM(東京)(JOAK-FM) 岩手県(3) # IBCラジオ(IBC) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) エフエム岩手(FMI) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(仙台)(JOHK) NHK-FM(東京)(JOAK-FM) 宮城県(4) # TBCラジオ(TBC) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) Date fm エフエム仙台(DATEFM) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(仙台)(JOHK) NHK-FM(東京)(JOAK-FM) 秋田県(5) # ABSラジオ(ABS) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) エフエム秋田(AFM) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(仙台)(JOHK) NHK-FM(東京)(JOAK-FM) 山形県(6) # YBC山形放送(YBC) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) Rhythm Station エフエム山形(RFM) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(仙台)(JOHK) NHK-FM(東京)(JOAK-FM) 福島県(7) # RFCラジオ福島(RFC) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) ふくしまFM(FMF) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(仙台)(JOHK) NHK-FM(東京)(JOAK-FM) 茨城県(8) # TBSラジオ(TBS) 文化放送(QRR) ニッポン放送(LFR) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) interfm(INT) TOKYO FM(FMT) J-WAVE(FMJ) LuckyFM 茨城放送(IBS) ラジオ日本(JORF) BAYFM78(BAYFM78) NACK5(NACK5) FMヨコハマ(YFM) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(東京)(JOAK) NHK-FM(東京)(JOAK-FM) 栃木県(9) # TBSラジオ(TBS) 文化放送(QRR) ニッポン放送(LFR) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) interfm(INT) TOKYO FM(FMT) J-WAVE(FMJ) CRT栃木放送(CRT) RADIO BERRY(RADIOBERRY) ラジオ日本(JORF) BAYFM78(BAYFM78) NACK5(NACK5) FMヨコハマ(YFM) LuckyFM 茨城放送(IBS) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(東京)(JOAK) NHK-FM(東京)(JOAK-FM) 群馬県(10) # TBSラジオ(TBS) 文化放送(QRR) ニッポン放送(LFR) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) interfm(INT) TOKYO FM(FMT) J-WAVE(FMJ) FM GUNMA(FMGUNMA) ラジオ日本(JORF) BAYFM78(BAYFM78) NACK5(NACK5) FMヨコハマ(YFM) LuckyFM 茨城放送(IBS) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(東京)(JOAK) NHK-FM(東京)(JOAK-FM) 埼玉県(11) # TBSラジオ(TBS) 文化放送(QRR) ニッポン放送(LFR) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) interfm(INT) TOKYO FM(FMT) J-WAVE(FMJ) ラジオ日本(JORF) BAYFM78(BAYFM78) NACK5(NACK5) FMヨコハマ(YFM) LuckyFM 茨城放送(IBS) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(東京)(JOAK) NHK-FM(東京)(JOAK-FM) 千葉県(12) # TBSラジオ(TBS) 文化放送(QRR) ニッポン放送(LFR) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) interfm(INT) TOKYO FM(FMT) J-WAVE(FMJ) ラジオ日本(JORF) BAYFM78(BAYFM78) NACK5(NACK5) FMヨコハマ(YFM) LuckyFM 茨城放送(IBS) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(東京)(JOAK) NHK-FM(東京)(JOAK-FM) 東京都(13) # TBSラジオ(TBS) 文化放送(QRR) ニッポン放送(LFR) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) interfm(INT) TOKYO FM(FMT) J-WAVE(FMJ) ラジオ日本(JORF) BAYFM78(BAYFM78) NACK5(NACK5) FMヨコハマ(YFM) LuckyFM 茨城放送(IBS) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(東京)(JOAK) NHK-FM(東京)(JOAK-FM) 神奈川県(14) # TBSラジオ(TBS) 文化放送(QRR) ニッポン放送(LFR) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) interfm(INT) TOKYO FM(FMT) J-WAVE(FMJ) ラジオ日本(JORF) BAYFM78(BAYFM78) NACK5(NACK5) FMヨコハマ(YFM) LuckyFM 茨城放送(IBS) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(東京)(JOAK) NHK-FM(東京)(JOAK-FM) 新潟県(15) # BSNラジオ(BSN) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) FM NIIGATA(FMNIIGATA) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(東京)(JOAK) NHK-FM(東京)(JOAK-FM) 富山県(16) # KNBラジオ(KNB) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) FMとやま(FMTOYAMA) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(名古屋)(JOCK) NHK-FM(東京)(JOAK-FM) 石川県(17) # MROラジオ(MRO) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) エフエム石川(HELLOFIVE) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(名古屋)(JOCK) NHK-FM(東京)(JOAK-FM) 福井県(18) # FBCラジオ(FBC) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) FM福井(FMFUKUI) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(名古屋)(JOCK) NHK-FM(東京)(JOAK-FM) 山梨県(19) # YBSラジオ(YBS) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) FM FUJI(FM-FUJI) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(東京)(JOAK) NHK-FM(東京)(JOAK-FM) 長野県(20) # SBCラジオ(SBC) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) FM長野(FMN) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(東京)(JOAK) NHK-FM(東京)(JOAK-FM) 岐阜県(21) # CBCラジオ(CBC) TOKAI RADIO(TOKAIRADIO) ぎふチャン(GBS) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) ZIP-FM(ZIP-FM) FM GIFU(FMGIFU) FM AICHI(FMAICHI) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(名古屋)(JOCK) NHK-FM(東京)(JOAK-FM) 静岡県(22) # SBSラジオ(SBS) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) K-MIX(K-MIX) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(名古屋)(JOCK) NHK-FM(東京)(JOAK-FM) 愛知県(23) # CBCラジオ(CBC) TOKAI RADIO(TOKAIRADIO) ぎふチャン(GBS) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) ZIP-FM(ZIP-FM) FM AICHI(FMAICHI) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(名古屋)(JOCK) NHK-FM(東京)(JOAK-FM) 三重県(24) # CBCラジオ(CBC) TOKAI RADIO(TOKAIRADIO) ぎふチャン(GBS) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) ZIP-FM(ZIP-FM) レディオキューブ FM三重(FMMIE) FM AICHI(FMAICHI) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(名古屋)(JOCK) NHK-FM(東京)(JOAK-FM) 滋賀県(25) # ABCラジオ(ABC) MBSラジオ(MBS) OBCラジオ大阪(OBC) FM COCOLO(CCL) FM802(802) FM大阪(FMO) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) KBS京都ラジオ(KBS) Kiss FM KOBE(KISSFMKOBE) e-radio FM滋賀(E-RADIO) ラジオ関西(CRK) α-STATION FM KYOTO(ALPHA-STATION) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(大阪)(JOBK) NHK-FM(東京)(JOAK-FM) 京都府(26) # ABCラジオ(ABC) MBSラジオ(MBS) OBCラジオ大阪(OBC) FM COCOLO(CCL) FM802(802) FM大阪(FMO) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) KBS京都ラジオ(KBS) Kiss FM KOBE(KISSFMKOBE) α-STATION FM KYOTO(ALPHA-STATION) ラジオ関西(CRK) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(大阪)(JOBK) NHK-FM(東京)(JOAK-FM) 大阪府(27) # ABCラジオ(ABC) MBSラジオ(MBS) OBCラジオ大阪(OBC) FM COCOLO(CCL) FM802(802) FM大阪(FMO) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) Kiss FM KOBE(KISSFMKOBE) ラジオ関西(CRK) KBS京都ラジオ(KBS) α-STATION FM KYOTO(ALPHA-STATION) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(大阪)(JOBK) NHK-FM(東京)(JOAK-FM) 兵庫県(28) # ABCラジオ(ABC) MBSラジオ(MBS) OBCラジオ大阪(OBC) FM COCOLO(CCL) FM802(802) FM大阪(FMO) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) ラジオ関西(CRK) Kiss FM KOBE(KISSFMKOBE) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(大阪)(JOBK) NHK-FM(東京)(JOAK-FM) 奈良県(29) # ABCラジオ(ABC) MBSラジオ(MBS) OBCラジオ大阪(OBC) FM COCOLO(CCL) FM802(802) FM大阪(FMO) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) Kiss FM KOBE(KISSFMKOBE) ラジオ関西(CRK) α-STATION FM KYOTO(ALPHA-STATION) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(大阪)(JOBK) NHK-FM(東京)(JOAK-FM) 和歌山県(30) # ABCラジオ(ABC) MBSラジオ(MBS) OBCラジオ大阪(OBC) FM COCOLO(CCL) FM802(802) FM大阪(FMO) wbs和歌山放送(WBS) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) Kiss FM KOBE(KISSFMKOBE) ラジオ関西(CRK) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(大阪)(JOBK) NHK-FM(東京)(JOAK-FM) 鳥取県(31) # BSSラジオ(BSS) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) エフエム山陰(FM-SANIN) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(広島)(JOFK) NHK-FM(東京)(JOAK-FM) 島根県(32) # BSSラジオ(BSS) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) エフエム山陰(FM-SANIN) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(広島)(JOFK) NHK-FM(東京)(JOAK-FM) 岡山県(33) # RSKラジオ(RSK) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) FM岡山(FM-OKAYAMA) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(広島)(JOFK) NHK-FM(東京)(JOAK-FM) 広島県(34) # RCCラジオ(RCC) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) 広島FM(HFM) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(広島)(JOFK) NHK-FM(東京)(JOAK-FM) 山口県(35) # KRY山口放送(KRY) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) エフエム山口(FMY) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(広島)(JOFK) NHK-FM(東京)(JOAK-FM) 徳島県(36) # JRT四国放送(JRT) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) FM徳島(FM807) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(松山)(JOZK) NHK-FM(東京)(JOAK-FM) 香川県(37) # RNC西日本放送(RNC) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) エフエム香川(FMKAGAWA) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(松山)(JOZK) NHK-FM(東京)(JOAK-FM) 愛媛県(38) # RNB南海放送(RNB) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) FM愛媛(JOEU-FM) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(松山)(JOZK) NHK-FM(東京)(JOAK-FM) 高知県(39) # RKC高知放送(RKC) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) エフエム高知(HI-SIX) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(松山)(JOZK) NHK-FM(東京)(JOAK-FM) 福岡県(40) # RKBラジオ(RKB) KBCラジオ(KBC) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) LOVE FM(LOVEFM) CROSS FM(CROSSFM) FM FUKUOKA(FMFUKUOKA) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(福岡)(JOLK) NHK-FM(東京)(JOAK-FM) 佐賀県(41) # ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) エフエム佐賀(FMS) NBCラジオ(NBC) RKBラジオ(RKB) KBCラジオ(KBC) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(福岡)(JOLK) NHK-FM(東京)(JOAK-FM) 長崎県(42) # NBCラジオ(NBC) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) FM長崎(FMNAGASAKI) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(福岡)(JOLK) NHK-FM(東京)(JOAK-FM) 熊本県(43) # RKKラジオ(RKK) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) FMKエフエム熊本(FMK) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(福岡)(JOLK) NHK-FM(東京)(JOAK-FM) 大分県(44) # OBSラジオ(OBS) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) エフエム大分(FM_OITA) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(福岡)(JOLK) NHK-FM(東京)(JOAK-FM) 宮崎県(45) # 宮崎放送(MRT) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) エフエム宮崎(JOYFM) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(福岡)(JOLK) NHK-FM(東京)(JOAK-FM) 鹿児島県(46) # MBCラジオ(MBC) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) μFM(MYUFM) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(福岡)(JOLK) NHK-FM(東京)(JOAK-FM) 沖縄県(47) # RBCiラジオ(RBC) ラジオ沖縄(ROK) ラジオNIKKEI第1(RN1) ラジオNIKKEI第2(RN2) FM沖縄(FM_OKINAWA) オーディオ高校野球(ABCR-KOSHIEN) NHKラジオ第1(福岡)(JOLK) NHK-FM(東京)(JOAK-FM)

Kindleの蔵書一覧を生成するRubyスクリプト

MacにインストールされているKindleアプリのデータから蔵書一覧を生成 kindle_books_mac.rbrequire 'rexml/document' require 'date' require 'csv' # Kindle for Mac KINDLE_XML = "#{ENV['HOME']}/Library/Containers/com.amazon.Kindle/Data/Library/Application Support/Kindle/Cache/KindleSyncMetadataCache.xml" doc = REXML::Document.new(File.read(KINDLE_XML)) csv = CSV.generate(force_quotes: true) do |csv| doc.elements.each("//response/add_update_list/meta_data") do |e| csv << [ e.elements["ASIN"].text, e.elements["title"].text, e.elements["authors"].map{|item| item.text}.join('/'), e.elements["publishers"].map{|item| item.text}.join('/'), e.elements["publication_date"].text, e.elements["purchase_date"].text ] end end puts csv

Appleのヘルスケアデータから体重を抜き出してCSVファイルを作成する

Appleのヘルスケアアプリのデータを使って、他のアプリでグラフを描こうと思ったが、エクスポートされるデータはXMLのため、そのままでは扱いにくい。 このため、XMLファイルから体重データを抜き出してCSVを出力するRubyスクリプトを書いた。 require 'nokogiri' require 'date' reader = Nokogiri::XML::Reader File.read('export.xml') data = [] reader.each do |node| if node.name == 'Record' && node.attributes['type'] == 'HKQuantityTypeIdentifierBodyMass' d = Date.parse(node.attributes['startDate']).strftime("%Y-%m-%d") data << [d, node.attributes['value']] end end data.sort.each {|d| puts d.join(',') } =begin <Record type="HKQuantityTypeIdentifierBodyMass" sourceName="1byone Health" sourceVersion="63" device="&lt;&lt;HKDevice: 0x3013e9b30&gt;, name:iPhone, manufacturer:Apple, model:iPhone, hardware:iPhone, firmware:iPhone, software:17.5.1, localIdentifier:ja_JP, UDIDeviceIdentifier:ja_JP, creation date:2024-06-02 22:17:36 +0000&gt;" unit="kg" creationDate="2024-06-17 07:17:17 +0900" startDate="2024-06-17 07:17:17 +0900" endDate="2024-06-17 07:17:17 +0900" value="71.9"/> =end 以下、ChatGPTにヘルスケアデータの構造を聞いた回答 Appleのヘルスケアアプリでエクスポートされるデータは、XML (Extensible Markup Language) フォーマットで提供されます。このフォーマットは、ヘルスデータを構造化して格納するための標準的な形式です。 データの構造と内容 # XMLヘッダー エクスポートされたファイルは、XMLヘッダーから始まります。 <?xml version="1.0" encoding="UTF-8"?> 全体のルート要素 データ全体は <HealthData> というルート要素でラップされています。 <HealthData locale="en_US"> ... </HealthData> データの各エントリー ヘルスケアのデータは、それぞれの記録を <Record> 要素として格納します。主な属性は以下の通りです: type: データの種類(例: 歩数、心拍数など)。 sourceName: データのソース名(iPhone、Apple Watchなど)。 sourceVersion: ソースのバージョン情報。 unit: データの単位(例: count, bpm, kcal など)。 creationDate: データが作成された日時。 startDate: データの開始日時(測定期間の開始)。 endDate: データの終了日時(測定期間の終了)。 value: データの値(例: 歩数の数値、体重の値など)。 例:

Pomera DM250

Pomera DM250は、デジタルメモツールとして人気のある「Pomera」シリーズの最新モデル。 Pomeraシリーズはキングジム社が製造する、主にテキスト入力に特化したポータブルデバイスで、ノートパソコンと同様のフルキーボードを備えていますが、インターネットや複雑なアプリケーションの使用を排除し、シンプルな文書作成に特化している。 Pomera DM250とファイルをやり取りする方法 # 方法 手順 SDカード経由 SDカードを抜き差し USBケーブルでPCと接続しストレージとして認識させる ツール→PCリンク スマホアプリPomera Link経由でファイルを送受信する ツール→アプリ接続 または ツール→QRコード Wi-Fiに接続しGmailでファイルを送信する ツール→アップロード 内部のディレクトリ構造 # 本体メモリ # Pomera本体ストレージはMacのFinderからボリューム名をPOMERAに変更した。 /dev/disk10 on /Volumes/POMERA (msdos, local, nodev, nosuid, noowners, noatime, fskit) flowchart TD A[/Volumes/POMERA] --> |本体メモリのメモ|B(Pomera) B --> C(ファイル名.txt) B --> G(フォルダ名) A --> |カレンダーメモ| D(Pomera_memo) D --> E(YYYY) E --> F[YYYYMMDD.txt] SDカード # PomeraのSDカードはMacのFinderからボリューム名をPOMERA_SDに変更した。

RubyからBlueskyへの投稿

作成しているツールでRubyからBlueskyへ投稿したかったので、ShreyanJain9/bskyrb: Ruby Gem for interacting with BlueSky/AT Protocolというライブラリを使うことにした。 使用例を見ると、 require 'bskyrb' username = 'your_username' password = 'your_password' pds_url = 'https://bsky.social' credentials = Bskyrb::Credentials.new(username, password) session = Bskyrb::Session.new(credentials, pds_url) bsky = Bskyrb::RecordManager.new(session) post_uri = bsky.create_post("Hello world from bskyrb!")["uri"] bsky.like(post_uri) bsky.repost(post_uri) bsky.create_reply(post_uri, "Replying to post from bskyrb") とあり、一見簡単そうに見えるがBlueskyの場合はXやMastodonのAPIとは異なり、投稿するメッセージの中に、 URLがあってもリンクは設定されない ハッシュタグがあってもリンクは設定されない URLのコンテンツにOGBタグがあってもリンクカードは表示されない という仕様であり、なかなか面倒であることがわかった。 Ruby から Bluesky に投稿してみる Links, mentions, and rich text | Bluesky そんなわけで上記のドキュメントを参照しつつ、それぞれどうやれば良いのか調べてみた。 リンクの設定 # メッセージ中にURLがあれば、その部分を自動的にリンク設定したかったため、Rich text facetsの例にある以下の例を参考に、 { text: 'Go to this site', facets: [ { index: { byteStart: 6, byteEnd: 15 }, features: [{ $type: 'app.bsky.richtext.facet#link', uri: 'https://example.com' }] } ] } 以下のようなコードでfacetを作成した。 def create_facets_for_urls(text) facets = [] text_copy = text.dup URI.extract(text_copy, ['http', 'https']).each do |url| byte_start = text_copy[0, text_copy.index(url)].encode('UTF-8').bytesize byte_end = byte_start + url.bytesize facets << { 'index' => {'byteStart' => byte_start, 'byteEnd' => byte_end}, 'features' => [ { 'uri' => url, '$type' => 'app.bsky.richtext.facet#link', }, ], } text_copy[text_copy.index(url), url.length] = "\0" * url.length end facets end ハッシュタグの設定 # メッセージ中にハッシュタグがあれば、その部分を自動的にリンク設定したかったため、同じようなロジックでfacetを作成する。

Platypus - RubyスクリプトをMac OSのアプリに変換できるツール

sveinbjornt/Platypus: Create native Mac applications from command line scripts. スクリプト(Shellスクリプト、Perl、Python、Rubyなど)を標準のMac OS Xアプリケーション(.app)に変換するツール。 Platypusを使用すると、コマンドラインやターミナルを介さずに、スクリプトを直接実行可能なアプリケーションとして実行できる。 生成されるappのinfo.plistを編集することで、スクリプトをURLスキームに対応させることができる。 RubyではURLスキームで指定された文字列へARGVでアクセスできた。

OAuthでアクセストークンを取得するスクリプト

OAuthでアクセストークン、アクセストークンシークレットを取得するサンプル。毎回、同じようなスクリプトを書いて使い捨てにするのはムダなのでメモしておく。 ブラウザで表示されるURLへアクセスする リダイレクトされたURLのoauth_verifierの値を入力 access_token.token、access_token.secretが表示される require 'oauth' URL = "https://www.tumblr.com" consumer_key = 'Cls**********yaqV4' consumer_secret = 'RG****3KwFy' oauth = OAuth::Consumer.new(consumer_key, consumer_secret, site: URL) request = oauth.get_request_token(exclude_callback: true) puts "Access this URL: #{request.authorize_url}" print "oauth_verifier: " verifier = gets.chomp access_token = request.get_access_token(oauth_verifier: verifier) pp access_token

Webページから本文らしき部分を抽出する

さまざまなパターンの日本語文章をデータとして欲しいケースがあったので、指定したURLから本文らしき内容を抽出するスクリプトを書いた。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 require 'playwright' require 'readability' require 'html2text' # 指定したURLから本文らしき内容を抽出して返却する def html2text(url) Playwright.create(playwright_cli_executable_path: 'npx playwright') do |playwright| playwright.chromium.launch(headless: true) do |browser| begin page = browser.new_page page.goto(url, waitUntil: 'load') doc = Readability::Document.new(page.content) sleep 1 return {:title => page.title, :content => Html2Text.convert(doc.content) } rescue return {:title => nil, :content => nil } end end end end url = ARGV.shift doc = html2text(url) puts "#{doc[:title]}\n#{doc[:content]}" Javascriptでコンテンツを生成するページに対応するためPlaywrightを使用。 使用したライブラリ # cantino/ruby-readability: Port of arc90’s readability project to Ruby YusukeIwaki/playwright-ruby-client: Playwright client for Ruby soundasleep/html2text_ruby: A Ruby component to convert HTML into a plain text format.

指定したWebページをMarkdownへ変換するRubyスクリプト

指定したWebページをMarkdownへ変換するRubyスクリプト require 'reverse_markdown' require 'open-uri' ReverseMarkdown.config do |config| config.unknown_tags = :bypass config.github_flavored = true config.tag_border = '' end def usage puts "usage: #{$0} uri" exit 1 end usage if ARGV.size != 1 html = OpenURI.open_uri(ARGV.shift).read print ReverseMarkdown.convert html

2ホップリンク

ホップ数 # flowchart LR B1 & B2 --> A G --> O1 H --> O1 A --> O1 & O2 O2 --> E F --> O2 B1:::hop1 B2:::hop1 O1:::hop1 O2:::hop1 F:::hop2 G:::hop2 H:::hop2 style A fill:#f9f,stroke:#333,stroke-width:4px classDef hop1 fill:#a9a classDef hop2 fill:#f96 ホップ数とは自身から任意のページまでたどり着くまでのリンクの数である。 このようなリンク関係がある場合、ページAから見て、B1 B2 O1 O2は1ホップリンクと呼ばれる。 2ホップリンクの意味 # このため、上記のリンク関係で言えば、ページAから見たG H E Fは2ホップリンクとなる。 Scrapboxでは2ホップリンクの内、アウトゴーイングリンクのページへリンクしているページ、つまり、 AからリンクしているO1へリンクしている Gと H AからリンクしているO2へリンクしている F を関連リンクとして表示している。これは、 A→C, B→Cというリンクが存在するとき、AとBの間にはなんらかの関連があると考えてよい。 「和歌山」→「みかん」、「愛媛県」→「みかん」 ならば「和歌山県」と「愛媛県」はみかんつながりになっているわけだし、 「増井」→「Rubyプログラミング」、「高林」→「Rubyプログラミング」 ならば「増井」⇔「高林」は意味がある。 出典: 2ホップリンクの考察 - 増井俊之 上記の考え方に基づく仕様であり、本サイトでもQuartzを拡張し同様の2ホップリンクを表示している(各ページ配下の「関連リンク」) QuartzにScrapbox的な2ホップリンクを追加する Obsidiaのリンク表示 参考情報 # 2ホップリンクの考察 - 増井俊之

画像ファイルをまとめてリサイズする

RubyからImageMagickを使うためにRMagickで画像を一括してリサイズするスクリプト。Obsidianへ移行したメモに添付されていた画像サイズを圧縮するためにやっつけで作成 require 'RMagick' include Magick MAX_PIXEL = 800 MAX_FILE_SIZE = 300000 ARGV.each do |f| next unless %w(.jpeg .jpg .png .heic .webp).index File.extname(f).downcase size = File.size(f) next if size < MAX_FILE_SIZE img = Magick::Image.read(f).first next if img.columns <= MAX_PIXEL && img.rows <= MAX_PIXEL img.resize_to_fit(MAX_PIXEL, MAX_PIXEL).write(f) puts "#{f}: #{size} -> #{File.size(f)}" end