您好,登錄后才能下訂單哦!
作為互聯(lián)網(wǎng)界的兩個(gè)對(duì)立的物種,產(chǎn)品汪與程序猿似乎就像一對(duì)天生的死對(duì)頭;但是在產(chǎn)品開(kāi)發(fā)鏈條上緊密合作的雙方,只有通力合作,才能更好地推動(dòng)項(xiàng)目發(fā)展。那么產(chǎn)品經(jīng)理平日里面都在看那些文章呢?我們程序猿該如何投其所好呢?我爬取了人人都是產(chǎn)品經(jīng)理欄目下的所有文章,看看產(chǎn)品經(jīng)理都喜歡看什么。
1. 分析背景
1.1. 為什么選擇「人人都是產(chǎn)品經(jīng)理」
人人都是產(chǎn)品經(jīng)理是以產(chǎn)品經(jīng)理、運(yùn)營(yíng)為核心的學(xué)習(xí)、交流、分享平臺(tái),集媒體、培訓(xùn)、招聘、社群為一體,全方位服務(wù)產(chǎn)品人和運(yùn)營(yíng)人,成立8年舉辦在線講座500+期,線下分享會(huì)300+場(chǎng),產(chǎn)品經(jīng)理大會(huì)、運(yùn)營(yíng)大會(huì)20+場(chǎng),覆蓋北上廣深杭成都等15個(gè)城市,在行業(yè)有較高的影響力和知名度。平臺(tái)聚集了眾多BAT美團(tuán)京東滴滴360小米網(wǎng)易等知名互聯(lián)網(wǎng)公司產(chǎn)品總監(jiān)和運(yùn)營(yíng)總監(jiān)。選取這個(gè)社區(qū)更有代表性。
1.2. 分析內(nèi)容
1.3. 分析工具
2. 數(shù)據(jù)抓取
使用 Python編寫(xiě)的爬蟲(chóng)抓取了人人都是產(chǎn)品經(jīng)理社區(qū)的產(chǎn)品經(jīng)理欄目下的所有文章并保存為csv格式,文章抓取時(shí)期為 2012年6月至 2019 年 1月 21 日,共計(jì)6574篇文章。抓取 了 10 個(gè)字段信息:文章標(biāo)題、作者、作者簡(jiǎn)介、發(fā)文時(shí)間、瀏覽量、收藏量、點(diǎn)贊量、評(píng)論量、正文、文章鏈接。
2.1. 目標(biāo)網(wǎng)站分析
這是要爬取的網(wǎng)頁(yè)界面,可以看到是直接加載出來(lái)的,沒(méi)有AJAX,爬取起來(lái)毫無(wú)難度。
仔細(xì)觀察要爬取的網(wǎng)頁(yè),我們可以看到頁(yè)面連接有規(guī)律可循,連接中page后面的參數(shù)就是頁(yè)面數(shù),所以我們編寫(xiě)爬蟲(chóng)時(shí)可以直接用for循環(huán)來(lái)構(gòu)造所有頁(yè)面連接代碼如下:
1import requests
2from bs4 import BeautifulSoup
3import csv
4
5headers = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
6 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
7 'Cache-Control': 'max-age=0',
8 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36',
9 'Connection': 'keep-alive',
10 'Host': '[www.woshipm.com'](http://www.woshipm.com'),
11 'Cookie' : 't=MHpOYzlnMmp6dkFJTEVmS3pDeldrSWRTazlBOXpkRjBzRXpZOU4yVkNZWWl5QVhMVXBjMU5WcnpwQ2NCQS90ZkVsZ3lTU2Z0T3puVVZFWFRFOXR1TnVrbUV2UFlsQWxuemY4NG1wWFRYMENVdDRPQ1psK0NFZGJDZ0lsN3BQZmo%3D; s=Njg4NDkxLCwxNTQyMTk0MTEzMDI5LCxodHRwczovL3N0YXRpYy53b3NoaXBtLmNvbS9XWF9VXzIwMTgwNV8yMDE4MDUyMjE2MTcxN180OTQ0LmpwZz9pbWFnZVZpZXcyLzIvdy84MCwsJUU1JUE0JUE3JUU4JTk5JUJF; Hm_lvt_b85cbcc76e92e3fd79be8f2fed0f504f=1547467553,1547544101,1547874937,1547952696; Hm_lpvt_b85cbcc76e92e3fd79be8f2fed0f504f=1547953708'
12 }
13for page_number in range(1, 549):
14page_url = "[http://www.woshipm.com/category/pmd/page/](http://www.woshipm.com/category/pmd/page/){}".format(page_number)
15print('正在抓取第' + str(page_number) + '頁(yè)>>>')
16response = requests.get(url=page_url, headers=headers)
Python資源分享qun 784758214 ,內(nèi)有安裝包,PDF,學(xué)習(xí)視頻,這里是Python學(xué)習(xí)者的聚集地,零基礎(chǔ),進(jìn)階,都?xì)g迎
頁(yè)面連鏈接構(gòu)造完之后我們可以開(kāi)始爬取文章詳情頁(yè),提取所需要的信息,在這里用到的解析庫(kù)是BeautifulSoup,整個(gè)爬蟲(chóng)非常簡(jiǎn)單,
完整代碼如下:
<1#!/usr/bin/env python
2# -*- encoding: utf-8 -*-
3
4import requests
5from bs4 import BeautifulSoup
6import csv
7
8headers = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
9 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
10 'Cache-Control': 'max-age=0',
11 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36',
12 'Connection': 'keep-alive',
13 'Host': '[www.woshipm.com'](http://www.woshipm.com'),
14 'Cookie' : 't=MHpOYzlnMmp6dkFJTEVmS3pDeldrSWRTazlBOXpkRjBzRXpZOU4yVkNZWWl5QVhMVXBjMU5WcnpwQ2NCQS90ZkVsZ3lTU2Z0T3puVVZFWFRFOXR1TnVrbUV2UFlsQWxuemY4NG1wWFRYMENVdDRPQ1psK0NFZGJDZ0lsN3BQZmo%3D; s=Njg4NDkxLCwxNTQyMTk0MTEzMDI5LCxodHRwczovL3N0YXRpYy53b3NoaXBtLmNvbS9XWF9VXzIwMTgwNV8yMDE4MDUyMjE2MTcxN180OTQ0LmpwZz9pbWFnZVZpZXcyLzIvdy84MCwsJUU1JUE0JUE3JUU4JTk5JUJF; Hm_lvt_b85cbcc76e92e3fd79be8f2fed0f504f=1547467553,1547544101,1547874937,1547952696; Hm_lpvt_b85cbcc76e92e3fd79be8f2fed0f504f=1547953708'
15 }
16with open('data.csv', 'w', encoding='utf-8',newline='') as csvfile:
17 fieldnames = ['title', 'author', 'author_des', 'date', 'views', 'loves', 'zans', 'comment_num','art', 'url']
18 writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
19 writer.writeheader()
20 for page_number in range(1, 549):
21 page_url = "[http://www.woshipm.com/category/pmd/page/](http://www.woshipm.com/category/pmd/page/){}".format(page_number)
22 print('正在抓取第' + str(page_number) + '頁(yè)>>>')
23 response = requests.get(url=page_url, headers=headers)
24 if response.status_code == 200:
25 page_data = response.text
26 if page_data:
27 soup = BeautifulSoup(page_data, 'lxml')
28 article_urls = soup.find_all("h3", class_="post-title")
29 for item in article_urls:
30
31 url = item.find('a').get('href')
32 # 文章頁(yè)面解析,獲取文章標(biāo)題、作者、作者簡(jiǎn)介、日期、瀏覽量、收藏量、點(diǎn)贊量、評(píng)論量、正文、文章鏈接
33 response = requests.get(url=url, headers=headers)
34 # time.sleep(3)
35 print('正在抓?。? + url)
36 # print(response.status_code)
37 if response.status_code == 200:
38 article = response.text
39 # print(article)
40 if article:
41 try:
42 soup = BeautifulSoup(article, 'lxml')
43 # 文章標(biāo)題
44 title = soup.find(class_='article-title').get_text().strip()
45 # 作者
46 author = soup.find(class_='post-meta-items').find_previous_siblings()[1].find('a').get_text().strip()
47 # 作者簡(jiǎn)介
48 author_des = soup.find(class_='post-meta-items').find_previous_siblings()[0].get_text().strip()
49 # 日期
50 date = soup.find(class_='post-meta-items').find_all(class_='post-meta-item')[0].get_text().strip()
51 # 瀏覽量
52 views = soup.find(class_='post-meta-items').find_all(class_='post-meta-item')[1].get_text().strip()
53 # 收藏量
54 loves = soup.find(class_='post-meta-items').find_all(class_='post-meta-item')[2].get_text().strip()
55 # 點(diǎn)贊量
56 zans = soup.find(class_='post-meta-items').find_all(class_='post-meta-item')[3].get_text().strip()
57 # 評(píng)論量
58 comment = soup.find('ol', class_="comment-list").find_all('li')
59 comment_num = len(comment)
60 # 正文
61 art = soup.find(class_="grap").get_text().strip()
62
63 writer.writerow({'title':title, 'author':author, 'author_des':author_des, 'date':date, 'views':views, 'loves':int(loves), 'zans':int(zans), 'comment_num':int(comment_num), 'art':art, 'url':url})
64 print({'title':title, 'author':author, 'author_des':author_des, 'date':date, 'views':views, 'loves':loves, 'zans':zans, 'comment_num':comment_num})
65 except:
66 print('抓取失敗')
67 print("抓取完畢!")
在這里說(shuō)一點(diǎn),評(píng)論數(shù)的爬取,觀察文章詳情頁(yè)你可以發(fā)現(xiàn)并沒(méi)有評(píng)論數(shù),我這里是直接計(jì)算出來(lái)的,可以看到評(píng)論是嵌套在ol里面,抓起所有的li,然后就可以計(jì)算出,代碼如下:
1 # 評(píng)論量
2 comment = soup.find('ol', class_="comment-list").find_all('li')
3 comment_num = len(comment)
這樣,我們運(yùn)行一下爬蟲(chóng)就能夠順利爬取 594 頁(yè)的結(jié)果了,我這里一共抓取了 6574 條結(jié)果,大概也就玩了兩把吃雞就抓完了。
以上,就完成了數(shù)據(jù)的獲取。有了數(shù)據(jù)我們就可以著手分析,不過(guò)這之前還需簡(jiǎn)單地進(jìn)行一下數(shù)據(jù)的清洗、處理。
3. 數(shù)據(jù)清洗處理
首先,我們需要把csv文件轉(zhuǎn)換為 DataFrame。
1# 將csv數(shù)據(jù)轉(zhuǎn)為dataframe
2csv_file = "data.csv"
3csv_data = pd.read_csv(csv_file, low_memory=False) # 防止彈出警告
4csv_df = pd.DataFrame(csv_data)
5print(csv_df)
下面我們看一下數(shù)據(jù)的總體情況,可以看到數(shù)據(jù)的維度是 6574 行 × 10 列。需要將 views 列更改為數(shù)值格式、date 列更改為日期格式。
1print(csv_df.shape) # 查看行數(shù)和列數(shù)
2print(csv_df.info()) # 查看總體情況
3print(csv_df.head()) # 輸出前5行
4#運(yùn)行結(jié)果
5(6574, 10)
6<class 'pandas.core.frame.DataFrame'>
7RangeIndex: 6574 entries, 0 to 6573
8Data columns (total 10 columns):
9title 6574 non-null object
10author 6574 non-null object
11author_des 6135 non-null object
12date 6574 non-null object
13views 6574 non-null object
14loves 6574 non-null int64
15zans 6574 non-null int64
16comment_num 6574 non-null int64
17art 6574 non-null object
18url 6574 non-null object
19dtypes: int64(3), object(7)
20memory usage: 513.7+ KB
21None
22 title ... url
230 2018,我產(chǎn)品生涯的第二年是這樣度過(guò)的 ... [http://www.woshipm.com/pmd/1863343.html](http://www.woshipm.com/pmd/1863343.html)
241 從《啥是佩奇》提煉出的產(chǎn)品三部曲 ... [http://www.woshipm.com/pmd/1860832.html](http://www.woshipm.com/pmd/1860832.html)
252 “采坑,填坑”,項(xiàng)目的那些事兒(第六階段:測(cè)試驗(yàn)收) ... [http://www.woshipm.com/pmd/1859168.html](http://www.woshipm.com/pmd/1859168.html)
263 如何成為CEO信任的產(chǎn)品經(jīng)理? ... [http://www.woshipm.com/pmd/1857656.html](http://www.woshipm.com/pmd/1857656.html)
274 如何讓程序員放下手中的刀? ... [http://www.woshipm.com/pmd/1858879.html](http://www.woshipm.com/pmd/1858879.html)
28
29[5 rows x 10 columns]
date列更改為日期非常簡(jiǎn)單,代碼如下:
1# 修改date列時(shí)間,并轉(zhuǎn)換為 datetime 格式
2csv_df['date'] = pd.to_datetime(csv_df['date'])
views列處理思路是增加一列,名字就叫views_num吧,我們可以觀察到views列有的數(shù)值是整數(shù),有的則是1.7萬(wàn)這種,代碼如下:
1#!/usr/bin/env python
2# -*- encoding: utf-8 -*-
3
4import pandas as pd
5import numpy as np
6import matplotlib.pyplot as plt
7import seaborn as sns
8import re
9from wordcloud import WordCloud, STOPWORDS, ImageColorGenerator
10import jieba
11import os
12from PIL import Image
13from os import path
14from decimal import *
15
16#views列處理
17def views_to_num(item):
18 m = re.search('.*?(萬(wàn))',item['views'])
19 if m:
20 ns = item['views'][:-1]
21 nss = Decimal(ns)*10000
22 else:
23 nss = item['views']
24 return int(nss)
25
26# 數(shù)據(jù)清洗處理
27def parse_woshipm():
28 # 將csv數(shù)據(jù)轉(zhuǎn)為dataframe
29 csv_file = "data.csv"
30 csv_data = pd.read_csv(csv_file, low_memory=False) # 防止彈出警告
31 csv_df = pd.DataFrame(csv_data)
32 # print(csv_df.shape) # 查看行數(shù)和列數(shù)
33 # print(csv_df.info()) # 查看總體情況
34 # print(csv_df.head()) # 輸出前5行
35
36 # 修改date列時(shí)間,并轉(zhuǎn)換為 datetime 格式
37 csv_df['date'] = pd.to_datetime(csv_df['date'])
38 #將views字符串?dāng)?shù)字化,增加一列views_num
39 csv_df['views_num'] = csv_df.apply(views_to_num,axis = 1)
40 print(csv_df.info())
41
42
43if **name** == '**main**':
44 parse_woshipm()
我們?cè)佥敵鲆幌驴纯锤髁袛?shù)據(jù)類(lèi)型:
1<class 'pandas.core.frame.DataFrame'>
2RangeIndex: 6574 entries, 0 to 6573
3Data columns (total 11 columns):
4title 6574 non-null object
5author 6574 non-null object
6author_des 6135 non-null object
7date 6574 non-null datetime64[ns]
8views 6574 non-null object
9loves 6574 non-null int64
10zans 6574 non-null int64
11comment_num 6574 non-null int64
12art 6574 non-null object
13url 6574 non-null object
14views_num 6574 non-null int64
15dtypes: datetime64[ns](1), int64(4), object(6)
16memory usage: 565.0+ KB
17None
可以看到數(shù)據(jù)類(lèi)型已經(jīng)變成我們想要的了, 下面,我們看一下數(shù)據(jù)是否有重復(fù),如果有,那么需要?jiǎng)h除。
1# 判斷整行是否有重復(fù)值,如果運(yùn)行結(jié)果為T(mén)rue,表明有重復(fù)值
2# print(any(csv_df.duplicated()))
3# 顯示True,表明有重復(fù)值,進(jìn)一步提取出重復(fù)值數(shù)量
4data_duplicated = csv_df.duplicated().value_counts()
5# print(data_duplicated)
6#運(yùn)行結(jié)果
7# True
8# False
9# 6562
10# True
11# 12
12# dtype: int64
13# 刪除重復(fù)值
14data = csv_df.drop_duplicates(keep='first')
15# 刪除部分行后,index中斷,需重新設(shè)置index
16data = data.reset_index(drop=True)
然后,我們?cè)僭黾觾闪袛?shù)據(jù),一列是文章標(biāo)題長(zhǎng)度列,一列是年份列,便于后面進(jìn)行分析。
1#增加標(biāo)題長(zhǎng)度列和年份列
2data['title_length'] = data['title'].apply(len)
3data['year'] = data['date'].dt.year
以上,就完成了基本的數(shù)據(jù)清洗處理過(guò)程,針對(duì)這些數(shù)據(jù)可以開(kāi)始進(jìn)行分析了。
4. 描述性數(shù)據(jù)分析
通常,數(shù)據(jù)分析主要分為四類(lèi): 「描述型分析」、「診斷型分析」「預(yù)測(cè)型分析」「規(guī)范型分析」?!该枋鲂头治觥故怯脕?lái)概括、表述事物整體狀況以及事物間關(guān)聯(lián)、類(lèi)屬關(guān)系的統(tǒng)計(jì)方法,是這四類(lèi)中最為常見(jiàn)的數(shù)據(jù)分析類(lèi)型。通過(guò)統(tǒng)計(jì)處理可以簡(jiǎn)潔地用幾個(gè)統(tǒng)計(jì)值來(lái)表示一組數(shù)據(jù)地集中性(如平均值、中位數(shù)和眾數(shù)等)和離散型(反映數(shù)據(jù)的波動(dòng)性大小,如方差、標(biāo)準(zhǔn)差等)。
這里,我們主要進(jìn)行描述性分析,數(shù)據(jù)主要為數(shù)值型數(shù)據(jù)(包括離散型變量和連續(xù)型變量)和文本數(shù)據(jù)。
4.1. 總體情況
先來(lái)看一下總體情況,使用了data.describe() 方法對(duì)數(shù)值型變量進(jìn)行統(tǒng)計(jì)分析。
mean 表示平均值,std表示標(biāo)準(zhǔn)差,從上面可以簡(jiǎn)要得出以下幾個(gè)結(jié)論:
對(duì)于非數(shù)值型變量(author、date),使用 describe() 方法會(huì)產(chǎn)生另外一種匯總統(tǒng)計(jì)。
1print(data['author'].describe())
2print(data['date'].describe())
3#結(jié)果
4count 6562
5unique 1531
6top Nairo
7freq 315
8Name: author, dtype: object
9count 6562
10unique 1827
11top 2015-01-29 00:00:00
12freq 16
13first 2012-11-25 00:00:00
14last 2019-01-21 00:00:00
15Name: date, dtype: object
Python資源分享qun 784758214 ,內(nèi)有安裝包,PDF,學(xué)習(xí)視頻,這里是Python學(xué)習(xí)者的聚集地,零基礎(chǔ),進(jìn)階,都?xì)g迎
unique 表示唯一值數(shù)量,top 表示出現(xiàn)次數(shù)最多的變量,freq 表示該變量出現(xiàn)的次數(shù),所以可以簡(jiǎn)單得出以下幾個(gè)結(jié)論:
4.2. 不同時(shí)期文章發(fā)布的數(shù)量變化
從圖中可以看到,網(wǎng)站文章發(fā)布數(shù)量在2012到2015年逐年遞增,增幅很大,這可能與網(wǎng)站的知名度提高有關(guān);2015年2季度之后比較平穩(wěn)。后面的分析代碼就不一一貼出,文末會(huì)留下代碼下載鏈接。
4.3. 文章瀏覽量 TOP10
接下來(lái),到了我們比較關(guān)心的問(wèn)題:幾萬(wàn)篇文章里,到底哪些文章寫(xiě)得比較好或者比較火
這里以閱讀量作為衡量標(biāo)準(zhǔn),排在第一的是《 小白產(chǎn)品經(jīng)理看產(chǎn)品:什么是互聯(lián)網(wǎng)產(chǎn)品》,第一名的瀏覽量遙遙領(lǐng)先于第二名,接近百萬(wàn),看來(lái)很多社區(qū)里面很多都是產(chǎn)品小白。而且看這幾篇文章標(biāo)題,貌似都是介紹什么是產(chǎn)品經(jīng)理,產(chǎn)品經(jīng)理干什么,看來(lái)社區(qū)里面初級(jí)產(chǎn)品挺多的。
4.4. 歷年文章收藏量 TOP3
在了解文章的總體排名之后,我們來(lái)看看歷年的文章排名是怎樣的。這里,每年選取了收藏量最多的 3 篇文章。
從圖中可以看出,2015年是的那篇文章收藏量是最多的,達(dá)到了2000,文章內(nèi)容則是后臺(tái)產(chǎn)品設(shè)計(jì),看來(lái)這篇文章里面干貨滿滿。
4.4.1. 最高產(chǎn)作者 TOP20
上面,我們從收藏量指標(biāo)進(jìn)行了分析,下面,我們關(guān)注一下發(fā)布文章的作者。前面提到發(fā)文最多的是Nairo,貢獻(xiàn)了315篇,這里我們看看還有哪些比較高產(chǎn)的作者。
可以看到第一名遙遙領(lǐng)先,是個(gè)狼人,大家可以關(guān)注一下這些優(yōu)質(zhì)作者。
4.4.2. 平均文章收藏量最多作者 TOP 10
我們關(guān)注一個(gè)作者除了是因?yàn)槲恼赂弋a(chǎn)以外,可能更看重的是其文章水準(zhǔn)。這里我們選擇「文章平均收藏量」(總收藏量/文章數(shù))這個(gè)指標(biāo),來(lái)看看文章水準(zhǔn)比較高的作者是哪些人。這里,為了避免出現(xiàn)「某作者只寫(xiě)了一篇高收藏率的文章」這種不能代表其真實(shí)水準(zhǔn)的情況,我們將篩選范圍定在至少發(fā)布過(guò) 5 篇文章的作者們。
對(duì)比這張圖和前面的發(fā)文數(shù)量排行榜,我們可以發(fā)現(xiàn)這張圖的作者均沒(méi)有上榜,相比于數(shù)量,質(zhì)量可能更重要吧。
4.5. 文章評(píng)論數(shù)最多 TOP10
說(shuō)完了收藏量。下面,我們?cè)賮?lái)看看評(píng)論數(shù)量最多的文章是哪些。
我們可以看到大部分都與初級(jí)產(chǎn)品有關(guān),而且我們可以看到評(píng)論多,收藏量也挺多的,我們進(jìn)一步探尋兩者之間關(guān)系。
我們可以發(fā)現(xiàn)絕大部分文章評(píng)論數(shù)和收藏量都很小。
4.6. 文章標(biāo)題長(zhǎng)度
下面,我們?cè)賮?lái)看看文章標(biāo)題的長(zhǎng)度和閱讀量之間有沒(méi)有什么關(guān)系。
我們可以看到文章標(biāo)題長(zhǎng)度在20左右時(shí)閱讀量普遍較高。
4.7. 文本分析
最后,我們從這 5 萬(wàn)篇文章中的正文內(nèi)容中看看產(chǎn)品經(jīng)理都在看什么。
我們可以看到設(shè)計(jì)、工作、數(shù)據(jù)、功能、需求、項(xiàng)目等都是產(chǎn)品經(jīng)理們關(guān)注的東西,產(chǎn)品們也很辛苦啊,程序猿以后不要吐槽自己多辛苦了。
5. 小結(jié)
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。