1. 程式人生 > >同樣是追星 ,為什麼他們能這麼做

同樣是追星 ,為什麼他們能這麼做

最近我朋友瘋狂迷戀韓國的偶像團體防彈少年團,於是拜託我幫忙寫一段程式實時檢測韓國新聞網站instiz旗下兩個板塊pt和clip,當出現自家idol的新聞時,程式能自動發微博通知她。我覺得這個功能還是蠻有意思的,程式實現起來並不複雜,而且妹子的請求不好意思拒絕,所以就答應她了。說幹就幹,程式實現如下。

模擬登入微博

發微博的功能如果藉助微博的api其實很簡單,然而當我註冊站內應用獲得APPKEY和ACCESS_TOKEN時,稽核了2天竟然被拒了(當然也有可能是自己填的太隨意哈)。不過懶得等的我乾脆自己模擬瀏覽器登入發微博。

首先我們需要分析模擬登陸需要提交的表單,開啟chrome分析登入時https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.19) 需要提交的表單,可以發現有以下資訊需要我們注意:

其中servertime,nonce,rsakv應該來自之前get到的資料,翻之前的url請求,注意到有一個prelogin的url值得我們注意,觀察返回來的資料:

{"retcode":0,
"servertime":1537519779,
"pcid":"gz-7b560c8c199aa33a6b201149095489a4d147","nonce":"H6ITP0","pubkey":"EB2A38568661887FA180BDDB5CABD5F21C7BFD59C090CB2D245A87AC253062882729293E5506350508E7F9AA3BB77F4333231490F915F6D63C55FE2F08A49B353F444AD3993CACC02DB784ABBB8E42A9B1BBFFFB38BE18D78E87A0E41B9B8F73A928EE0CCEE1F6739884B9777E4FE9E88A1BBE495927AC4A799B3181D6442443",
"rsakv":"1330428213",
"is_openlock":0,
"lm":1,
"smsurl":"https:\/\/login.sina.com.cn\/sso\/msglogin?entry=weibo&mobile=18800190793&s=f0cd668a3b51745b707c94f41a090c98",
"showpin":0,
"exectime":110}

裡面也確實有我們需要的資料,那麼另外兩個su以及sp應該就是加密之後的username和password了,然而網站如何加密的呢?

仔細觀察的話會有一個ssologin.js的檔案在prelogin和login中都有出現,猜測加密應該是在這裡面完成的,這個檔案很大,但我們只需要搜我們自己想要的,果然找到了如下程式碼:

request.su=sinaSSOEncoder.base64.encode(urlencode(username))

RSAKey.setPublic(me.rsaPubkey,"10001");

password=RSAKey.encrypt([me.servertime,me.nonce].join("\t")+"\n"+password)

OK,將這段js程式碼翻譯成python程式碼就可以了,完整的程式碼如下所示:

importrequests

importbase64

importre

importrsa

importjson

importbinascii

importtime

classweibo(object):

def__init__(self, username, password):

self.username = username

self.password = password

defencrypted_username(self):

# 對使用者名稱加密,返回su

returnbase64.b64encode(bytes(self.username, encoding="utf-8")).decode("utf-8")

defencrypted_password(self):

# 對密碼加密,返回sp

data=self.get_prelogin_data()

rsa_e=65537

password_str=str(data["servertime"])+"\t"+str(data["nonce"])+"\n"+self.password

key=rsa.PublicKey(int(str(data["pubkey"]),16), rsa_e)

password_encrypt=rsa.encrypt(password_str.encode("utf-8"), key)

returnbinascii.b2a_hex(password_encrypt).decode("utf-8")

defget_prelogin_data(self):

# 以json格式返回prelogin的資料

url ='http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=&'+ self.encrypted_username() +'&rsakt=mod&checkpin=1&client=ssologin.js(v1.4.18)'

withrequests.Session()assess:

r=sess.get(url, timeout=2)

pattern = re.compile(r"\((.*)\)")

data = pattern.search(r.text).group(1)

json_data=json.loads(data)

returnjson_data

deflogin_and_send(self, text):

prelogin_data=self.get_prelogin_data()

data={

"entry":"weibo",

"gateway":"1",

"from":"",

"savestate":"7",

"qrcode_flase":"false",

"useticket":"1",

"pagerefer":r"http://passport.weibo.com/visitor/visitor?entry=miniblog&a=enter&url=http%3A%2F%2Fweibo.com%2F&domain=.weibo.com&ua=php-sso_sdk_client-0.6.14",

"vsnf":"1",

"su":self.encrypted_username(),

"service":"miniblog",

"servertime":prelogin_data['servertime'],

"nonce":prelogin_data['nonce'],

"pwencode":"rsa2",

"rsakv":prelogin_data['rsakv'],

"sp":self.encrypted_password(),

"sr":"1680*1050",

"encoding":"UTF-8",

"prelt":"122",

"url":"https://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack",

"returntype":"META"

}

url ='http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.18)'

headers = {

"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36"

}

#設定發微博時需要提交的表單

weibo_data={

"location":"v6_content_home",

"appkey":"",

"style_type":"1",

"pic_id":"",

"text": text,

"pdetail":"",

"rank":"1",#設定僅自己可見,如果對所有人可見改為0

"rankid":"",

"module":"stissue",

"pub_type":"dialog",

"_t":"0",

}

weibo_headers = {

"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36",

"referer":""

}

withrequests.Session()assess:

r=sess.post(url, headers=headers, data=data, timeout=2, allow_redirects=True)

pattern1=re.compile(r"location\.replace\(\'(.*)\'\)")

pattern2=re.compile(r"userdomain\":\"(.*)\"},")

redirent_url=pattern1.search(r.content.decode("GBK")).group(1)

r1=sess.get(redirent_url)

login_url="https://weibo.com/"+ pattern2.search(r1.content.decode("utf-8")).group(1)

r2=sess.get(login_url)

weibo_headers["referer"]=r2.url

login_url1="https://weibo.com/aj/mblog/add?ajwvr=6&__rnd="+str(int(time.time()*1000))

r3=sess.post(login_url1, headers=weibo_headers, data=weibo_data, timeout=2)

if(r3.status_code==requests.codes.ok):

print("send weibo successfully!!!")

else:

print("there is something wrong!!!")

if__name__ =='__main__':

wb=weibo("***","***")

wb.login_login_send("這是一段測試文字")

然後你不用申請key也能寫個自動發微博的程式了,當然能申請key最好啦。

監測新聞網站,自動發微博

這一點實現很簡單,定義幾個關鍵詞,每隔60s爬取一次新聞網站,如果新出的新聞標題中包含關鍵詞,就把新聞的標題和連結發到微博,程式的實現如下:

importre

importrequests

frombs4importBeautifulSoup

importtime

fromWeiboimportweibo

KEYWORDS = ["BTS","방탄소넌단","김석진","김남준","민윤기","정호석","박지민","김태형","전정국"]

classNewsSpider(object):

"""docstring for NewsSpider"""

def__init__(self):

super(NewsSpider, self).__init__()

self.url=["http://www.instiz.net/pt","http://www.instiz.net/clip"]

self.newslist=[]

self.wb=weibo("***","***")

print("complete initializing")

defcheckkeywords(self, title):

isinclude=False

forkeywordsinKEYWORDS:

ifkeywordsintitle:

isinclude=True

returnisinclude

defupdatenewslist(self, url):

withrequests.Session()assess:

r=sess.get(url, timeout=2)

soup=BeautifulSoup(r.content,"lxml")

listsubject=soup.find_all(id="subject")

forsubjectinlistsubject:

pattern = re.compile(r'\d{6,7}')

href=subject.a.get('href')

id=pattern.search(href)

ifid.group():

title=subject.a.text

ifself.checkkeywords(title)andid.group()notinself.newslist:

self.newslist.append(id.group())

self.updateWeibo(url+"/"+id.group(), title)

defrunforever(self):

i=0

failnum=0

while(1):

try:

self.updatenewslist(self.url[i])# 兩個板塊,交替執行

failnum=0

exceptExceptionase:

# 如果由於某些問題連續失敗,比如ip被ban,記錄失敗次數,連續60次失敗通知

failnum=failnum+1

iffailnum>=60:

print("There is something wrong with your code!!!")

failnum=0

finally:

i=(i+1)%2

time.sleep(30)

defupdateWeibo(self, newsurl, newstitle):

text="你的偶像們又有新訊息了:"+newstitle+"。詳情檢視連結->"+newsurl

print(text)

self.wb.login_and_send_message(text)

if__name__ =='__main__':

ns=NewsSpider()

ns.runforever()

具體效果如圖:

後記

當我幫程式交到妹子手上 ,就沒有然後了。果然是badiaowuqing啊~

這波教程不點個贊,不關注一下說不過去吧?


對爬蟲技術感興趣的同學可以加群705673780,一起探討,交流學習~


這邊是我的一個微信公眾號,分享Python最新技術,學習方法的一個公眾號,有興趣的朋友可以關注一哈