一、項(xiàng)目需求
前言:BBS上每個(gè)id對(duì)應(yīng)一個(gè)用戶,他們注冊(cè)時(shí)候會(huì)填寫(xiě)性別(男、女、保密三選一)。
經(jīng)過(guò)檢查,BBS注冊(cè)用戶的id對(duì)應(yīng)1-300000,大概是30萬(wàn)的用戶
筆者想用Python統(tǒng)計(jì)BBS上有多少注冊(cè)用戶,以及這些用戶的性別分布
順帶可以統(tǒng)計(jì)最近活動(dòng)用戶是多少,其中男、女、保密各占多少
活動(dòng)用戶的限定為“上次活動(dòng)時(shí)間”為 2015年
二、最終結(jié)果
性別信息保存在文本里,一行表示一個(gè)用戶的信息,各列分別表示
【行數(shù),id(涂掉了),性別,最后活躍時(shí)間】



三、實(shí)現(xiàn)思路
用戶性別信息在哪個(gè)頁(yè)面?
得到下面?zhèn)€人主頁(yè)

把后面的uid=256730數(shù)字改成其他數(shù)字,就可以得到其他人的主頁(yè)。
另外,如果上面的鏈接無(wú)法得到性別,可以再通過(guò)這個(gè)鏈接,也是修改uid可以訪問(wèn)其他人主頁(yè)。
http://rs.xidian.edu.cn/home.php?mod=space&uid=256730&do=profile

四、數(shù)據(jù)如何存儲(chǔ)?
用數(shù)據(jù)庫(kù)還是其他方案?
為了閱讀方便,我們考慮用文本文件存儲(chǔ)。
30萬(wàn)的用戶存儲(chǔ)在一個(gè)文本里會(huì)導(dǎo)致文本過(guò)大。如果程序被意外終止,30 萬(wàn)的用戶數(shù)據(jù)需要重新爬取。
我們我們考慮一個(gè)文本里存放1000條記錄,理論上可以用30個(gè)文本來(lái)存放30萬(wàn)條數(shù)據(jù)。
文本名稱為correct1-1001.txt correct47001-48001.txt,注意:1-1001是[1,1001),包含1,不包含1001
1、使用正則匹配找出性別
查看網(wǎng)頁(yè)源代碼
<!-- 找出性別這一欄--><li><em>性別</em>女</li>還可以找到活動(dòng)時(shí)間--><li><em>上次發(fā)表時(shí)間</em>2015-11-4 20:04</li><!-- 有些id不存在相應(yīng)的用戶,會(huì)有這樣的提示--><p>抱歉,您指定的用戶空間不存在</p>

我們可以利用re模塊來(lái)進(jìn)行正則匹配
sexRe = re.compile(u'em>/u6027/u522b</em>(.*?)</li')timeRe = re.compile(u'em>/u4e0a/u6b21/u6d3b/u52a8/u65f6/u95f4</em>(.*?)</li')notexistRe = re.compile(u'(p>)/u62b1/u6b49/uff0c/u60a8/u6307/u5b9a/u7684/u7528/u6237/u7a7a/u95f4/u4e0d/u5b58/u5728<')
因?yàn)橹形牡脑颍枰猆nicode 轉(zhuǎn)換 中文工具,可以用站長(zhǎng)工具 Unicode 轉(zhuǎn)換 ASCII,ASCII 轉(zhuǎn)換 Unicode,比如下面這個(gè)鏈接: http://tool.chinaz.com/Tools/Unicode.aspx
這兒是簡(jiǎn)單獲取性別的源代碼,通過(guò)urllib2對(duì)鏈接myurl發(fā)送一個(gè)get請(qǐng)求,將得到的html保存下來(lái)。注意編碼問(wèn)題unicode(html, 'utf-8'),然后對(duì)html正則匹配seWord。
如果該用戶有性別信息,返回對(duì)應(yīng)的性別;否則,返回None
#對(duì)myurl頁(yè)面進(jìn)行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') #需要進(jìn)行編碼,否則找不到信息 timeMatch = seWord.search(html) #因?yàn)閟eWord是用unicode表示 if timeMatch: s = timeMatch.groups() return s[0] else: return None五、錯(cuò)誤處理
1、斷網(wǎng)情況(熱修復(fù)方案)
2、無(wú)法獲取性別
知識(shí)點(diǎn)小結(jié)
對(duì)于這種錯(cuò)誤,SyntaxError: Non-ASCII character '/xe5' in file
需要在文件開(kāi)頭加上# -*- coding: UTF-8 -*-
因?yàn)?python 的默認(rèn)編碼文件是用的 ANSCII 碼
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
BBS網(wǎng)頁(yè)源代碼使用utf-8進(jìn)行編碼的。
本項(xiàng)目設(shè)計(jì)到中文字符,自然會(huì)遇到編碼問(wèn)題。
import sysprint sys.getdefaultencoding()
輸出 ascii
從上面的代碼可以看出 sys.defaultencoding 是 ANSCII,ANSCII是無(wú)法對(duì)中文字符進(jìn)行編碼的。UTF-8是Unicode的實(shí)現(xiàn)方式之一,可以對(duì)中文字符進(jìn)行編碼。遇到中文字符,我們需要加上這行代碼
reload(sys)# sys.setdefaultencoding('utf-8')更改 sys.defaultencoding 為'utf-8'
后期整理的時(shí)候發(fā)現(xiàn)了自己一個(gè)小問(wèn)題,因?yàn)檎齽t表達(dá)式當(dāng)時(shí)用unicode來(lái)表示的,所以需要把html進(jìn)行unicode轉(zhuǎn)換進(jìn)行查找。
后來(lái)發(fā)現(xiàn)可以直接用漢字對(duì)原來(lái)的html進(jìn)行查找。
# -*- coding: UTF-8 -*- html = response.read() sexRe = re.compile('em>性別</em>(.*?)</li') timeMatch = sexRe.search(html) if timeMatch: s = timeMatch.groups() print "字符串 "+s[0] html = unicode(html, 'utf-8') sexRe = re.compile(u'em>/u6027/u522b</em>(.*?)</li') timeMatch = sexRe.search(html) if timeMatch: s = timeMatch.groups() print "unicode " +s[0]輸出
字符串 女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實(shí)現(xiàn)爬蟲(chóng)統(tǒng)計(jì)學(xué)校BBS男女比例的前期準(zhǔn)備和方案分析,希望對(duì)大家的學(xué)習(xí)有所幫助。
|
新聞熱點(diǎn)
疑難解答
圖片精選