前言由于之后要做一个实验,需要用到大量豆瓣用户的电影数据,因此想到了从豆瓣电影的“看过这部电影 的豆瓣成员”页面上来获取较为活跃的豆瓣电影用户。
链接分析这是看过"模仿游戏"的豆瓣成员的网页链接: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中是这样的:
<tablewidth="100%"class=""><tr><tdwidth="80"valign="top"><ahref="http://movie.douban.com/people/46770381/"><imgclass=""src="http://img4.douban.com/icon/u46770381-16.jpg"alt="七月"/></a></td><tdvalign="top"><divclass="pl2"><ahref="http://movie.douban.com/people/46770381/"class="">七月<spanstyle="font-size:12px;">(银川)</span></a></div><pclass="pl">2015-08-23 <spanclass="allstar40"title="推荐"></span></p></td></tr></table>
首先用读取到的html初始化soup=BeautifulSoup(html)。本次需要的信息仅仅是用户id和用户的电影主页,因此真正有用的信息在这段代码中:
<tdwidth="80"valign="top"><ahref="http://movie.douban.com/people/46770381/"><imgclass=""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就可以得到
<ahref="http://movie.douban.com/people/46770381/"><imgclass=""src="http://img4.douban.com/icon/u46770381-16.jpg"alt="七月"/></a>
通过link=a.get('href')可以得到href属性,也就用户的电影主页链接。然后通过字符串查找也就可以得到用户ID了。
完整代码1#coding=utf-82##从豆瓣网页中得到用户id34##网页地址类型:http://movie.douban.com/subject/26289144/collections?start=05## http://movie.douban.com/subject/26289144/collections?start=2067fromBeautifulSoupimportBeautifulSoup8importcodecs9importtime10importurllib21112baseUrl='http://movie.douban.com/subject/25895276/collections?start='1314PRoxyInfo='127.0.0.1:8087'15proxySupport=urllib2.ProxyHandler({'http':proxyInfo})16opener=urllib2.build_opener(proxySupport)17urllib2.install_opener(opener)181920#将用户信息(id,主页链接)保存至文件21defsaveUserInfo(idList,linkList):22iflen(idList)!=len(linkList):23print'Error: len(idList)!=len(linkList) !'24return25writeFile=codecs.open('UserIdList3.txt','a','utf-8')26size=len(idList)27foriinrange(size):28writeFile.write(idList[i]+'\t'+linkList[i]+'\n')29writeFile.close()3031#从给定html文本中解析用户id和连接32defparseHtmlUserId(html):33idList=[]#返回的id列表34linkList=[]#返回的link列表3536soup=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>42td_tags=soup.findAll('td',width='80',valign='top')43i=044fortdintd_tags:45#前20名用户是看过这部电影的,46#而后面的只是想看这部电影的用户,因此舍弃47ifi==20:48
break49a=td.a50link=a.get('href')51i_start=link.find('people/')52id=link[i_start+7:-1]53idList.append(id)54linkList.append(link)55i+=156return(idList,linkList)5758#返回指定编号的网页内容59defgetHtml(num):60url=baseUrl+str(num)61page=urllib2.urlopen(url)62html=page.read()63returnhtml6465deflaunch():66#指定起始编号:20的倍数67ques=raw_input('Start from number?(Multiples of 20)')68startNum=int(ques)69ifstartNum%20 !=0:70print'Input number error!'71return72foriinrange(startNum,200,20):73print'Loading page %d/200 ...'%(i+1)74html=getHtml(i)75(curIdList,curLinkList)=parseHtmlUserId(html)76saveUserInfo(curIdList,curLinkList)77print'Sleeping.'78time.sleep(5)