見出し画像

Pythonを使ってお気に入りサイトのRSSを取得する➁ 対象を絞る

前回、PythonでRSSを取得する方法を記載しましたが、今日は取得したRSSから欲しい記事だけを選別する方法を書いていきます。

1. 今回の目的(情報の選別・効率化)

RSSリーダーアプリって便利ですよね。

Feedlyや、Inoreader(僕はこれを使っています),feederなど。
ただ、登録したサイトの新着記事がずらーっと並ぶので、結構欲しい記事を探して読むのが面倒というのが実態。

欲しい情報だけを選別して、読めるようにすれば効率化にもなります。結構、RSSリーダーは時間泥棒になりますよね。

2. 正規表現で文字列に特定の文字があるかを確認する

正規表現は、文字列から「特定の文字を抽出する」際などに利用します。なお、正規表現自体はPython限定でないため、他言語でも利用できます。

標準モジュールであるreをインポートすることで利用できます。

基本形は以下の通りです。

import re
print(re.match('ノンストップ飯田', 'ノンストップ飯田です'))

実行結果は以下となります。

<re.Match object; span=(0, 8), match='ノンストップ飯田'>

つまり、reモジュールのmatch関数に、第1引数として抽出したいパターン、第2引数に対象の文字列を渡すことで、マッチオブジェクトが返ります。

なお、match関数は文頭から検索をします。
文中に対して検索をかけたい場合は、search関数を使います。
少し例を変えてみましょう。

import re

str1 = '''かねてから、私はノンストップ飯田という名前で
ブログを書いたり、歌ったりしているが、私の本当の苗字が飯田かは私にももう分からない。
本当は前田かもしれない。'''

print(re.search('前田', str1))

長文なので、予めstr1という変数に格納したうえで、”前田”という文字列が含まれているかを検索しています。

実行結果はこれが下の通りです。

<re.Match object; span=(67, 69), match='前田'>

参考までに、match関数を使った場合は・・・

import re

str1 = '''かねてから、私はノンストップ飯田という名前で
ブログを書いたり、歌ったりしているが、私の本当の苗字が飯田かは私にももう分からない。
本当は前田かもしれない。'''

print(re.match('前田', str1))

実行結果は以下となります。

None

先頭行から検索するので、マッチせず。その場合は、戻り値なNoneとなります。以上が、正規表現の超基本的な内容です。

これを使って、取得したRSSフィードを絞っていきます。

3. RSSフィードの絞り込み方

RSSフィードからは、記事タイトルとURL、それからサマリ(記事の要約)を取得します。

この際、記事タイトルかサマリに気になるキーワードが含まれているかを確認し、キーワードがある場合だけ出力をするようにコードを書いていきます。

例えば、適当に以下のキーワードで複数サイトのRSSフィードから絞り込みをかけて情報を抽出したいと思います。

条件

(含む)
・プログラミング
・Python

(含まない)
・スクール
・AI

上記を正規表現で表すと以下となります。

'^(?=.*プログラミング|Python)(?!.*スクール|AI)'

そして、条件にマッチしたら文字列を出力。マッチしなかったら、出力しないというif文を書いてみましょう。

import re

#テスト文字列
str1 = 'プログラミング学習するならやっぱりスクールにいくべき'
str2 = '解決!プログラミング!ファイル読み書きをマスターしよう'
str3 = 'AI×Pythonで顏認証する'
str4 = '学習のサポートに!python関連書籍'

p = re.compile('^(?=.*(プログラミング|Python))(?!.*(スクール|AI))', re.IGNORECASE)
p2 = re.compile('プログラミング|Python', re.IGNORECASE)

for str_ in [str1, str2, str3, str4]:
   if p.search(str_):
       print('マッチしたキーワード:{}'.format(p2.search(str_).group()))
       print(str_)
   else:
       pass

出力結果を見てみましょう。

=========== RESTART: C:\Users\yusuke\python_scripts\rss_feed\test.py ===========
マッチしたキーワード:プログラミング
解決!プログラミング!ファイル読み書きをマスターしよう
マッチしたキーワード:python
学習のサポートに!python関連書籍

4. コードの解説

(1) re.compileについて

突然、re.compileが登場しましたが、これは条件を定義して変数に格納しておくためのものです。

この変数pの型を確認してみると・・・

>>>print(type(p))
<class 're.Pattern'>

re.Patternクラスであると出力されます。こうして定義をしておくと、後で違う箇所にも使いまわせるので、何度も条件を記載せずともよく便利なので覚えておきましょう。

(2) re.IGNORECASEについて

パターン定義の際に第2引数に記載しているre.IGNORECASEという謎の引数は、アルファベットの大文字小文字を区別せずに判定するためのものです。

Pythonと条件にはありますが、pythonでもマッチと判定してくれます。

(3) マッチオブジェクト.group() について

わざわざp2というパターンを作っているのは、どのキーワードにマッチしたのかを出力するためのものです。

なお、マッチオブジェクトのうちマッチした文字を出力する際は、マッチオブジェクト.group()で出力が可能です。
なお、そもそもマッチしてないとマッチオブジェクトでなく、Noneが戻り値となるのでエラーとなることに注意してください。

5. RSSと正規表現を組み合わせて、対象を絞ってRSSフィードを抽出する

では、いくつか要件を決めて、今回のメインである複数サイトのRSSフィードを取得+対象絞り込みをやっていきましょう。

(1) 対象とするサイト

対象とするサイトは以下

#各サイトのRSS URL
gizmodo = "https://www.gizmodo.jp/index.xml" #ギズモードジャパン
gigazine = "https://gigazine.net/news/rss_2.0/" #GIGAZINE
lifehacker ="https://www.lifehacker.jp/feed/index.xml" #ライフハッカー日本版
atmarkit = "https://rss.itmedia.co.jp/rss/2.0/ait.xml" #@IT
it_domestic = "https://rss.itmedia.co.jp/rss/2.0/news_domestic.xml" #ITmedia 国内 
it_oversea = "https://rss.itmedia.co.jp/rss/2.0/news_foreign.xml" #ITmedia 海外
it_biz = "https://rss.itmedia.co.jp/rss/2.0/business.xml" #ITmedia buisiness
jbpress = "https://jbpress.ismedia.jp/list/feed/rss" #JB Press
groaca = "https://g-aca.com/column/feed" #Growing-Academy
biz_journal = "https://biz-journal.jp/index.xml" #Biz Jounal
agora = "https://agora-web.jp/feed" #アゴラ・プラットフォーム
hatena_url = 'http://feeds.feedburner.com/hatena/b/hotentry' #はてなブックマーク
hatena_tech_url = "https://b.hatena.ne.jp/hotentry/it.rss" #はてなブックマーク テクノロジー
tech_url = 'https://jp.techcrunch.com/feed/' #TechCrunch Japan
toyokeizai = "https://toyokeizai.net/list/feed/rss" #東洋経済オンライン
diamond = "https://diamond.jp/list/feed/rss/dol" #ダイヤモンド・オンライン
bunshun = "https://bunshun.jp/list/feed/rss" #文春オンライン
yahoo_biz = "https://news.yahoo.co.jp/rss/topics/business.xml" #Yahooニュース 経済
yahoo_it = "https://news.yahoo.co.jp/rss/topics/it.xml" #Yahooニュース IT

(2) 絞り込み条件

絞り込みの条件は以下とします。

p = re.compile('^(?=.*(プログラミング|コード|重宝|リモート|方法|裏技|Python|書評|書籍|生き方|多様性|思考|ロジカル|効率|捗る|スキル|リスキル|勉強|教育|人材|新))(?!.*(アップル|キャンプ))')
p2 = re.compile('プログラミング|コード|重宝|リモート|コツ|裏技|Python|書評|書籍|生き方|多様性|思考|ロジカル|効率|捗る|スキル|リスキル|勉強|教育|人材')

なお、条件はいくらでも変更可能です。
お好みの条件に変えてみてください。

(3) データ抽出方法

今回抽出するのは、➊どの条件に合致したか(カテゴリー)、➋記事タイトル、➌掲載日、➍URL、➎サマリの5点。

これを辞書形式とし、リストに辞書形式とした各記事情報を保存。最終的に、CSVファイルに書き出ししたいと思います。

各記事を辞書形式にして、リストに格納するパーツは以下のとおり。
予め、空のcontents_dictとarticles_listは用意しておきます。

f = feedparser.parse(yahoo_it)
entries = f['entries']

for e in entries:
   m_title = p.search(e['title'])
   m_summary = p.search(e['summary'])
   if m_title and m_summary:
       try:
           contents_dict = {}
           keyword = p2.search(e['title']).group()
           contents_dict['category'] = keyword
           contents_dict['title'] = e['title']
           contents_dict['link'] = e['link']
           contents_dict['published'] = e['published']
           contents_dict['summary'] = e['summary']
           article_list.append(contents_dict)
       except:
           pass
   elif m_summary:
       try:
           contents_dict = {}
           keyword = p2.search(e['summary']).group()
           contents_dict['category'] = keyword
           contents_dict['title'] = e['title']
           contents_dict['link'] = e['link']
           contents_dict['published'] = e['published']
           contents_dict['summary'] = e['summary']
           article_list.append(contents_dict)
       except:
           pass
   else:
       pass
       

一度、これまでの内容を組み合わせて実行してみましょう。
記事数多いので、一部だけ・・・。

[{'category': 'リモート',
 'link': 'https://diamond.jp/articles/-/280763',
 'published': 'Sun, 05 Sep 2021 04:50:00 +0900',
 'summary': 'マッキンゼー、Google、リクルート、楽天など、14もの職を経て、現在はシンガポール・バリ島を拠点にリモートで活動するIT批評家の尾原和啓氏。2021年7月に発売された最新著書『プロセスエコノミー '
            '』には、発売前から予約が殺到し、Amazon総合ランキング1位に。本のタイトルである「プロセスエコノミー」という言葉がメディアで紹介されるなど、注目を集めている。本書の刊行を記念して、著者の尾原和啓氏と、『ニュータイプの時代』など数々のベストセラーをもち、“これからは「役に立つ」より「意味がある」ことに価値がある”と提唱したことでも話題となった、山口周氏との対談が行われた。今回は、2020年には対談本『仮想空間シフト』を出版した2人が、真のイノベーションが起こるタイミングについて、それぞれの視点で語り合う。',
 'title': 'これからの時代、「完成形」の概念が根本的に変わっていく理由 - 「プロセスエコノミー」が来る!'},
{'category': '思考',
 'link': 'https://diamond.jp/articles/-/280682',
 'published': 'Sun, 05 Sep 2021 04:05:00 +0900',
 'summary': '私たちは「面倒な人」と付き合っていくべきなのか? '
            '34万部のベストセラーになっている『1%の努力』の著者・ひろゆき氏。現在、YouTubeやテレビで大人気の彼の「思考の原点」について聞いてみた。',
 'title': 'ひろゆきが語る「距離を置いたほうがいい人」ベスト1 - 1%の努力'},
{'category': '思考',
 'link': 'https://diamond.jp/articles/-/277215',
 'published': 'Sun, 05 Sep 2021 03:50:00 +0900',
 'summary': '20万部のベストセラー待望のマンガ版『マンガ\u3000このまま今の会社にいていいのか?と一度でも思ったら読む '
            '転職の思考法』が発売された。前作で「転職は悪」という風潮に一石を投じ、日本人の働き方を変えた北野唯我氏が、今回は「自分にはキャリアの武器が何もない」と思っている主人公の奈美(もうすぐ30歳)の悩みに答えを出す。「やりたいことがなければダメ」「S級人材以外は有利な転職は無理」など転職の常識が次々と覆される。この連載では、本書から特別に一部を抜粋して紹介する。',
 'title': '【マンガ】30歳「転職したけどまたすぐ辞める人」と「活躍できる人」を分けるポイント - マンガ転職の思考法'},
{'category': '生き方',
 'link': 'https://bunshun.jp/articles/-/48066',
 'published': 'Sat, 04 Sep 2021 11:00:00 +0900',
 'summary': '新著『他者の靴を履く\u3000'
            'アナーキック・エンパシーのすすめ』が話題のブレイディみかこさんと、『分解の哲学』(サントリー学芸賞)などの名著で知られる歴史学者・藤原辰史さんとの特別対談が実現。言葉が拓く可能性…',
 'title': 'ブレイディみかこが語る“パンデミック時代の生き方”と、藤原辰史の「知性の足がガタガタと震える」世界'}]

では、これをCSVファイルに吐き出して保存できるようにしていきます。

path = "ファイルパスを格納してください"

with open(path, 'w', newline = '') as f:
    fieldnames = header
       writer = csv.DictWriter(f, fieldnames = fieldnames)
       writer.writeheader()
       for article in article_list:
           writer.writerow({'カテゴリ' : article['category'],
                            'タイトル' : article['title'],
                            '発行日' : article['published'],
                            'URL' : article['link'],
                            'サマリー' : article['summary']
                           })

厳密には、記事が重複しないように既存ファイルを読み込んで重複チェックが必要だったりしますが、上記で辞書形式でヘッダーに合わせて書き込みができます。

以上で、各パーツは揃いました!

実行すると・・・

画像1

こんな感じで、無事csvファイルに保存が完了しました!
次回は、このPythonファイルを定期的に自動実行(自動化)することに挑戦したいと思います。

処理完了:新着記事27件を取得

6. コード全文

上のパーツを組み合わせ、既存ファイルに記載済の場合に重複チェックをして常に未取得の記事のみ書き込むようにしたのが以下です。

なお、サイトごとに処理をしていく方法もありますが、コードがかなり長くなりますので、共通で処理できる部分はまとめていたりします。

ご自分で、条件を変えたり、RSSのURLを増やしたり自由にカスタマイズしてご活用ください!

~コード全文~

ここから先は

4,896字

¥ 500

この記事が気に入ったらサポートをしてみませんか?