XMPPボット-2chリーダーの作成1

Last-modified: 2014-08-16 (土) 12:41:50 (2120d)

[ 前のページ : XMPPボット-リマインダーボットの作成 | ]

2ch掲示板の更新をチェックし、更新が見つかれば更新内容をIMとして送信してくるボットを作成します。

まずは、ボットとして作成する前に、更新があるかをチェックするPythonプログラムをモジュールとして作成しておきます。

更新があるかどうかはdatファイルをGETではなくHEADで要求し、Last-Modified ヘッダの値に変化があるかどうかで判断します。変化していたら、datファイルをまるごとダウンロードし、解析を行います。

なお、このプログラムをそのまま使うと30秒ごとにひたすらHEADを行い、更新頻度が高いファイルの場合は30秒ごとにdatファイルをダウンロードし続けるため、場合によっては大量アクセスとみなされ、どこかで制限がかかるかもしれません。実行は自己責任でお願いします。

nichanChecker.py

#!/usr/bin/python
# -*- coding: utf-8 -*-

#
# 2ch datファイル 更新チェッカー
# 
# ytyng.com
#

import urllib2
import time

#
# urlのLast-Modifiedヘッダが更新されているかチェックする
#

headerLastModifiedOld = ""
def checkLastModified(targetUrl):
	
	global headerLastModifiedOld
	
	request = urllib2.Request(targetUrl)
	request.get_method = lambda: "HEAD"
	http_file = urllib2.urlopen(request)
	header = str(http_file.headers)
	
	headerLastModified = header[header.find("Last-Modified:"):].split("\n")[0]
	
	#print headerLastModified
	
	if headerLastModifiedOld == "" : 
		headerLastModifiedOld = headerLastModified
		#print "First load.",headerLastModified
		return True
	elif headerLastModifiedOld != headerLastModified:
		headerLastModifiedOld = headerLastModified
		#print "Modified.",headerLastModified
		return True
	else:
		#print "Not modified. Do nothing."
		return False

#
# 新規レスを表示
#
readedLine=0
def getNewRes(datUrl):
	
	global readedLine
	
	#request = urllib2.Request(datUrl)
	datHandle = urllib2.urlopen(datUrl)
	#datSource = datHandle.read()
	datLines = datHandle.readlines()
	
	if readedLine == 0 :
		linesForPrint = datLines[-5:] #最新5件
	else:
		linesForPrint = datLines[readedLine:]
	readedLine = len(datLines)
	
	resNum = readedLine - len(linesForPrint)
	
	#print type(datSource)
	#datHandle.close()
	
	#SAMPLE
	#名無しさん@九周年<>sage<>2009/01/01(木) 15:47:26 ID:BZWBZfQd0<> 裸の王様でしかない <>
	#0                   1     2                                      3
	
	buffer = ""
	#c = 0
	for line in linesForPrint:
		resNum += 1
		#if c > 0 :
		#	buffer += "\n----------\n"
		buffer += "["+str(resNum)+"]----------\n"
		
		cells = line.decode('cp932','ignore').split("<>")
		buffer += decodeRes(cells[3]).strip()+"\n"
		#c += 1
		
	#print linesForPrint
	
	return buffer

#
# <br>を改行文字にして、簡易実体参照デコードを行う。
#
def decodeRes(resLine):
	lines = resLine.split("<br>")
	
	buffer = ""
	for line in lines:
		line = line.strip()
		#if line.find(u"    ") >= 0 : continue #簡易AAストリップ
		if len(line):
			buffer += line+"\n"
	resLine = buffer
	resLine = stripTags(resLine)
	resLine = resLine.replace("&gt;",">")
	resLine = resLine.replace("&lt;","<")
	resLine = resLine.replace("&nbsp;"," ")
	
	return resLine

#
# HTMLタグ除去
#
def stripTags(s):
	buffer = ''
	mode = 1
	for i in s:
		if   i == '<' : mode = 0
		elif i == '>' : mode = 1
		elif mode == 1: buffer += i
		else          : pass
	return buffer



#
# スレッドURLをdatURLに変換
#
def convertToDatUrl(threadUrl):
	
	# http://mamono.2ch.net/test/read.cgi/newsplus/1230792238/
	# ↓     0              1    2        3        4
	# http://mamono.2ch.net/newsplus/dat/1230792238.dat
	# +      0              3        +   4         +
	
	threadUrl = threadUrl.replace("https://","",1)
	threadUrl = threadUrl.replace("http://","",1)
	threadUrl = threadUrl.replace("ttp://","",1)
	cell = threadUrl.split("/")
	if len(cell) < 5 :
		return None
	datUrl = "http://"+cell[0]+"/"+cell[3]+"/dat/"+cell[4]+".dat"
	return datUrl

if __name__ == "__main__":
	
	import sys
	
	if len(sys.argv) <= 1 :
		print "usage:",sys.argv[0],"<2ch-thread-url> "
		sys.exit(0)
	
	#threadUrl = "http://mamono.2ch.net/test/read.cgi/newsplus/1230792238/"
	threadUrl = sys.argv[1]
	
	datUrl = convertToDatUrl(threadUrl)
	while True:
		r = checkLastModified(datUrl)
		
		if r:
			print getNewRes(datUrl) ,
		if readedLine >= 1000: break
		time.sleep(30)
	print "end."

decodeRes()の実体参照デコード部が我ながら適当すぎて泣けてくる。多分モジュールが用意されていると思うのですが、わかりませんでした……。

実行結果

引数にスレッドURLを与えて実行させると、更新結果が次々と表示されていきます。

各行はトリム(strip)されるため、AAは崩れます。

$ ./nichanChecker.py http://mamono.2ch.net/test/read.cgi/newsplus/1230853710/
[798]----------
で、パケモンとやらのCEOは誰なの?
[799]----------
そうか、2ちゃんねる閉鎖か。
今日は良い酒が飲めそうだ。
初めて書くメシウマ
[800]----------
次は中川翔子か?
今まで2ちゃんねるはマスコミ、企業を相手にねらーを誘導して圧力をかけてきた。
しかし黙ってみているほど相手もお人好しでもない。
田代逮捕に始まり植草謀殺ホリエモン弾劾と次々に血祭りに送っていくのである。
もちろん2ちゃんねるもそれに対抗しp2pや失言を駆使して祭りを仕立て上げ反撃を試みた。
その結果がのまねこで打ち負かしジャスラックを巻き込んだニコニコの設立である。
しかしここへ来てひろゆきも弱気だ
盟友飯島愛の死と度重なる訴訟地獄である。
続く
[801]----------
糞掲示板とっとと閉鎖しろ
[802]----------
とりあえずカキコ
[803]----------
てす
わらくすゎイノセントぬ「ねえねえおかーさん、こんなにご馳走食べれるなら毎日お葬式だといいネ!」とゆつちやうこせい
でありたし むっふん
[804]----------
譲渡っつーか放棄だろ?w
[805]----------
>>788
大阪さん、何してはるんですか
[806]----------
ショック!!激甘日本には「法廷侮辱罪」がなかった!!(けど外国にはある)
[807]----------
>>797
大丈夫 です
もう すぐ かわる よ せかいが
[808]----------
これはやばいな
おそらく中国の陰謀