Googleニュースの検索結果の上位3件からランダムで1件選び、タイトルとURLとハッシュタグを投稿するコードです。本ページではコードの詳細は解説していません。読めばどこでなにをしているか大体わかる人向けです。
ニュース情報はRSSから取得しています。
投稿先は上がTwitter(X)、下がBlueSkyです。
BlueSkyは「ハッシュタグ」と「投稿文章内URLのハイパーリンク」と「リンクカード」に対応してます。ただしアイキャッチは画像はつきません。付けたい方は以下サイトが参考になるでしょう。
BlueskyのAT Protocolでリンクカード付きのpostを投稿する方法
検索ワード、取得件数、投稿時間、ハッシュタグはコード内の値を変更することでカスタマイズ可能です。ただし、投稿する数は1件でこれを変える処理は組み込んでおりません。
特定の時間に実行する環境での実装を想定しています。例えばlolipopのcronの場合、cronの設定にて毎月毎日毎時00分に実行するように設定する→コード内に設定した時間のみ投稿される、という感じです。ローカル上でも設定した時間以外に実行されても投稿されません。
参考として公開したまでですので、自己責任でご活用ください。
Twitter(X)に投稿するコード
/#!/usr/local/bin/python3.7
# -*- coding: utf-8 -*-
import tweepy
import requests
from bs4 import BeautifulSoup
import feedparser
import random
import datetime
import sys
# APIキーとアクセストークンの設定
api_key_common = '' #TWitterAPIのAPIキー
api_key_secret_common = '' #TwitterAPIのAPIシークレットキー
access_token_common = '' #TwitterAPIのaccesstoken
access_token_secret_common = '' #TwitterAPIのaccesstokensecret
# APIの設定
client = tweepy.Client(
consumer_key=api_key_common,
consumer_secret=api_key_secret_common,
access_token=access_token_common,
access_token_secret=access_token_secret_common
)
# ジャンプ先のURLを取得する関数
def get_final_url(url):
try:
response = requests.head(url, allow_redirects=True)
return response.url
except requests.exceptions.RequestException as e:
print("ジャンプ先のURLを取得できませんでした:", e)
sys.exit(1)
# ジャンプ先のページのタイトルを取得する関数
def get_page_title(url):
try:
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')
return soup.title.string
except requests.exceptions.RequestException as e:
print("ページタイトルを取得できませんでした:", e)
sys.exit(1)
# RSSフィードから上位3つの記事を取得する関数
def get_top_three_news_entries(keyword):
rssDatas = feedparser.parse(f'https://news.google.com/rss/search?q=%27{keyword}%27&hl=ja&gl=JP&ceid=JP:ja')
return rssDatas.entries[:3] #初期値は上位3件。変更したい場合は値を変える
# ランダムに1つの記事を選んでツイートする関数
def tweet_random_news_entry(entries):
# ランダムに1つの記事を選択
selected_entry = random.choice(entries)
# 記事のタイトルとURLを取得
title = selected_entry.title
link = selected_entry.link
# ジャンプ先のURLを取得
final_url = get_final_url(link)
if final_url:
print("ジャンプ先のURL:", final_url)
# ツイート内容を作成
tweet_text = f"{title} #ハッシュタグ名\n{final_url}\n{final_url}" #ハッシュタグ名はここで変更
# ツイートを投稿
client.create_tweet(text=tweet_text)
else:
print("ジャンプ先のURLを取得できませんでした。")
sys.exit(1)
# メイン処理
def main():
keyword = 'hyogokurumi.com' #検索したいキーワードを入力する
# RSSフィードから上位3つの記事を取得
entries = get_top_three_news_entries(keyword)
if len(entries) > 0:
# ランダムに1つの記事を選んでツイート
tweet_random_news_entry(entries)
print("ツイートが投稿されました。")
else:
print("記事が見つかりませんでした。")
sys.exit(1)
# 指定した時間に一度だけツイートを投稿する関数
def schedule_tweet():
current_time = datetime.datetime.now().time()
if current_time.hour in [7, 12]: #初期値は7時と12時
main()
if __name__ == "__main__":
schedule_tweet()
BlueSKyに投稿するコード
#!/usr/local/bin/python3.7
# -*- coding: utf-8 -*-
from atproto import client_utils
from atproto import Client, models
import requests
from bs4 import BeautifulSoup
import random
import time
import datetime
import re
import typing as t
import feedparser
# Blueskyへの投稿関数
def post_to_bluesky(text: str, link_card_uri: str, facets: t.List[models.AppBskyRichtextFacet.Main], embed: models.AppBskyEmbedExternal.Main):
client = Client()
client.login('〜bsky.socialまでのアカウント名@不要', 'アプリパスワード') #アカウント名とアプリパスワード
client.send_post(text, facets=facets, embed=embed)
def extract_url_byte_positions(text: str, *, encoding: str = 'UTF-8') -> t.List[t.Tuple[str, int, int]]:
"""This function will detect any links beginning with http or https."""
encoded_text = text.encode(encoding)
# Adjusted URL matching pattern
pattern = rb'https?://[^ \n\r\t]*'
matches = re.finditer(pattern, encoded_text)
url_byte_positions = []
for match in matches:
url_bytes = match.group(0)
url = url_bytes.decode(encoding)
url_byte_positions.append((url, match.start(), match.end()))
return url_byte_positions
def get_top_three_news_entries(keyword):
rssDatas = feedparser.parse(f'https://news.google.com/rss/search?q=%27{keyword}%27&hl=ja&gl=JP&ceid=JP:ja')
return rssDatas.entries[:3]
def get_final_url(url):
try:
response = requests.head(url, allow_redirects=True)
return response.url
except requests.exceptions.RequestException as e:
print("ジャンプ先のURLを取得できませんでした:", e)
return None
def get_page_title(url):
try:
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')
return soup.title.string
except requests.exceptions.RequestException as e:
print("ページタイトルを取得できませんでした:", e)
return None
if __name__ == "__main__":
current_hour = datetime.datetime.now().hour # 現在の時間を取得
# 指定された時間帯にのみ投稿する
if current_hour in [7, 12]: #初期値は7時と12時
# ランダムに1つの記事を選んでBlueskyに投稿する
keyword = 'hyogokurumi.com' #検索したいキーワードを入力する
entries = get_top_three_news_entries(keyword)
if len(entries) > 0:
selected_entry = random.choice(entries)
title = selected_entry.title
link = selected_entry.link
final_url = get_final_url(link)
if final_url:
print("ジャンプ先のURL:", final_url)
page_title = get_page_title(final_url)
# リンクカードの情報を設定
link_card_title = page_title if page_title else title
link_card_uri = final_url
# 投稿テキストからURLのバイト位置を検出
url_positions = extract_url_byte_positions(title)
facets = []
# URLのバイト位置をリンクカードとして追加
for link_data in url_positions:
uri, byte_start, byte_end = link_data
facets.append(
models.AppBskyRichtextFacet.Main(
features=[models.AppBskyRichtextFacet.Link(uri=uri)],
index=models.AppBskyRichtextFacet.ByteSlice(byte_start=byte_start, byte_end=byte_end),
)
)
# リンクカードの設定
embed_external = models.AppBskyEmbedExternal.Main(
external=models.AppBskyEmbedExternal.External(
title=link_card_title,
uri=link_card_uri,
description=""
)
)
# Blueskyに投稿する
# テキストに #発達障害ニュース をハッシュタグとして追加し、同時にリンクカードを設定する
text_builder = client_utils.TextBuilder().text(title).tag('#ハッシュタグ名', '←ハッシュタグ名と同じワード#不要') #ハッシュタグもつけられる。
# リンクカードの後に改行を追加
text_builder.text("\n")
text_builder.link(text=f"{link_card_uri}\n", url=link_card_uri)
post_to_bluesky(text_builder, link_card_uri, facets, embed_external)
print("投稿しました hattatsuabyss1_bsauto.py Yahoo 7, 12, 17, 22")
else:
print("ジャンプ先のURLを取得できませんでした。")
else:
print("記事が見つかりませんでした。")
else:
print("投稿しませんでした hattatsuabyss1_bsauto.py Yahoo 7, 12, 17, 22")