Twitterのトレンドを利用してブログ記事を宣伝するプログラムを書いた話。

目次。

 

修論締切の2日前に思いついて、執筆の息抜きのつもりでプログラムを書き始めたら、修論が…。結局、締切3分前に提出できたので、ぎりぎりセーフ。

 

 

はじめに。

これは、「Twitterの自動投稿を利用して、はてなブログの記事を宣伝するプログラムの話。」を拡張させた話。

blog.sun-ek2.com

 

2018年の末ぐらいにブログを始めて、そこからゆるゆると文章を書いてきた。気づいたら記事の数は、約40記事。と言っても、僕の文章は、結構長いので、普通の人の100記事分ぐらいあると思う。

 

まあ、それは置いといて、記事が溜まってきたので、そろそろちゃんと宣伝したいなって思って、(けれども手作業でそれをやるのは面倒くさいので、)自動でブログ記事の宣伝をするプログラムを書いたっていうのが、ここでの話。前回と動機は一緒だけれども、ちょっとだけ頭をひねってみたっていうのが今回。

 

 

 

 

なぜブログ記事を宣伝したいのか?

ブログ収益。

分かる人には分かると思うが、僕はブログ開設当初から書いた文章を収益化できるようにしている。メインは、Google AdSenseの広告(アドセンス広告)。アフィリエイトもちょこちょこやっているが、収益のほとんどは前者から入ってくる。微々たる量ですが。

 

と言っても、あんまりブログ収益を意識して、文章を書いているわけではない。高校の頃に収益を得るのを第一目標としてブログを何回かやったことがあるが、どれも続かなかった。なので、今は書きたい文章を書きたいように書いている。「SEO対策」とかは、あんまり念頭にない。

 

要するに…

折角、文章を書いているのだから、「小遣い程度に稼げたらいいよね」ってくらいの感じ。

 

 

情報発信基盤の強化。

ブログで広告収入を得るというのは、確かにブログ記事の宣伝を始めた理由の一つであるが、実はもっと大事な理由がある。それが、情報発信基盤の強化。

 

ここら辺の話は、自分の中でもはっきりしていないが、「自分の意見や自分自身の情報を発信する強力なプラットフォームを今から少しずつ構築しておけば、将来役に立つのでは」なんて思っている。

 

特にアカデミアの世界で生き残るために。

 

 

Twitterのトレンドを利用して、ブログ記事の宣伝。

前回のプログラムは、定期的にブログ記事を宣伝するツイートをするという単純なものだった。今回は、ちょっとだけひねる。

 

Twitterのトレンドは、こんな感じ。

 

f:id:sun_ek2:20200124224051p:plain

 

それぞれがハイパーリンクになっていて、リンクを踏むと、トレンドワードが含まれているツイート一覧が表示される。Twitterのトレンドを確認する人は、それなりにいるような気がするので、これを上手く利用すれば、もっとブログを宣伝できるのでは。

 

やりたいことは、Twitterのトレンドに使われている単語が多く含まれているブログ記事の宣伝ツイートを投稿するブログラムを書くこと。

 

 

 

 

ブログの記事を形態素解析。

まず初めに、はてなブログのAPIを叩いて、記事情報をxml形式で取ってきて、パース。xmlは、htmlと雰囲気あんま変わらないので、htmlパーサーを使っている(もちろんxmlとhtmlの違いは知っています)。前回と全く一緒のコードでブログの記事タイトルとURLを取ってくることができる(今回は記事タイトルの情報は使わないが、ついでに取ってきている)。ここら辺の詳しい話は、前回の記事にちゃんと書いてあるので、そちらを参照のこと。一応、コードはこっちにも載っけておく。

blog.sun-ek2.com

 

前回と違うのは、ここから。

xmlにブログの本文のhtmlが埋まっているので、まずはそいつを発掘。xmlにhtmlが埋まっているということは、めんどくさいことにhtmlのタグがすべて文字参照になっている。そのため、タグが文字参照状態になっているhtmlを一旦、文字列に変換して、ちゃんとhtmlタグにしたのちに、そいつを再度、htmlパーサーに渡し、記事の文章を抽出する。

 

形態素解析には、janomeを使っている。むっちゃ便利。抽出した文章を単語に分解して、それぞれの名詞が何回使われているかカウントする。ちなみに名詞の中で「非自立」とか「代名詞」に分類されるものは除いている(非自立ってなんぞ?)。

 

import requests
from bs4 import BeautifulSoup
from janome.tokenizer import Tokenizer
import tweepy


article_titles = []
article_links = []
all_word_counters = []
request_url = 'https://blog.hatena.ne.jp/hatenaID/hatenaID.hatenablog.com/atom/entry'
safety_counter = 0
while request_url != None:
    safety_counter += 1
    r = requests.get(url=request_url, auth=('hatenaID', 'APIkey'))
    soup = BeautifulSoup(r.text, 'html.parser')
    request_url = soup.find('link', rel='next')
    soup.findAll('app:draft')
    if request_url != None:
        request_url = request_url['href']
    temp_article_titles = soup.findAll('title')[1:]
    temp_article_links = soup.findAll('link', rel='alternate', type='text/html')
    draft_check = soup.findAll('app:draft')
    for i in range(len(draft_check)):
        if draft_check[i].string == 'yes':
            temp_article_titles.pop(i)
            temp_article_links.pop(i)
    for i in range(len(temp_article_titles)):
        temp_article_titles[i] = temp_article_titles[i].string
        temp_article_links[i] = temp_article_links[i]['href']
    article_titles.extend(temp_article_titles)
    article_links.extend(temp_article_links)

    tmp = soup.findAll('hatena:formatted-content')
    for i in range(len(tmp)):
        #xml内の本文部分のHTMLのタグが文字参照になっているので一旦、文字列に変換して、再度、引数に渡す。
        soup2 = BeautifulSoup(str(tmp[i].string), 'html.parser')
        t = Tokenizer()
        word_counter = {}
        for i in range(len(soup2.findAll('p'))):
            ele_str = soup2.findAll('p')[i].string
            if ele_str == None:
                continue
            for token in t.tokenize(ele_str):
                noun_str = str(token.surface)
                if len(noun_str) == 1:
                    continue
                if token.part_of_speech.split(',')[0]== '名詞':
                    if token.part_of_speech.split(',')[1]== '非自立':
                        continue
                    if token.part_of_speech.split(',')[1]== '代名詞':
                        continue
                    word_counter.setdefault(noun_str, 0)
                    word_counter[noun_str] = word_counter[noun_str] + 1
        all_word_counters.append(word_counter)

 

 

 

 

Twitterのトレンドを形態素解析。

TwitterのAPIを叩いて、Twitterのトレンドを取ってきて、そいつをさっきと同様に形態素解析。TwitterアプリとかだったらTwitterのトレンドは上位30個ぐらいしか表示されないが、APIを直接叩くと、Twitterのトレンドが上位50個、取得できる。

 

Twitterのトレンドに使われている単語を多く含んだブログ記事を抽出し、そこからツイートする文章を作成。そして、実際にツイートする。

consumer_key='XXXXXXXXXXXXXXXXXXXX'
consumer_secret='XXXXXXXXXXXXXXXXXXXX'
access_token_key='XXXXXXXXXXXXXXXXXXXX'
access_token_secret='XXXXXXXXXXXXXXXXXXXX'

auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token_key, access_token_secret)
api = tweepy.API(auth)
trends = api.trends_place(23424856)[0]['trends']

trend_list= []
trend_words = []
for i in range(len(trends)):
    trend_list.append(trends[i]['name'])
    for token in t.tokenize(trends[i]['name']):
        if token.part_of_speech.split(',')[0]== '名詞':
            if len(token.surface) == 1:
                continue
            if token.part_of_speech.split(',')[1]== '非自立':
                continue
            if token.part_of_speech.split(',')[1]== '代名詞':
                continue
            trend_words.append(token.surface)

word_counter_sum = []
trend_word_num = []
for i in range(len(all_word_counters)):
    word_counter_sum_tmp = 0
    for ele in set(all_word_counters[i].keys()) & set(trend_words):
        word_counter_sum_tmp += all_word_counters[i][ele]
        for a_trend in trend_list:
            if ele in a_trend:
                trend_word_num.append([i, a_trend, ele, all_word_counters[i][ele]])
    word_counter_sum.append([i, word_counter_sum_tmp])
article_ranking = sorted(word_counter_sum, reverse=True, key=lambda x : x[1])

tweet_elements = []
for a_trend_word_num in trend_word_num:
    if a_trend_word_num[0] == article_ranking[0][0]:
        tweet_elements.append(a_trend_word_num)
    tweet_elements = sorted(tweet_elements, reverse=True, key=lambda x : x[3])

tweet_status = ''
for i in range(len(tweet_elements)):
    tweet_status_ele = '「' + tweet_elements[i][1] + '」の「' + tweet_elements[i][2] + '」が' + str(tweet_elements[i][3]) + '回\n'
    if len(tweet_status) + len(tweet_status_ele) < 141-len('含まれている文章です。よければどうぞ。'):
        tweet_status += tweet_status_ele
    else:
        break

tweet_status += '含まれている文章です。よければどうぞ。\n' + article_links[article_ranking[0][0]]
api.update_status(status=tweet_status)

 

ツイートされる内容はこんな感じ。

「AAAAA」の「aa」がα回

「BBBBB」の「bb」がβ回

「CCCCC」の「cc」がγ回

含まれている文章です。よければどうぞ。

https://blog.sun-ek2.com/~(記事のURL)

大文字はTwitterのトレンドに上がっている言葉を表し、小文字はトレンドに含まれている単語を表し、ギリシャ文字はそれが記事の文章中に何回含まれているか表している。

 

 

 

 

今後。

  • ブログの宣伝ツイートをしまくって、他人のタイムラインを汚すと、ミュートされる可能性があるので(僕だったらミュートする)、新規に宣伝ツイートをしたら、一個前のツイートを削除するコードを書く。
  • 一度、宣伝させた記事は、一定期間、宣伝されないようにする。このアルゴリズムでは、1万字ある記事は、500字しかない記事に比べて、圧倒的に宣伝されやすい。ある程度、公平にあらゆる記事が宣伝されるようにする。

 

この2つの機能を実装した後に、実際に僕の個人アカウントを使って自動投稿してみたいと思う。

 

 

高校生の頃、倫理的にグレーゾーンなブログのアクセスを上げるプログラムを書いて、数か月に1回しか更新していないブログで最高月2万pv以上いったが、このプログラムではどのくらいいくのだろう…。

 

ブログランキング・にほんブログ村へ
にほんブログ村