Python模擬微博抽獎機制!中獎十個九個半女生?自動統計男女比例
今天來寫一個自動計算微博抽獎男女比例的程式碼,很早就應該發這篇了,只是不想蹭熱點(才不是拖更)。
整個的過程大概分為三步:
S1:從抽獎公示頁獲取所有中獎者的微博ID
S2:由每個中獎者的微博ID進入其相應主頁,獲得需要的個人資訊(性別、粉絲數、微博數等)
S3:對收集到的資訊進行相應的彙總分析
接下來一步一步地進行就好了,沒什麼難點和需要注意的地方,權當做是一次很小的練手。
首先每次微博抽獎都會有一個公示連結。形如:http://event.weibo.com/yae/event/lottery/result?pageid=100140E1204222&id=3538105&f=weibo
其中pageid和id兩個變數就可以定位一次抽獎。
中獎名單每頁公示3個,當你點下一頁的時候會以AJAX方式請求資料。
因此我們只需要請求第一頁以後,獲取獲獎的總人數,然後迴圈分別獲取其餘AJAX請求。
進學習交流群:548377875 海量學習教程在群檔案,大牛隨時答疑!是一個很不錯的學習交流基地呢!
將每個獲獎人的ID放在一個列表裡,每次append即可。
在這邊有一點就是,我們必須要在登陸狀態下訪問才可以看到獲獎情況,否則會跳轉登入頁。解決辦法是帶cookie訪問。無腦加headers和cookies不會有問題。
def lottery(page, pageid, lid): cookies = {# your cookies } headers = {# copy the headers } params = ( ('pageid', pageid), # 100140E1198435 ('id', lid), # 3436763 ('page', page), # 2 ('prizeLevel', '1'), ('_t', '0'), ('__rnd', int(time.time() * 1000)), # 1542650067843 ) response = requests.get('https://event.weibo.com/yae/aj/event/lottery/result', headers=headers, params=params, cookies=cookies) return response.text
我們可以看到AJAX返回的內容是一個JSON,但是這個JSON內的資料卻又沒有那麼的友好,並不是我們常見的直接給出了每個使用者的資料字典,而是給了我們一個HTML標籤包裹的程式碼塊。也就是說需要進一步的解析,不過好在並不複雜,這裡我選擇自己比較熟悉的BS來做,別的解析方法也都可以。
執行程式碼,我們便可以得到所有中獎使用者ID組成的一個列表了。
def result(pageid, lid): userid = [] jsonObj = json.loads(lottery('1', pageid, lid)) html = jsonObj['data']['html'] # print(html) bsObj = BeautifulSoup(html, 'lxml') # <span class='lottery_published_gray'>113</span> spans = bsObj.find_all('span', {'class': 'lottery_published_gray'}) count = spans[-1].text n = int(count) // 3 + 1 if n == 1: dt = bsObj.find_all('dt') for each in dt: userid.append(each.find('a')['href'].split('/')[3]) print(userid) else: for i in range(1, n + 1): jsonObj = json.loads(lottery(i, pageid, lid)) html = jsonObj['data']['html'] bsObj = BeautifulSoup(html, 'lxml') dt = bsObj.find_all('dt') for each in dt: userid.append(each.find('a')['href'].split('/')[3]) print(userid) return userid
獲取性別要進入到每個使用者的個人資訊頁面。在這裡我們選擇請求手機版頁面,沒有太多雜亂的頁面結構和廣告,反爬也相對寬鬆。
還是跟剛才差不多,帶cookies請求頁面就好了。這邊的結構很規範,用XPATH也可以,當然如果我們只取性別的話,正則也是夠用的。其餘的資訊像是姓名、地區、生日、標籤、簡介等等,大家可以相應地自己實現。
def userInfo(uid): cookies = {# your cookies} headers = {# copy the headers} response = requests.get('https://weibo.cn/' + uid + '/info', headers=headers, cookies=cookies) h = response.text # print(h) pattern = re.compile(r'性別:(.)') sex = pattern.search(h).group(1) return sex
如此迴圈得到了所有使用者的性別後,我們只需要統計列表中的男女比例就可以了。
# 大概在300次左右會出現請求失敗。所以如果中間人數特別多的話,還是設定一下延時。
最後就是簡單的資料分析。因為一來資料總量不大,二來我們不打算進行太深入的資料分析,在不考慮儲存的情況下,我們直接使用了列表來存結果。如果要進一步分析,最好還是用字典(JSON)、CSV等方式進行持久化操作。既然是列表儲存的話,我們可以直接用列表的count方法來計算出男女比例。大家也可以結合視覺化方法來更直觀地展示結果。
print(usersex.count('女')) print(usersex.count('男'))
最終可以看一下兩次抽獎的結果:
usersex1 = ['女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '男', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女'] usersex2 = ['男', '女', '女', '男', '女', '男', '女', '女', '女', '男', '女', '女', '女', '女', '女', '女', '女', '男', '女', '男', '女', '男', '男', '女', '男', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '男', '女', '男', '男', '男', '女', '女', '男', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '女', '男', '女', '女', '男', '女', '女', '女', '女', '女', '女']
第一次抽獎113人中,有112人為女;第二次抽獎67人中,有51人為女。
今天的內容我也為大家錄了一期視訊講解,大家可以點選原文跳轉觀看,比較適合零基礎的同學學習~