前言
由於之后要做一個實驗,需要用到大量豆瓣用戶的電影數據,因此想到了從豆瓣電影的“看過這部電影 的豆瓣成員”頁面上來獲取較為活躍的豆瓣電影用戶。
鏈接分析
這是看過"模仿游戲"的豆瓣成員的網頁鏈接:http://movie.douban.com/subject/10463953/collections。
一頁上顯示了20名看過這部電影的豆瓣用戶。當點擊下一頁時,當前連接變為:http://movie.douban.com/subject/10463953/collections?start=20。
由此可知,當請求下一頁內容時,實際上就是將"start"后的索引增加20。
因此,我們可以設定base_url='http://movie.douban.com/subject/10463953/collections?start=',i=range(0,200,20),在循環中url=base_url+str(i)。
之所以要把i的最大值設為180,是因為后來經過測試,豆瓣只給出看過一部電影的最近200個用戶。
讀取網頁
在訪問時我設置了一個HTTP代理,並且為了防止訪問頻率過快而被豆瓣封ip,每讀取一個網頁后都會調用time.sleep(5)等待5秒。 在程序運行的時候干別的事情好了。
網頁解析
本次使用BeautifulSoup庫解析html。
每一個用戶信息在html中是這樣的:
<table width="100%" class=""> <tr> <td width="80" valign="top"> <a href="http://movie.douban.com/people/46770381/"> <img class="" src="http://img4.douban.com/icon/u46770381-16.jpg" alt="七月" /> </a> </td> <td valign="top"> <div class="pl2"> <a href="http://movie.douban.com/people/46770381/" class="">七月 <span style="font-size:12px;">(銀川)</span> </a> </div> <p class="pl">2015-08-23 <span class="allstar40" title="推薦"></span> </p> </td> </tr> </table>
首先用讀取到的html初始化soup=BeautifulSoup(html)。本次需要的信息僅僅是用戶id和用戶的電影主頁,因此真正有用的信息在這段代碼中:
<td width="80" valign="top"> <a href="http://movie.douban.com/people/46770381/"> <img class="" src="http://img4.douban.com/icon/u46770381-16.jpg" alt="七月" /> </a> </td>
因此在Python代碼中通過td_tags=soup.findAll('td',width='80',valign='top')找到所有<td width="80" valign="top">的塊。
td=td_tags[0],a=td.a就可以得到
<a href="http://movie.douban.com/people/46770381/"> <img class="" src="http://img4.douban.com/icon/u46770381-16.jpg" alt="七月" /> </a>
通過link=a.get('href')可以得到href屬性,也就用戶的電影主頁鏈接。然后通過字符串查找也就可以得到用戶ID了。
完整代碼
1 #coding=utf-8 2 ##從豆瓣網頁中得到用戶id 3 4 ##網頁地址類型:http://movie.douban.com/subject/26289144/collections?start=0 5 ## http://movie.douban.com/subject/26289144/collections?start=20 6 7 from BeautifulSoup import BeautifulSoup 8 import codecs 9 import time 10 import urllib2 11 12 baseUrl='http://movie.douban.com/subject/25895276/collections?start=' 13 14 proxyInfo='127.0.0.1:8087' 15 proxySupport=urllib2.ProxyHandler({'http':proxyInfo}) 16 opener=urllib2.build_opener(proxySupport) 17 urllib2.install_opener(opener) 18 19 20 #將用戶信息(id,主頁鏈接)保存至文件 21 def saveUserInfo(idList,linkList): 22 if len(idList)!=len(linkList): 23 print 'Error: len(idList)!=len(linkList) !' 24 return 25 writeFile=codecs.open('UserIdList3.txt','a','utf-8') 26 size=len(idList) 27 for i in range(size): 28 writeFile.write(idList[i]+'\t'+linkList[i]+'\n') 29 writeFile.close() 30 31 #從給定html文本中解析用戶id和連接 32 def parseHtmlUserId(html): 33 idList=[] #返回的id列表 34 linkList=[] #返回的link列表 35 36 soup=BeautifulSoup(html) 37 ##<td width="80" valign="top"> 38 ##<a href="http://movie.douban.com/people/liaaaar/"> 39 ##<img class="" src="/u3893139-33.jpg" alt="Liar." /> 40 ##</a> 41 ##</td> 42 td_tags=soup.findAll('td',width='80',valign='top') 43 i=0 44 for td in td_tags: 45 #前20名用戶是看過這部電影的, 46 #而后面的只是想看這部電影的用戶,因此舍棄 47 if i==20: 48 break 49 a=td.a 50 link=a.get('href') 51 i_start=link.find('people/') 52 id=link[i_start+7:-1] 53 idList.append(id) 54 linkList.append(link) 55 i+=1 56 return (idList,linkList) 57 58 #返回指定編號的網頁內容 59 def getHtml(num): 60 url=baseUrl+str(num) 61 page=urllib2.urlopen(url) 62 html=page.read() 63 return html 64 65 def launch(): 66 #指定起始編號:20的倍數 67 ques=raw_input('Start from number?(Multiples of 20) ') 68 startNum=int(ques) 69 if startNum%20 != 0: 70 print 'Input number error!' 71 return 72 for i in range(startNum,200,20): 73 print 'Loading page %d/200 ...' %(i+1) 74 html=getHtml(i) 75 (curIdList,curLinkList)=parseHtmlUserId(html) 76 saveUserInfo(curIdList,curLinkList) 77 print 'Sleeping.' 78 time.sleep(5)
