1. 程式人生 > >Python 爬取愛奇藝 52432 條資料分析

Python 爬取愛奇藝 52432 條資料分析

 

爬取資料

 

奇葩說是愛奇藝獨播視訊,所以這一次,筆者選取官方評論資料作為資源庫,來進行資料分析。

使用 Chrome 檢視原始碼模式,在“奇葩說”播放頁面往下面滑動,有一個get_comments 的請求,經過分析,這個介面就是獲取評論資料的介面。

看一下介面地址和請求引數:

介面地址:
http://sns-comment.iqiyi.com/v3/comment/get_comments.action

引數:
"types":"time"
"business_type":"17"
"agent_type":"119"
"agent_version":"9.9.0"
"authcookie":"cookie"
"last_id": ""
"content_id": ""

 

其中 last_id 是用來進行分頁的。

  • 使用 Python 獲取資料

上面的請求使用的 GET 方式,請求程式碼如下:

def saveMoveInfoToFile(movieId, movieName, lastId):
    url = "http://sns-comment.iqiyi.com/v3/comment/get_comments.action?"
    params = {
        "types":"time",
        "business_type":"17",
        "agent_type":"119",
        "agent_version":"9.9.0",
        "authcookie":"authcookie"
    }
    if lastId != "":
        params["last_id"] =  lastId
    for item in params:
        url = url + item + "=" + params[item] + "&"
    url = url + "content_id=" + movieId
    responseTxt = getMoveinfo(url)

def getMoveinfo(url):
    session = requests.Session()
    headers = {
        "User-Agent": "Mozilla/5.0",
        "Accept": "application/json",
        "Referer": "http://m.iqiyi.com/v_19rqriflzg.html",
        "Origin": "http://m.iqiyi.com",
        "Host": "sns-comment.iqiyi.com",
        "Connection": "keep-alive",
        "Accept-Language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,zh-TW;q=0.6",
        "Accept-Encoding": "gzip, deflate"
    }
    response = session.get(url, headers=headers)
    if response.status_code == 200:
        return response.text
    return None

 

請求返回的資料是 JSON ,這裡筆者就不貼返回資料,直接解析儲存。本處,筆者使用 SQLite3 進行資料儲存。

  • 解析資料

def parseData(movieId, movieName, htmlContent):
    data = json.loads(htmlContent)['data']['comments']
    lastId = "-1"
    if json.dumps(data) == "[]":
        return lastId
    lastId = "-1"
    for item in data:
        originalData = json.dumps(item)
        saveOriginalDataToDatabase(item["id"], movieId, movieName, originalData)
        lastId = item['id']
    return lastId

 

為了更方便後續進行資料分析,所以將拉下來的評論資料全部進行儲存,防止多次去爬取資料。

資料儲存在資料庫中非常簡單,一個簡單的 insert 語句就可以搞定。程式碼如下:

def saveOriginalDataToDatabase(msgId, movieId, movieName, originalData):
    conn = sqlite3.connect('i_can_i_bb.db')
    conn.text_factory = str
    cursor = conn.cursor()
    ins="insert into originalData values (?,?,?,?)"
    v = (movieId+ "_" + msgId, movieId, originalData, movieName)
    cursor.execute(ins, v)
    cursor.close()
    conn.commit()
    conn.close()

 

本次總共從愛奇藝抓取了 52432 條評論資料。

 

資料清洗與整理

 

從愛奇藝抓取的資料,並不是所有的資料我們都需要,這裡,只需將我們想要的資料提取出來。

  • 提取資料

此處將使用者的個人資訊、評論、評論時間、性別等資料提取出來,儲存到另一張表中。後續資料分析就從新的表中拿取就可以了,處理邏輯如下:

def saveRealItem(id, originalData):
    user = json.loads(originalData)
    conn = sqlite3.connect('deal_data.db')
    conn.text_factory = str
    cursor = conn.cursor()
    ins="insert into realData values (?,?,?,?,?,?,?,?)"
    content = ""
    if user.has_key("content"):
        content = user["content"]
    v = (id, content, user["userInfo"]["gender"], user["addTime"], user["userInfo"]["uname"], user["userInfo"]["uid"], user["id"], user["userInfo"]["uidType"])
    cursor.execute(ins, v)
    cursor.close()
    conn.commit()
    conn.close()

## 轉換資料
if __name__ == '__main__':
    conn = sqlite3.connect('i_can_i_bb.db')
    conn.text_factory = str
    cursor = conn.cursor()
    cursor.execute("select * from originalData")
    values = cursor.fetchall()
    for item in values:
        saveRealItem(item[0], item[2])
    cursor.close()
    conn.commit()
    conn.close()

 

  • 分析資料

在海量的資料中,我們可以分析出我們想看到的結果。為了更好的資料處理和視覺化展示,筆者使用了 Pandas 和 Pyecharts 這兩個庫,很好用。

因愛奇藝使用者資料維度有限,所以只能簡單地分析性別。來綜合看一下,奇葩說使用者的男女比例。話不多說,先放程式碼:

conn = sqlite3.connect('deal_data.db')
conn.text_factory = str
data = pd.read_sql("select * from realData", conn)
genderData = data.groupby(['gender'])
rateDataCount = genderData["id"].agg([ "count"])
rateDataCount.reset_index(inplace=True)
print rateDataCount
attr = ["女", "男"]
v1 = [rateDataCount["count"][i] for i in range(0, rateDataCount.shape[0])]
pie = Pie("性別比例")
pie.add("", attr, v1, is_label_show=True)
pie.render("html/gender.html")
conn.commit()
conn.close()    

 

使用 Pyecharts 畫了一個簡單的餅圖:

 

男女比例圖

從圖中可以看出來,男女比例差不多到 1:2,看奇葩說的女性使用者,比男性使用者要多很多。也許,這也是這一季奇葩說情感話題比較多的一大原因。

接下來,我們再來看一下,每一期的評論數量,看是否能夠得出一些不一樣的資料。

還是先上程式碼:

conn = sqlite3.connect('deal_data.db')
conn.text_factory = str
data = pd.read_sql("select * from realData", conn)
movieIdData = data.groupby(['movieId'])
commentDataCount = movieIdData["movieId"].agg([ "count"])
commentDataCount.reset_index(inplace=True)
print commentDataCount
movies = {
    "1629260900":u"第 22 期",
    "1629256800":u"第 21 期",
    ## 後面的資料,這裡不列出來
}
attr = [movies[commentDataCount["movieId"][i]] for i in range(0, commentDataCount.shape[0])]
v1 = [commentDataCount["count"][i] for i in range(0, commentDataCount.shape[0])]
bar = Bar("評論數量")
bar.add("數量",attr,v1,is_stack=True,xaxis_rotate=30,yaxix_min=4.2,
        xaxis_interval=0,is_splitline_show=True,is_label_show=True)
bar.render("html/comment_count.html")
conn.commit()
conn.close()

 

跑出來的資料如下:

每期評論數量

從圖中的資料我們可以看到,評論數量並不會因為更新早而變得更多。所以可以看出,奇葩說的使用者群體是相對穩定的。不僅如此,我們也可以看出,在第 17 期評論數量比其他都要多,很有可能是這一期節目的話題更讓使用者關注。

分析了上面的兩個資料,下面再分析一下評論時間分佈,本次分析是按照星期來分析的,所以,還需要對資料進行一定的處理。將每一條評論所在星期更新到資料庫中,程式碼如下:

conn = sqlite3.connect('deal_data.db')
conn.text_factory = str
cursor = conn.cursor()
cursor.execute("select * from realData")
values = cursor.fetchall()
cursor.close()
for item in values:
    realTime = time.localtime(float(item[3]))
    realTime = time.strftime("%A",realTime)
    sql = "UPDATE `realData` SET `week`=\"" + realTime + "\" WHERE `id`=\"" + item[0] + "\""
    cc = conn.cursor()
    cc.execute(sql)
    cc.close()
    conn.commit()
    conn.close()
    time.localtime()

 

使用折線圖分析如下:

conn = sqlite3.connect('deal_data.db')
conn.text_factory = str
data = pd.read_sql("select * from realData", conn)
movieIdData = data.groupby(['week'])
commentDataCount = movieIdData["week"].agg([ "count"])
commentDataCount.reset_index(inplace=True)
print commentDataCount
weekInfo = {
    "Monday":u"週一",
    "Tuesday":u"週二",
    "Wednesday":u"週三",
    "Thursday":u"週四",
    "Friday":u"週五",
    "Saturday":u"週六",
    "Sunday":u"週日"
}
weeks = [
    "Monday",
    "Tuesday",
    "Wednesday",
    "Thursday",
    "Friday",
    "Saturday","Sunday"
]
attr = []
v1 = []
week_temp = [commentDataCount["week"][i] for i in range(0, commentDataCount.shape[0])]
for item in weeks:
    attr.append(weekInfo[item])
    index = week_temp.index(item)
    v1.append(commentDataCount["count"][index])
    bar = Line("天評論數量")
    bar.add("數量",attr,v1,is_stack=True,xaxis_rotate=30,yaxix_min=4.2,
            xaxis_interval=0,is_splitline_show=True,is_label_show=True)
    bar.render("html/comment_week_count.html")

 

評論週期

可以看出,奇葩說的忠實使用者基本是在更新當天就看,並且週五、週六、週日的評論數量遠大於其他天。其實我們還可以分析,更新當天的 4 個小時內評論量有多大,感興趣的讀者可以嘗試去跑一下資料。

而作為一名程式設計師,筆者平時基本是不寫評論的,在這裡,我們特地分析了一下評論字數的分佈,不看不知道,一看嚇一跳。先上程式碼:

# 先獲取評論長度,並更新到資料庫中
conn = sqlite3.connect('deal_data.db')
conn.text_factory = str
cursor = conn.cursor()
cursor.execute("select * from realData")
values = cursor.fetchall()
cursor.close()
for item in values:
    content = item[1]
    length = 0
    if len(content) <= 20:
        length = 0
    elif len(content) > 20 and len(content) <= 50:
        length = 1
    elif len(content) > 50 and len(content) <= 100:
        length = 2
    else:
        length = 3
    sql = "UPDATE `realData` SET `length`=\"" + str(length) + "\" WHERE `id`=\"" + item[0] + "\""
    cc = conn.cursor()
    cc.execute(sql)
    cc.close() 
    conn.commit()
    conn.close()
    time.localtime()

# 獲取數量並展示
conn = sqlite3.connect('deal_data.db')
conn.text_factory = str
data = pd.read_sql("select * from realData", conn)
lengthData = data.groupby(['length'])
lengthDataCount = lengthData["movieId"].agg([ "count"])
lengthDataCount.reset_index(inplace=True)
print lengthDataCount
attr = ["20 字以內", "20~50 字", "50~100 字", "100 字以上"]
v1 = [lengthDataCount["count"][i] for i in range(0, lengthDataCount.shape[0])]
bar = Line("評論字數")
bar.add("數量",attr,v1,is_stack=True,xaxis_rotate=30,yaxix_min=4.2,
        xaxis_interval=0,is_splitline_show=True,is_label_show=True)
bar.render("html/comment_word_count.html")
conn.commit()
conn.close()

 

分析結果如下:

評論字數分析

實在是沒有想到,100 字以上的評論居然有 1/4,在這個移動端已成視訊播放主要平臺的時代,使用者還能夠花費較多精力寫下評論,筆者還是比較震驚的。

最後,筆者將通過 jieba 把評論進行分詞,然後再以 wordcloud 製作詞雲來看看,觀眾朋友的整體評價:

conn = sqlite3.connect('deal_data.db')
    conn.text_factory = str
    data = pd.read_sql("select * from realData", conn)
    jieba.add_word("馬薇薇", freq = 20000, tag = None)
    comment = jieba.cut(str(data["content"]),cut_all=False)
    wl_space_split = " ".join(comment)
    backgroudImage = np.array(Image.open(r"./qipashuo.jpg"))
    stopword = STOPWORDS.copy()
    wc = WordCloud(width=1920,height=1080,background_color='white',
        mask=backgroudImage,
        font_path="/Users/zhaocheng/Documents/Deng.ttf",
        stopwords=stopword,max_font_size=400,
        random_state=50)
    wc.generate_from_text(wl_space_split)
    plt.imshow(wc)
    plt.axis("off")
    wc.to_file('html/word_cloud.png')
    conn.commit()
    conn.close()

 

詞雲圖:

詞雲

通過上面的詞雲可以很明顯地看出,李誕、(薛)教授、(詹)青雲、馬薇薇、(傅)首爾等人物名稱高頻地出現在了評論裡面,他們才是這部綜藝的焦點人物。