【Python】Googleニュースの検索結果をランダムでTwitter(X)に投稿するコードとBlueSkyに投稿するコード

 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")

 

 

タイトルとURLをコピーしました