Python selenium 爬取網(wǎng)易云個(gè)人動(dòng)態(tài)

因?yàn)閷?duì)request,cooick等不甚了解,所以選用最簡(jiǎn)單的selenium爬取

selenium 的特點(diǎn)是所見即所得,爬取到的網(wǎng)頁(yè)結(jié)構(gòu)和正常加載的一樣
配置也很簡(jiǎn)單,使用driver將谷歌瀏覽器驅(qū)動(dòng)起來即可

功能需求很簡(jiǎn)單:

  1. 爬取個(gè)人的動(dòng)態(tài)
  2. 保存至數(shù)據(jù)庫(kù)
  3. 如果檢測(cè)到更,新通過郵件通知

一 分析個(gè)人界面的網(wǎng)頁(yè)url:

https://music.163.com/#/user/event?id=XXXXXXXXXXXXXX

可以看出 id 后面的XXXXXXXX(位數(shù)不固定)標(biāo)識(shí)了每個(gè)用戶,想要更換用戶只需要找到對(duì)應(yīng)用戶的id即可

二 分析網(wǎng)頁(yè)結(jié)構(gòu):

可以很容的看出 網(wǎng)頁(yè)的結(jié)構(gòu)為如下

注意: ??爬取時(shí)需要從frame 切換到 iframe

<iframe>
      <html>    
                <div>.........</div> //為要爬取的內(nèi)容
     </html>
</iframe>

三 分析如何獲取元素:

selenium提供了方法有很多,因?yàn)橛械膁iv的id是隨機(jī)生成的,class結(jié)構(gòu)也比較復(fù)雜;我使用了full xpath的方法,獲取方法也比較簡(jiǎn)單,只需要使用chrome瀏覽器,

在網(wǎng)頁(yè)任意位置單擊左鍵 --> 點(diǎn)擊檢查 --> 選中要獲取的元素標(biāo)簽可以是<div> ,<li>,<a>,<span >--> 再次點(diǎn)擊左鍵 --> 選擇copy --> 選擇copy full xpath

此時(shí)會(huì)得到如下的串:
是該元素從網(wǎng)頁(yè)<html>標(biāo)簽下的結(jié)構(gòu)

/html/body/div[3]/div/div[2]/div[1]/div/div/div/div/ul/li[1]/div[2]/div/div[4]/div/div/div[2]/h3/a

通過.text方法即可獲取其中的內(nèi)容

源碼:

import re
from datetime import datetime,timedelta
import smtplib
from email.mime.text import MIMEText
from email.header import Header

from selenium.webdriver.chrome.options import Options
from selenium import webdriver
import pymysql

"""
 selenium 模塊 爬去動(dòng)態(tài)返回入庫(kù)系統(tǒng)需要的基本信息
"""
def eye (url):
    # 配置谷歌瀏覽器無界面運(yùn)行
    chrome_options = Options()
    chrome_options.add_argument('--no-sandbox')
    chrome_options.add_argument('--disable-dev-shm-usage')
    chrome_options.add_argument('--headless')
    chrome_options.add_argument('blink-settings=imagesEnabled=false')
    chrome_options.add_argument('--disable-gpu')
    chrome_options.add_experimental_option("excludeSwitches", ["ignore-certificate-errors",
                                                               "enable-automation"])
    driver = webdriver.Chrome(chrome_options=chrome_options)
    driver.get(url)
    driver.implicitly_wait(1)  # 顯式等待1秒
    driver.switch_to.frame('contentFrame')  # 切入contentFrame

    ##使用 fullxpath獲取元素的內(nèi)容
    name_session = driver.find_elements_by_xpath('/html/body/div[3]/div/dl/dd/div[1]/div/h2/span[1]')
    name = name_session[0].text

    dynamic_session = driver.find_elements_by_xpath('/html/body/div[3]/div/dl/dd/ul/li[1]/a/strong')
    dynamic = dynamic_session[0].text

    addtimes_session = driver.find_elements_by_xpath(
        '/html/body/div[3]/div/div[2]/div[1]/div/div/div/div/ul/li/div[2]/div/div[2]/a')

    addtimes = []
    for item in addtimes_session:
        addtimes.append(item.text)

    comments_session = driver.find_elements_by_xpath(
        '/html/body/div[3]/div/div[2]/div[1]/div/div/div/div/ul/li/div[2]/div/div[3]')

    comments = []
    for item in comments_session:
        comments.append(item.text)

    songs_session = driver.find_elements_by_xpath(
        '/html/body/div[3]/div/div[2]/div[1]/div/div/div/div/ul/li/div[2]/div/div[4]/div/div/div[2]/h3/a')

    songs = []
    for item in songs_session:
        songs.append(item.text)

    singers_session = driver.find_elements_by_xpath(
        '/html/body/div[3]/div/div[2]/div[1]/div/div/div/div/ul/li/div[2]/div/div[4]/div/div/div[2]/h4/a')

    singers = []

    for item in singers_session:
        singers.append(item.text)

    driver.quit()
    return name,dynamic,addtimes,comments,songs,singers

"""
數(shù)據(jù)持久化模塊 將爬去的信息存儲(chǔ)到數(shù)據(jù)庫(kù)中
"""
def keep(url):
    flag= True
    email_message = ''
    error_message = ''
    name, dynamic, addtimes, comments, songs, singers = eye(url)
    db = pymysql.connect("XXXX", "root", "XXXXXX.", "數(shù)據(jù)庫(kù)名稱")
    cursor = db.cursor()
    cursor.execute("SELECT VERSION()")
    data = cursor.fetchone()
    print("Database version : %s " % data)
    #keep_eye_on_title_on 標(biāo)題內(nèi)容存入數(shù)據(jù)庫(kù)
    # 先檢察動(dòng)態(tài)數(shù)是否改變(不否認(rèn)刪除一條增加一條的情況祷安,但是我又懶得寫)

    sql = 'select dynamic  from eye_on_title order by `date` desc limit 1 '
    try:
        cursor.execute(sql)
        result = cursor.fetchall()
        dynamic_number = result[0][0]
        print("查詢成功")
    except:
        print("出錯(cuò)")
    if dynamic_number != dynamic:
        today = datetime.today()
        sql = "insert into eye_on_title (name,dynamic,date) values ( '%s',  '%s', '%s')" % (name, dynamic, today)
        print(sql)
        try:
            cursor.execute(sql)
            db.commit()
            print("保存成功")
            if dynamic == 0:
                email_message = email_message + "keep_an_eye_on失敗,計(jì)劃暴露或結(jié)束請(qǐng)求撤離" + dynamic 
            else:
                email_message = email_message + "提示:動(dòng)態(tài)更新  " + dynamic + "\n"
        except:
            db.rollback()
            print("出錯(cuò)")

        ##檢察更新
        for i in range(len(comments)):
            songName = re.sub(r'\'', "\\'", songs[i])  # 匹配掉 歌名中的 ' 單引號(hào)
            sql = "select * from eye_on_timeline where comment = '%s' and song  = '%s' " % (comments[i], songName)
            print(sql)
            cursor.execute(sql)
            result = cursor.fetchall()
            if result:
                print("此條動(dòng)態(tài)已存在")
                if i + 1 == len(comments):
                    error_message = " \n(刪除后未添加新的內(nèi)容) " + today.strftime(
                        "%m月%d日 %H:%M")  # 循環(huán)條件左開右閉 所以 i+1 才可以等于 len(comments)取巧寫法不好

            else:
                print("未檢測(cè)到此條動(dòng)態(tài)津滞,準(zhǔn)備寫入 ")

                ##處理時(shí)間問題
                if addtimes[i] == "剛剛":
                    print("剛剛")
                    addtime = (datetime.now() + timedelta(minutes=-1)).strftime("%m月%d日 %H:%M")
                    sql = "insert into eye_on_timeline (song,singer,`comment`,addtine)values('%s','%s','%s','%s') " % (
                    songName, singers[i], comments[i], addtime)

                elif (addtimes[i])[-3:] == "分鐘前":
                    print('分鐘前')
                    reducetime = (addtimes[i])[:-3]
                    print(reducetime, "計(jì)算時(shí)間")
                    addtime = (datetime.now() + timedelta(minutes=-int(reducetime))).strftime("%m月%d日 %H:%M")
                    sql = "insert into eye_on_timeline (song,singer,`comment`,addtine)values('%s','%s','%s','%s') " % (
                        songName, singers[i], comments[i], addtime)

                elif (addtimes[i])[:2] == "昨天":
                    print("昨天")
                    addtime = (datetime.now() + timedelta(days=-1)).strftime("%m月%d日 %H:%M")
                    sql = "insert into eye_on_timeline (song,singer,`comment`,addtine)values('%s','%s','%s','%s') " % (
                        songName, singers[i], comments[i], addtime)

                else:
                    sql = "insert into eye_on_timeline (song,singer,`comment`,addtine)values('%s','%s','%s','%s') " % (
                    songName, singers[i], comments[i], addtimes[i])

                print(sql)
                sql_message = ("分享歌曲: " + songs[i]) + ("  歌手: " + singers[i]) + ("  評(píng)論: " + comments[i] + "\n")
                email_message = email_message + sql_message
                try:
                    cursor.execute(sql)
                    db.commit()
                    print("保存成功")

                except:
                    db.rollback()
                    print("出錯(cuò)")
    else:
        print("沒有更新")
        flag = False
    db.close()

    return flag,email_message ,error_message

"""郵件模塊將檢測(cè)到的更新信息發(fā)送到郵箱內(nèi)提醒"""
def mail (email_message,url,error_message,flag):
    if flag == True:
        from_addr = 'XXXXXXXX@qq.com'  # 郵件發(fā)送賬號(hào)
        to_addrs = 'XXXXXXXXX@qq.com'  # 接收郵件賬號(hào)
        qqCode = 'XXXXXXX'  # 授權(quán)碼(這個(gè)要填自己獲取到的)
        smtp_server = 'smtp.qq.com'  # 固定寫死
        smtp_port = 465  # 固定端口

        # 配置服務(wù)器
        stmp = smtplib.SMTP_SSL(smtp_server, smtp_port)
        stmp.login(from_addr, qqCode)

        # 組裝發(fā)送內(nèi)容
        email_message = email_message + ("點(diǎn)擊查看:  " + url) + error_message

        print(email_message)

        message = MIMEText(email_message, 'plain', 'utf-8')  # 發(fā)送的內(nèi)容
        message['From'] = Header("EYE", 'utf-8')  # 發(fā)件人
        message['To'] = Header("boss", 'utf-8')  # 收件人
        subject = 'Keep_an_eye_on 計(jì)劃'
        message['Subject'] = Header('Keep_an_eye_on', 'utf-8')  # 郵件標(biāo)題

        try:
            stmp.sendmail(from_addr, to_addrs, message.as_string())
        except Exception as e:
            print('郵件發(fā)送失敗--' + str(e))
        print('郵件發(fā)送成功')

if __name__ == '__main__':
    url = 'https://music.163.com/#/user/event?id=XXXXXXXXX'#所要爬去的網(wǎng)易云動(dòng)態(tài)頁(yè)面
    flag,email_message ,error_message=keep(url)
    mail(email_message,url,error_message,flag)

"""整體有三大模塊:
1. 爬取模塊,使用selenium 爬取網(wǎng)易云的動(dòng)態(tài)上的基本信息
2. 入庫(kù)模塊,使用pymysql  將爬取到的信息存入數(shù)據(jù)庫(kù)
3. 郵件模塊,使用smtp     將數(shù)據(jù)發(fā)送到用戶郵箱以題型
4. 需要添加一個(gè)日志模塊 保證服務(wù)持久運(yùn)行谎砾,報(bào)錯(cuò)有據(jù)可循
"""

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末甲馋,一起剝皮案震驚了整個(gè)濱河市脯厨,隨后出現(xiàn)的幾起案子驱负,更是在濱河造成了極大的恐慌邑雅,老刑警劉巖片橡,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蒂阱,居然都是意外死亡锻全,警方通過查閱死者的電腦和手機(jī)狂塘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門录煤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人荞胡,你說我怎么就攤上這事妈踊。” “怎么了泪漂?”我有些...
    開封第一講書人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵廊营,是天一觀的道長(zhǎng)歪泳。 經(jīng)常有香客問我,道長(zhǎng)露筒,這世上最難降的妖魔是什么呐伞? 我笑而不...
    開封第一講書人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮慎式,結(jié)果婚禮上伶氢,老公的妹妹穿的比我還像新娘。我一直安慰自己瘪吏,他們只是感情好癣防,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著掌眠,像睡著了一般蕾盯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蓝丙,一...
    開封第一講書人閱讀 50,084評(píng)論 1 291
  • 那天级遭,我揣著相機(jī)與錄音,去河邊找鬼渺尘。 笑死装畅,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的沧烈。 我是一名探鬼主播掠兄,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼锌雀!你這毒婦竟也來了蚂夕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤腋逆,失蹤者是張志新(化名)和其女友劉穎婿牍,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惩歉,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡等脂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了撑蚌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片上遥。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖争涌,靈堂內(nèi)的尸體忽然破棺而出粉楚,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布模软,位于F島的核電站伟骨,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏燃异。R本人自食惡果不足惜携狭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望回俐。 院中可真熱鬧暑中,春花似錦、人聲如沸鲫剿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)灵莲。三九已至雕凹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間政冻,已是汗流浹背枚抵。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留明场,地道東北人汽摹。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像苦锨,于是被迫代替她去往敵國(guó)和親逼泣。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容