python实战(开发新浪微博应用)

 

 

 

 

 

 

#coding=utf-8
"""
本应用主要功能
1.用户选择喜欢的标签加关注
2.获取用户粉丝中自己还没有关注的,->加关注,提高粉丝稳定性
3.获取用户关注列表中没有回粉的,并可以一键取消关注
2,3两个功能基本实现,有一缺点,数据量一大,很慢很慢
1功能不太好,主要是通过一个线程去搜索数据,把感兴趣的用户放入数据库,当用户选择加关注标签时,从数据库中取数据,
以前用sqlite3比较少,一用发现还是有好多值得研究的地方,主要是线程安全....,慢慢研究....
"""

import os
import sys
import key
import web
import threading
import sqlite3
import time
from weibopy.auth import OAuthHandler
from weibopy.api import API
from jinja2 import Environment,FileSystemLoader

"""
url配置
"""
urls = (
     '/', 'Login',
     '/index','Index',
     '/callback','CallBack',
     '/logout','LogOut',
     '/(.*)/', 'Redirect',
     '/tag', 'Tag',
     '/noattention','Noattention',
     '/fensiattention','Fensiattention',
     '/minusattention','Minusattention',
     '/delattention','Delattention'
 )

app=web.application(urls,globals())

if web.config.get('_session') is None:
     session = web.session.Session(app,web.session.DiskStore("sina"))
     web.config._session = session
else:
     session = web.config._session

"""
   用jinja2模板渲染文件
"""
def render_template(template_name,**context):
     extensions=context.pop('extensions',[])
     globals=context.pop("globals",{})
     jinja_env=Environment(
         loader=FileSystemLoader(os.path.join(os.path.dirname(__file__),'templates')),
         extensions=extensions)
     jinja_env.globals.update(globals)
     return jinja_env.get_template(template_name).render(context)

"""
定义404请求页面
"""
def notfound():
     info="亲,您所请求的页面不存在,系统在3秒后自动返回..."
     return web.notfound(render_template('error.html',info=info.decode('utf-8')))

db=web.database(dbn='sqlite',db='tag.s3db')

"""
要求tag
"""
tagdict={'水瓶座':1,'双鱼座':2,'白羊座':3,'金牛座':4,'双子座':5,'巨蟹座':6,'狮子座':7,'处女座':8,'天秤座':9,'天蝎座':10,'射手座':11,
         '摩羯座':12,'吃':13,'听歌':14,'淘宝':15,'网购':16,'数码':17,'摄影':18,'睡觉':19,'旅游':20,'体育':21,'动漫':22,'游戏':23,
         '股票':24,'交友':25,'宅女':26,'宅男':27,'时尚':28,'浪漫':29,'美女':30,'创业':31,'IT':32,'媒体':33,'营销':34}
systag=['水瓶座','双鱼座','白羊座','金牛座','双子座','巨蟹座','狮子座','处女座','天秤座','天蝎座','射手座','摩羯座','吃','听歌','淘宝',
        '网购','数码','摄影','睡觉','旅游','体育','动漫','游戏','股票','交友','宅女','宅男','时尚','浪漫','美女','创业','IT','媒体','营销']

conn=sqlite3.connect('tag.s3db',check_same_thread=False) #允许其它线程使用这个连接
conn.text_factory = str
cursor=conn.cursor()

class Setag(threading.Thread):
    """
这个线程主要是用来搜索用户tag,如果满足tag要求就写入数据库中,
    """
    def authorization(self):
        """
        开发者认证
        """
        auth = OAuthHandler(key.CONSUME_KEY, key.CONSUME_SECRET)
        auth.setToken(key.TOKEN,key.TOKEN_SECRET)
        self.api = API(auth)
        self.cursor=cursor

    def adduser(self,uid):
        """
        遍历uid用户的tag,满足条件加入数据库
        """
        try:
            fan=self.api.followers_ids(uid)
            fanuid=fan.ids
            for id in fanuid:
                tags=self.api.tags(id)
                tt=[]
                for t in tags:
                    tagid=t.__getattribute__('id')
                    value=t.__getattribute__(tagid)
                    tt.append(value.encode('utf-8'))
                """
                获取用户tag与要求标签的交集
                """
                common=set(tt).intersection(set(systag))
                if len(common)==0:
                    continue
                else:
                    for t in common:
                        """
                        获取tag对应的tagid
                        """
                        tagindex=tagdict[t]
                        try:
                            self.cursor.execute("insert into taginfo(uid,tagid) values(%d,%d)" %(int(id),int(tagindex)))
                            conn.commit()
                        except:
                            continue
        except:
            time.sleep(120)
            pass
        finally:
            time.sleep(60)
            """
            将uid用户的第一个粉丝uid传给adduser
            """
            return self.adduser(fanuid[0])

    def run(self):
        self.authorization()
        me=self.api.verify_credentials()
        """
        将我自己的uid给adduser
        """
        self.adduser(me.id)

"""
定义404请求页面
"""
app.notfound= notfound
 #首页
 #首先从session中获取access_token,没有就转向新浪微博页面认证
 #认证成功后将access_token保存在session中
"""
首页是登陆页面,通过新浪微博授权
"""
class Login:
    def GET(self):
        return render_template('login.html')

"""
新浪微博授权原理:
首先首页判断有无用户session信息,如果有则跳转到相应地址,
没有则引导用户跳转到授权uri,授权后自动跳转到永远自定义的回调地址,
回调地址保存用户session信息,跳转到首页,这时已有用户session信息,干坏事吧....
"""
class Index:
     def GET(self):
         access_token=session.get('access_token',None)
         if not access_token:
             """
             key.py中放置了开发者的信息
             """
             auth = OAuthHandler(key.CONSUME_KEY, key.CONSUME_SECRET,web.ctx.get('homedomain')+'/callback')
             #获取授权url
             auth_url = auth.get_authorization_url()
             session.request_token=auth.request_token
             web.seeother(auth_url)
         else:
             auth = OAuthHandler(key.CONSUME_KEY, key.CONSUME_SECRET)
             auth.access_token=access_token
             api=API(auth)
             user=api.verify_credentials()
             return render_template('index.html',user=user)

"""
 页面回调,新浪微博验证成功后会返回本页面
"""
class CallBack:
     def GET(self):
         try:
             ins=web.input()
             oauth_verifier=ins.get('oauth_verifier',None)
             request_token=session.get('request_token',None)
             auth=OAuthHandler(key.CONSUME_KEY, key.CONSUME_SECRET)
             auth.request_token=request_token
             access_token=auth.get_access_token(oauth_verifier)
             session.access_token=access_token
             web.seeother("/index")
         except Exception:
             info="亲,系统繁忙,请稍后再试......,系统在3秒后自动返回..."
             return render_template('error.html',info=info.decode('utf-8'))

"""
重定向用户输入uri后的/
"""
class Redirect:
    def GET(self,path):
        web.seeother('/'+path)

class Tag:
    """
    获取用户选择加关注的tag
    """
    def GET(self):
        data=web.input()
        try:
            select=data.star
        except:
            try:
                select=data.hobby
            except:
                try:
                    select=data.personality
                except:
                    select=data.job
        try:
            auth = OAuthHandler(key.CONSUME_KEY, key.CONSUME_SECRET)
            auth.access_token=session['access_token']
            api=API(auth)
            seuid=[]
            nu=0
            """
            这里写的很不好.....
            """
            while True:
                re=cursor.execute('select uid from taginfo where tagid=%d limit 20' %select).fetchall()
                for r in re:
                    seuid.append(r[0])
                for s in seuid:
                    try:
                        api.create_friendship(user_id=s)
                        nu+=1
                    except:
                        continue
                if nu>=50:
                    break

            info="恭喜您已成功关注%d位用户....." %nu
            return render_template('success.html',info=info.decode('utf-8'))
        except:
            info="亲,系统繁忙,请稍后再试......,系统在3秒后自动返回..."
            return render_template('error.html',info=info.decode('utf-8'))

class Noattention:
    """
    获取我的粉丝中我没有加关注的,把数据传给noattention.html页面显示...
    """
    def GET(self):
        try:
            auth=OAuthHandler(key.CONSUME_KEY,key.CONSUME_SECRET)
            auth.access_token=session['access_token']
            api=API(auth)
            user=api.verify_credentials()
            fan=[]
            next_cursor=-1
            while next_cursor!=0:
                timeline=api.followers(user.id,'','','',next_cursor)
                if isinstance(timeline,tuple):
                    next_cursor=timeline[1]
                    for line in timeline[0]:
                        fid=line.__getattribute__("id")
                        fname=line.__getattribute__("screen_name")
                        fan.append((fid,fname))

                else:
                    next_cursor=0
                    for line in timeline:
                        fid=line.__getattribute__("id")
                        fname=line.__getattribute__("screen_name")
                        fan.append((fid,fname))

            friend=[]
            next_cursor=-1
            while next_cursor!=0:
                timeline=api.friends(user.id,'','','',next_cursor)
                if isinstance(timeline,tuple):
                    next_cursor=timeline[1]
                    for line in timeline[0]:
                        frid=line.__getattribute__("id")
                        frname=line.__getattribute__("screen_name")
                        friend.append((frid,frname))
                else:
                    next_cursor=0
                    for line in timeline:
                        frid=line.__getattribute__("id")
                        frname=line.__getattribute__("screen_name")
                        friend.append((frid,frname))
            #获取我的粉丝中还不是我的关注对象
            fanNotAttention=list(set(fan).difference(set(friend)))
            nu=len(fanNotAttention)
            if nu==0:
                return render_template('noattentionok.html',nu=nu)
            else:
                return render_template('noattention.html',nu=nu,fanNotAttention=fanNotAttention)

        except:
            info="亲,系统繁忙,请稍后再试......,系统在3秒后自动返回..."
            return render_template('error.html',info=info.decode('utf-8'))

class Fensiattention:
    """
    对未加关注的粉丝加关注
    """
    def GET(self):
        #获取noattentionok.html传过来的数据
        data=web.input()
        on=[]
        try:
            auth=OAuthHandler(key.CONSUME_KEY,key.CONSUME_SECRET)
            auth.access_token=session['access_token']
            api=API(auth)
            """
            获取noattention.html页面传过来的uid,通过checkbox,由于有一个全选按钮,如果点击,则去掉
            """
            for x in data:
                on.append(x)
            try:
                on.remove('checkbox2')
            except:
                pass
            nu=len(on)
            if nu==0:
                pass
            if nu>60:
                on=on[:60]
                nu=60
            """
            一次最多加60次关注
            """
            map(api.create_friendship,on)
            info="恭喜您已成功关注%d位用户....." %nu
            return render_template('success.html',info=info.decode('utf-8'))
        except:
             info="亲,系统繁忙,请稍后再试......,系统在3秒后自动返回..."
             return render_template('error.html',info=info.decode('utf-8'))

class Minusattention:
    """
    获取我的关注中不是我粉丝的,即不回粉的家伙,把数据传给attentionnotfan.html显示...
    """
    def GET(self):
        try:
            auth=OAuthHandler(key.CONSUME_KEY,key.CONSUME_SECRET)
            auth.access_token=session['access_token']
            api=API(auth)
            user=api.verify_credentials()
            fan=[]
            next_cursor=-1
            while next_cursor!=0:
                timeline=api.followers(user.id,'','','',next_cursor)
                if isinstance(timeline,tuple):
                    next_cursor=timeline[1]
                    for line in timeline[0]:
                        fid=line.__getattribute__("id")
                        fname=line.__getattribute__("screen_name")
                        fan.append((fid,fname))

                else:
                    next_cursor=0
                    for line in timeline:
                        fid=line.__getattribute__("id")
                        fname=line.__getattribute__("screen_name")
                        fan.append((fid,fname))

            friend=[]
            next_cursor=-1
            while next_cursor!=0:
                timeline=api.friends(user.id,'','','',next_cursor)
                if isinstance(timeline,tuple):
                    next_cursor=timeline[1]
                    for line in timeline[0]:
                        frid=line.__getattribute__("id")
                        frname=line.__getattribute__("screen_name")
                        friend.append((frid,frname))
                else:
                    next_cursor=0
                    for line in timeline:
                        frid=line.__getattribute__("id")
                        frname=line.__getattribute__("screen_name")
                        friend.append((frid,frname))
            attentionNotFan=list(set(friend).difference(set(fan)))
            nu=len(attentionNotFan)
            if nu==0:
                return render_template('attentionnotfanok.html',nu=nu)
            else:
                return render_template('attentionnotfan.html',nu=nu,attentionNotFan=attentionNotFan)

        except:
             info="亲,系统繁忙,请稍后再试......,系统在3秒后自动返回..."
             return render_template('error.html',info=info.decode('utf-8'))

class Delattention:
    """
    获取attentionnotfan.html页面选择的用户,并一键取消关注
    """
    def GET(self):
        #获取attentionnotfan.html传过来的数据
        data=web.input()
        on=[]
        try:
            auth=OAuthHandler(key.CONSUME_KEY,key.CONSUME_SECRET)
            auth.access_token=session['access_token']
            api=API(auth)
            for x in data:
                on.append(x)
            try:
                #同理,由于有全选按钮.....
                on.remove('checkbox2')
            except:
                pass
            nu=len(on)
            if nu==0:
                pass
            #取消关注
            map(api.destroy_friendship,on)
            info="恭喜您已成功取消关注%d位用户....." %nu
            return render_template('success.html',info=info.decode('utf-8'))
        except:
             info="亲,系统繁忙,请稍后再试......,系统在3秒后自动返回..."
             return render_template('error.html',info=info.decode('utf-8'))

if __name__=='__main__':
     """
     启动app,启动s线程去搜索数据
     """
     s=Setag()
     s.start()
     app.run()

  

posted @ 2016-08-16 12:52  青春永不言弃  阅读(920)  评论(0编辑  收藏  举报