兄弟次乓!
是不是還單身?
想不想找女朋友孽水?
想不想拉著她在西安的街頭走一走,嗚哦嗚哦城看?
直到所有的燈都熄滅了女气,也不停留?
你會說测柠,當然想炼鞠,可是我在西電啊轰胁!
人家的校緣谒主,那可都是“愛”!
我們的校媛赃阀,呸霎肯,猿,都是“唉”伴凰埂观游!
還好我們有睿思,有論壇驮俗,有相親帖懂缕!
但是!
剛看上一個漂亮的小姐姐王凑,想加微信撩搪柑,人家就結(jié)帖了,結(jié)帖了索烹!
嗯工碾?不知道結(jié)帖啥意思,看圖术荤!
對倚喂!就是這樣!
人家已經(jīng)被身披金甲圣衣,腳踏七彩祥云的蓋世英雄給追到手了端圈!
那你的余生是不是就只能找個男的湊合過日子了焦读?
不!
身為肩負拯救世界重任的好心人舱权,也就是我矗晃,不會讓這種事發(fā)生的!
喏宴倍!
現(xiàn)在你可以在微信端實時接收最新的帖子啦脖律!
她只要一在緣聚睿思版塊發(fā)出求偶信號,你就可以在第颁湖!一屎媳!時!間阔逼!腆著個大臉過去撩了兆衅!
效果如下:
sorry,放錯圖了嗜浮,是下面這張羡亩!
只要經(jīng)過一些簡單的配置,就可以享受這種黃金VIP級的待遇了危融!
沒辦法畏铆,誰讓我人好,下面我就開始整了吉殃!
參考文檔與博客
[1] BeautifulSoup中文文檔
[2] itchat應用教程
[3] 校招提醒機器人-肖灑
環(huán)境部署
Anaconda是一個開源的python發(fā)行版本辞居,個人習慣用python3,所以用的是Anaconda3寨腔。下載并安裝好Anaconda3之后速侈,python3、python3常用的依賴包迫卢、開發(fā)環(huán)境就都有了倚搬,開發(fā)環(huán)境習慣用jupyter notebook,當然其他的也可以乾蛤。
另外還要用到兩個包每界,BeautifulSoup和itchat,分別用于頁面解析家卖、與微信端交互眨层,用pip安裝,方法如下:
pip3 install beautifulsoup4
pip3 install itchat
解析相親帖
某位女嘉賓的帖子是這樣的
既有文本上荡,又有照片趴樱,所以馒闷,按照套路,先導入所有要用到的包
from bs4 import BeautifulSoup#解析頁面叁征,第三方包
import urllib.request#請求網(wǎng)頁
import itchat#用于微信端交互纳账,第三方包
import time#定時器,python自帶
import os#用于創(chuàng)建文件夾捺疼,python自帶
import shutil#用于遞歸刪除文件夾疏虫,python自帶
解析頁面,這里就直接引用大神校招提醒機器人-肖灑的代碼了
def getPageContent(url):
#偽裝瀏覽器
headers = {
#瀏覽器信息啤呼,我用的是chrome
'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36',
#因為睿思論壇要先登錄才能訪問相親帖卧秘,故要加入cookie,每個人的cookie都不同
'Cookie' : 'Q8qA_2132_saltkey=Qdmt1tYy; Q8qA_2132_lastvisit=1529493180; Q8qA_2132_ulastactivity=4a18XdrzuW602gpzpKQEU5prg6bxSTeIM7hEYMDp7k6uJ%2BnogwMZ; Q8qA_2132_lastcheckfeed=304070%7C1529496798; Q8qA_2132_myrepeat_rr=R0; Q8qA_2132_auth=770aHvS7Tt2zInpFLb4FtNeIrYgHBY5rjKxZPFoXgWGhYTec%2BPuWoM19uou%2BdGLELy%2BnLJKub8Fg8Opp%2FJnNnHmM64E; Q8qA_2132_home_diymode=1; Q8qA_2132_nofavfid=1; Q8qA_2132_smile=4D1; Q8qA_2132_visitedfid=217D13D110; Q8qA_2132_st_t=304070%7C1529503019%7Cd72f8f898362e189f2b2780ed6e60c93; Q8qA_2132_forum_lastvisit=D_106_1529500683D_110_1529500694D_217_1529503019; Q8qA_2132_st_p=304070%7C1529503185%7C00734d0bcbe0384484f7216ada21fa02; Q8qA_2132_viewid=tid_945811; Q8qA_2132_sid=Pb9XCX; Q8qA_2132_lip=10.170.41.52%2C1529503691; Q8qA_2132_lastact=1529503776%09misc.php%09patch'
}
#請求頁面
req = urllib.request.Request(url=url,headers=headers)
try:
res = urllib.request.urlopen(req)
except urllib.error.URLError as e:
return e
page_content = res.read()
#用lxml方式解析網(wǎng)頁
page_content=BeautifulSoup(page_content,"lxml")
return page_content
先分析一下這個網(wǎng)頁官扣,既有文本翅敌,又有圖片,先分析文本怎么爬惕蹄。
定位到文本對應的網(wǎng)頁元素哼御,發(fā)現(xiàn)不同的字體對應不同的標簽,但所有文本都在td標簽下焊唬,即上圖中箭頭所指。只要想辦法定位到相應的td標簽下看靠,用get_text()就可以得到所有文本了赶促。但直接使用get_text()方法還會包含一些“最后發(fā)帖由誰在什么時間完成”之類的雜七雜八的文字,所以在代碼中要對這些無關(guān)文字再刪除挟炬。
對于圖片鸥滨,我們先定位圖片的url,它長這樣
./data/attachment/forum/201805/15/212638i0ktdwi1c9298wix.jpg
沒有以http打頭谤祖,一看就是相對路徑婿滓,但相對路徑瀏覽器不能識別哇,怎么得到絕對路徑粥喜?
考慮到當前的url凸主,也就是地址欄中的地址,它是這樣什兒的:
http://rs.xidian.edu.cn/forum.php?mod=viewthread&tid=937063&extra=page%3D1%26filter%3Dlastpost%26orderby%3Dlastpost
而./data又表示先跳到上一級再定位到data目錄额湘,所以圖片在服務器中完整的絕對路徑應該是把http://rs.xidian.edu.cn/后面的內(nèi)容替換成data/attachment/forum/201805/15/212638i0ktdwi1c9298wix.jpg卿吐,即
http://rs.xidian.edu.cn/data/attachment/forum/201805/15/212638i0ktdwi1c9298wix.jpg
寫一個函數(shù)來實現(xiàn)這種替換功能
def urlJoin(urlCur, urlImg):
#urlCur = 'http://rs.xidian.edu.cn/forum.php?mod=viewthread&tid=947526&extra=page%3D1%26filter%3Dlastpost%26orderby%3Dlastpost&page=1'
#urlImg = './data/attachment/forum/201806/20/235708qtq25ommzqqruoa9.jpg'
a = urlCur.split('/')
b = urlImg.split('/')
url = ''
for i in a[:-1]:
url += i + '/'
for i in b[1:]:
url += i + '/'
return url[:-1]
現(xiàn)在,文本的內(nèi)容和圖片的地址我們都知道怎么爬取了锋华,寫個函數(shù)來實現(xiàn)它:
#urlCur為當前帖子的url嗡官,titleCur為帖子標題,nth為當前帖子是第幾個人
def getInfo(urlCur, titleCur, nth):
#解析網(wǎng)頁
page_content = getPageContent(urlCur)
#定位td標簽
contents = page_content.find_all('td',class_='t_f')
subpage = contents[0]
#定位圖片毯焕,把所有圖片的url放到imageList中
images = subpage.select('ignore_js_op')
imageList = []
for i in images:
urlImg = i.find_all('img')[0].get('file')
imageList.append(urlJoin(urlCur, urlImg))
#刪除無關(guān)文字
while(subpage.i!=None):
subpage.i.extract()
while(subpage.ignore_js_op!=None):
subpage.ignore_js_op.extract()
info = subpage.get_text().strip()
text = '『緣聚睿思【%d】——阿健的爬蟲』\n\n' % nth
text += '標題:' + titleCur + '\n\n'
#刪除無關(guān)的回車和空格衍腥,得到最終的文本text
infoSplits = info.splitlines()
for tt in infoSplits:
if len(tt.strip()) == 0:
infoSplits.remove(tt)
for tt in infoSplits:
text += tt + '\n'
return text, imageList
好,對于文本,我們可以直接使用了婆咸,但圖片的話要先下載下來才能使用竹捉。下載之前,我們先在當前目錄創(chuàng)建一個文件夾
def mkdir(path):
# 去除首位空格
path=path.strip()
# 去除尾部 \ 符號
path=path.rstrip("\\")
# 判斷路徑是否存在
isExists=os.path.exists(path)
# 要是存在擅耽,先刪掉
text = ''
if isExists:
shutil.rmtree(path)
text += ' has been deleted and'
#創(chuàng)建文件夾
os.makedirs(path)
print(path + text + ' created successfully!')
再把這個寶寶所有的照片下載下來
# 傳入照片url列表和文件夾名活孩,下載照片,返回照片數(shù)
def downloadImgs(imageList, pathName):
# 如果沒有照片乖仇,返回照片數(shù)0
if len(imageList) == 0:
return 0
# 創(chuàng)建文件夾
mkdir(pathName)
# 照片id憾儒,保存時取名用
imgID = 0
# 保存所有照片
for image in imageList:
imgID += 1
urllib.request.urlretrieve(image, "%s/%d.jpg" % (pathName,imgID))
numImgs = imgID
# 返回照片數(shù)
return numImgs
好了,當前這個寶寶的文本和圖片我們都有了乃沙,考慮一下怎么發(fā)送到微信起趾。我用了itchat這個包,登錄后警儒,可以把文本和圖片發(fā)送給自己训裆、好友和群聊,功能很強大蜀铲,詳情請參考itchat應用教程或校招提醒機器人-肖灑的通俗解釋边琉。直接上代碼:
'''
輸入要發(fā)送的文本,圖片路徑记劝,圖片數(shù)量变姨,發(fā)送對象
com=1,發(fā)送給自己
com=2厌丑,發(fā)送給好友
com=3定欧,發(fā)送給群聊
'''
def wx(info, pathName, numImgs, com):
itchat.auto_login(hotReload = True)# 可設置hotReload = True
if com == 1:
userName = 'filehelper'
elif com == 2:
userName = itchat.search_friends(name=u'碩士-徐賽')[0]["UserName"]
else:
i = itchat.get_chatrooms(update=True)
name = "這一家子不簡單"
iRoom = itchat.search_chatrooms(name)
for room in iRoom:
if room['NickName'] == name:
userName = room['UserName']
break
itchat.send_msg(info, userName)
if numImgs == 0:
itchat.send_msg('【TA暫時沒有美照】', userName)
else:
for i in range(0, numImgs):
path = pathName + '/' + str(i+1) + '.jpg'
itchat.send_image(path,toUserName=userName)
這個函數(shù)運行時,會像微信電腦版一樣提醒你在手機端登錄怒竿,登錄后就能自動把信息發(fā)送到指定對象了砍鸠。
好,現(xiàn)在耕驰,對某個寶寶爷辱,我們可以爬取信息并發(fā)送到微信了,再考慮爬取其他寶寶的信息朦肘⊥邢回到緣聚睿思版塊,按帖子發(fā)布時間排序厚骗,它是這樣的
我們只爬取普通帖示启,不爬取投票帖(就是圖中洗澡尿尿的那個,我也是醉了)领舰,區(qū)別就在于標題前面的圖標不同夫嗓。那就通過普通帖的圖標迟螺,定位到該帖,我們要得到3個信息舍咖,該帖的標題矩父、id和url。
標題就不用說了排霉,url也好說窍株,就是為了跳轉(zhuǎn)到帖子內(nèi)部去爬取文本內(nèi)容和圖片的,最重要的是id攻柠,每個帖子都有自己的id球订。因為我們要循環(huán)爬取帖子,為了避免重復抓取瑰钮,必須要在爬取前判斷該帖是否已經(jīng)爬過冒滩,所以一定到得到每個帖子的唯一標識id!
# 論壇網(wǎng)址和每次要爬取的帖子數(shù)量
# 輸出每個帖子的url浪谴、id开睡、標題
def getUrlList(urlHome, numInfo):
page_content = getPageContent(urlHome)
subContents = page_content.find_all('img',{'src':'static/image/common/folder_new.gif'})
urlList = []
idList = []
titleList = []
for i in subContents:
urlList.append('http://rs.xidian.edu.cn/' + i.parent.get('href'))
idList.append(i.parent.parent.parent.parent.get('id'))
titleList.append(i.parent.parent.parent.find_all('a',{'class':'s xst'})[0].get_text())
return urlList[:numInfo],idList[:numInfo],titleList[:numInfo]
再寫一個函數(shù),來實現(xiàn)得到所有寶寶帖子的鏈接苟耻、爬取每個寶寶的信息篇恒、把信息發(fā)送到微信的功能。
# 輸入:論壇地址凶杖,爬取過的寶寶的id記錄婚度,這是第幾個寶寶,要爬幾個寶寶官卡,發(fā)送給誰
# 返回:爬取過的寶寶的id記錄,這是第幾個寶寶
def xdLoveEachTime(urlHome, idList, nth, numInfo,com):
[urlList,curIdList,curTitleList] = getUrlList(urlHome, numInfo)
for urlCur,idCur,titleCur in zip(urlList,curIdList,curTitleList):
if idCur in idList:
continue
else:
idList.append(idCur)
[info, imageList] = getInfo(urlCur,titleCur, nth)
pathName = 'images'
numImgs = downloadImgs(imageList, pathName)
wx(info,pathName,numImgs,com)
nth += 1
return idList,nth
好醋虏,只要給定輸入寻咒,運行xdLoveEachTime函數(shù),就能在微信端獲取每個寶寶的信息了颈嚼,但我們希望能實時獲取最新寶寶的信息毛秘,那就加個定時器,每隔一段時間運行一次阻课,保證能拿到第一手的資料叫挟。
寫一個主函數(shù),把前面所有的功能都封裝好限煞,每次要爬幾個人抹恳、發(fā)送給誰等,完全由這個主函數(shù)控制署驻,不再需要去修改其他函數(shù)的信息
# 輸入:論壇網(wǎng)址奋献,發(fā)送對象健霹,要爬取幾個人,隔多長時間爬取一次
def xdLove(urlHome,com=1,numInfo=1,sleepTime=60):
idList = []
nth = 1
# 這里可以改成while(true)死循環(huán)
for i in range(1000):
[idList,nth] = xdLoveEachTime(urlHome,idList,nth,numInfo,com)
print('阿健的爬蟲已爬取' + str(i+1) + '次')
time.sleep(sleepTime)
最后瓶蚂,運行主函數(shù)就可以了
# 注意論壇的網(wǎng)址一定是這個糖埋,這是按發(fā)帖時間排序的
urlHome = 'http://rs.xidian.edu.cn/forum.php?mod=forumdisplay&fid=217&filter=author&orderby=dateline'
xdLove(urlHome)
后臺的運行界面是這樣的
微信端效果參考前面的圖片。
至此窃这,我們已經(jīng)實現(xiàn)了從微信端實時獲取睿思最新相親帖的功能了⊥穑現(xiàn)在,你就可以等著喜歡的女嘉賓登場了杭攻,是不是有種翻牌兒的感覺~
不過祟敛,還是很多地方需要改進一下的:
獲取的寶寶是男是女都有可能,我希望每次推薦的寶寶都是女生
即使是在普通帖子中朴上,也會有很多租房帖子之類奇葩帖垒棋,我不想看到這些東西
我希望帖主對帖子更新后,我也能看到更新信息痪宰。比如叼架,某位女嘉賓希望找一米八的,但后來降低了要求衣撬,更新了帖子乖订,改成了一米二的,那我就符合條件啦~
前兩個功能可能會加一些自然語言處理的算法來預測一下具练,再判斷是否過濾乍构,還是很有挑戰(zhàn)性的;第三個功能其實還不確定是否能看到更新帖扛点,這個就再說吧~