一、項目需求
前言:BBS上每個id對應一個使用者,他們註冊時候會填寫性別(男、女、保密三選一)。
經過檢查,BBS註冊使用者的id對應1-300000,大概是30萬的使用者
筆者想用Python統計BBS上有多少註冊使用者,以及這些使用者的性別分布
順帶可以統計最近活動使用者是多少,其中男、女、保密各佔多少
活動使用者的限定為“上次啟用時間”為 2015年
二、最終結果
性別資訊儲存在文本裡,一行表示一個使用者的資訊,各列分別表示
【行數,id(塗掉了),性別,最後活躍時間】
三、實現思路
使用者性別資訊在哪個頁面?
得到下面個人首頁
把後面的uid=256730數字改成其他數字,就可以得到其他人的首頁。
另外,如果上面的連結無法得到性別,可以再通過這個連結,也是修改uid可以訪問其他人首頁。
http://rs.xidian.edu.cn/home.php?mod=space&uid=256730&do=profile
四、資料如何儲存?
用資料庫還是其他方案?
為了閱讀方便,我們考慮用文字檔儲存。
30萬的使用者儲存在一個文本裡會導致文本過大。如果程式被意外終止,30 萬的使用者資料需要重新爬取。
我們我們考慮一個文本裡存放1000條記錄,理論上可以用30個文本來存放30萬條資料。
文本名稱為correct1-1001.txt correct47001-48001.txt,注意:1-1001是[1,1001),包含1,不包含1001
1、使用正則匹配找出性別
查看網頁原始碼
性別女還可以找到啟用時間-->
上次發表時間2015-11-4 20:04抱歉,您指定的使用者空間不存在
我們可以利用re模組來進行正則匹配
sexRe = re.compile(u'em>\u6027\u522b(.*?)\u4e0a\u6b21\u6d3b\u52a8\u65f6\u95f4(.*?))\u62b1\u6b49\uff0c\u60a8\u6307\u5b9a\u7684\u7528\u6237\u7a7a\u95f4\u4e0d\u5b58\u5728<')
因為中文的原因,需要Unicode 轉換 中文工具,可以用站長工具 Unicode 轉換 ASCII,ASCII 轉換 Unicode,比如下面這個連結: http://tool.chinaz.com/Tools/Unicode.aspx
- 性別的Unicode 是 \u6027\u522b
- 上次啟用時間 \u4e0a\u6b21\u6d3b\u52a8\u65f6\u95f4
- 抱歉,您指定的使用者空間不存在
- \u62b1\u6b49\uff0c\u60a8\u6307\u5b9a\u7684\u7528\u6237\u7a7a\u95f4\u4e0d\u5b58\u5728
這兒是簡單擷取性別的原始碼,通過urllib2對連結myurl發送一個get請求,將得到的html儲存下來。注意編碼問題unicode(html, 'utf-8'),然後對html正則匹配seWord。
如果該使用者有性別資訊,返回對應的性別;否則,返回None
#對myurl頁面進行seWord匹配尋找#seWord是用unicode表示def getInfo(myurl, seWord): headers = { 'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6' } req = urllib2.Request( url=myurl, headers=headers ) time.sleep(0.3) response = urllib2.urlopen(req) html = response.read() html = unicode(html, 'utf-8') #需要進行編碼,否則找不到資訊 timeMatch = seWord.search(html) #因為seWord是用unicode表示 if timeMatch: s = timeMatch.groups() return s[0] else: return None
五、錯誤處理
1、斷網情況(熱修複方案)
- 總共爬蟲需要幾天時間,用的校園網,中間可能有斷網的可能。
- 如果發現斷網,我們可以重新連上互連網,這中間有些使用者的性別沒有擷取到。
- 程式已耗用時間較長,斷一次網就重新從id=1開始跑是不科學的。而且你也不能保證這次就網一直是好的。
- 為了不讓程式重頭開始跑,所以我們是記錄下斷網中漏掉的使用者id。
- 等一次程式跑完了(這需要幾天的時間),我們再跑記錄下來的id重新跑一次。
2、無法擷取性別
- 這種有兩種情況:
- 一是真的沒有性別(使用者沒有填寫)
- 二是伺服器抽了,咱們請求網頁失敗了。
- 這種咱們也是和上面類似,記錄下失敗的id,後面再重新跑。
知識點小結
對於這種錯誤,SyntaxError: Non-ASCII character '\xe5' in file
需要在檔案開頭加上# -*- coding: UTF-8 -*-
因為 python 的預設編碼檔案是用的 ANSCII 碼
BBS網頁原始碼使用utf-8進行編碼的。
本項目設計到中文字元,自然會遇到編碼問題。
import sysprint sys.getdefaultencoding()
輸出 ascii
從上面的代碼可以看出 sys.defaultencoding 是 ANSCII,ANSCII是無法對中文字元進行編碼的。UTF-8是Unicode的實現方式之一,可以對中文字元進行編碼。遇到中文字元,我們需要加上這行代碼
reload(sys)# sys.setdefaultencoding('utf-8')
更改 sys.defaultencoding 為'utf-8'
後期整理的時候發現了自己一個小問題,因為Regex當時用unicode來表示的,所以需要把html進行unicode轉換進行尋找。
後來發現可以直接用漢字對原來的html進行尋找。
# -*- coding: UTF-8 -*- html = response.read() sexRe = re.compile('em>性別(.*?)\u6027\u522b(.*?)輸出
字串 女unicode 女 html = response.read() print len(html) html = unicode(html, 'utf-8') # print len(html)
輸出
html = response.read() print len(html) html = unicode(html, 'utf-8') # print len(html)
輸出
3542333658
以上就是python實現爬蟲統計學校BBS男女比例的前期準備和方案分析,希望對大家的學習有所協助。