IVY DOM


 

人生就像一副复杂拼图
每个人总有属於自己的记忆碎片
优质美国空间-老薛主机|IVY DOM|Flowline|

联系我

RSS




二月 02, 2015

Python 获得知乎日报数据

PHP版本的知乎日报 http://daily.ivydom.com/

(注意知乎启用了很多反爬虫机制,比如图片是无法直接获取到的,在我的PHP版本里都获得了解决,详情请看github:https://github.com/leinue/daily)

昨天刚看完O’REILLY的Python学习手册,于是就写了这个获取知乎日报每日数据的小程序,难度非常小,拿来练练手,熟悉下Python.本程序涉及到了运算符重载,urllib,json,正则表达式,面向对象编程和异常处理.

先来看一下知乎日报的API:

self.apiLatest=’http://news-at.zhihu.com/api/3/news/latest’ #获取最新消息

self.apiBefore=’http://news.at.zhihu.com/api/3/news/before/’ #获取以前的消息,before后面要加日期

self.apiID=’http://news-at.zhihu.com/api/3/news/’ #获取指定消息,news后面加消息ID

以上3个API全都返回JSON数据.

所以,我们要引入

import urllib.request as http
import json

注意,知乎日报有反爬虫机制,因此我们要模拟浏览器访问,使用:

self.user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
self.headers = { 'User-Agent' : self.user_agent }

一共有4个类,APIMgr,NewsMgr,SingleNews,AllDateNews

其中APIMgr用来管理/访问知乎日报API,NewsMgr是SingleNews和AllDateNews的父类,用来表示SingleNews和AllDateNews通用的函数.

通过分析返回的json数据得知,SingleNews和AllDateNews共有的属性是

    def __init__(self,newsData):
        self.data=newsData
    def getType(self):
        return self.data['type']
    def getID(self):
        return self.data['id']
    def __repr__(self):
        return self.data

因此这些可以放到NewsMgr总类里管理,不会发生冲突,其余的分别放到SingleNews和AllDateNews里.

SingleNews的构造函数通过APIMgr的方法getAssignedNews获得singleNews的数据回传给NewsMgr的构造函数,并构造self.data的数据.

AllDateNews的构造函数通过APIMgr的方法getLatestNews或getBeoreNews获得消息回传NewsMgr的构造函数,使用哪个方法根据AllDateNews构造函数date是否为空决定.如果date为空则返回最新消息,如果date不为空则用正则表达式检验日期格式是否正确,若正确则调用getBeforeNews,否则raise异常.

正则表达式我目前学的还不精,写了个简单的规则:(?!0000)[0-9]{4}[0-9]{4})

完整代码如下:

import urllib.request as http
import json
import re #正则表达式

class APIMgr:
    def __init__(self):
        self.apiLatest='http://news-at.zhihu.com/api/3/news/latest'
        self.apiBefore='http://news.at.zhihu.com/api/3/news/before/'
        self.apiID='http://news-at.zhihu.com/api/3/news/'
        
        #知乎日报禁止了爬虫,因此要模拟浏览器访问
        self.user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
        self.headers = { 'User-Agent' : self.user_agent }
        
    def access(self,url):
        self.req=http.Request(url,headers=self.headers)
        self.fp=http.urlopen(self.req)
        self.mybytes=self.fp.read()
        self.mystr=self.mybytes.decode("utf8")
        self.fp.close()
        return json.loads(self.mystr)
    def getLatestNews(self):
        return self.access(self.apiLatest)
    def getBeoreNews(self,date):
        return self.access(self.apiBefore+date)
    def getAssignedNews(self,id_):
        return self.access(self.apiID+id_)
    def parse(self):
        return json.loads(self.a)

class NewsMgr:
    def __init__(self,newsData):
        self.data=newsData
    def getType(self):
        return self.data['type']
    def getID(self):
        return self.data['id']
    def __repr__(self):
        return self.data
    
class SingleNews(NewsMgr):
    def  __init__(self,apimgr,id_):
        NewsMgr.__init__(self,apimgr.getAssignedNews(id_))
    def getImages(self):
        return self.data['image']
    def getTitle(self):
        return self.data['title']
    def __len__(self):
        return len(self.getBody())
    def getImageSource(self):
        return self.data['date']
    def getGaOrefix(self):
        return self.data['ga_prefix']
    def getBody(self):
        return self.data['body']
    def getShareUrl(self):
        return self.data['share_url']
    def getCSS(self):
        return self.data['css'][0]
        
class AllDateNews(NewsMgr):
    def __init__(self,apimgr,date=''):
        if len(date)==0:
            self.preData=apimgr.getLatestNews()
            NewsMgr.__init__(self,self.preData['stories'])
        elif self.dateIsLegal(date):
            self.preData=apimgr.getBeforeNews()
            NewsMgr.__init__(self,self.preData['stories'])
        else:
            raise 'DateError:date is not legal'
    def getImages(self):
        return self.data[0]['images'][0]
    def getNewsNum(self):
        return len(self.data)
    def getDate(self):
        return self.preData['date']
    def getStories(self):
        return self.data
    def __len__(self):
        return self.getNewsNum()
    def dateIsLegal(self,date):
        return re.match(r'(?!0000)[0-9]{4}[0-9]{4}',date)
    def getTitle(self,index):
        return self.data[index]['title']
    def getID(self,index):
        return self.data[index]['id']

if __name__=='__main__':
    apimgr=APIMgr()
    print('-'*100)
    print('知乎日报ID为4497219的文章题目是:')
    single=SingleNews(apimgr,'4497219')
    print('    ',single.getTitle())
    print('知乎日报ID为4497219的图片地址是:')
    print('    ',single.getImages())
    print('-'*100)
    allnews=AllDateNews(apimgr)
    print('今日的知乎日报消息有:',len(allnews),'条')
    for index in range(len(allnews)):
        print('    标题:',allnews.getTitle(index),'ID:',allnews.getID(index))

运行结果如下:

>>> ================================ RESTART ================================
>>>
—————————————————————————————————-
知乎日报ID为4497219的文章题目是:
使用不同语言的人,对世界的看法可能真不一样
知乎日报ID为4497219的图片地址是:

http://pic1.zhimg.com/188c38f4626467f71c93b668029cdcf7.jpg

—————————————————————————————————-
今日的知乎日报消息有: 18 条
标题: 好的包装让礼物精致有格调,心意满满(多图) ID: 4494751
标题: 饿了 · 喜闻乐见,糖醋味(多图) ID: 4488150
标题: 装空调的师傅发生意外,雇主要承担多大责任? ID: 4496915
标题: 使用不同语言的人,对世界的看法可能真不一样 ID: 4497219
标题: 如果是室外的话,打断冬眠这种行为真的很贱啊 ID: 4496844
标题: 欣赏西洋古典手套,研究人类的行为演变(多图) ID: 4493844
标题: 用很多张图表说明,为什么去年下半年油价跌得特别惨(多图) ID: 4488429
标题: 像刘若英这样 45 岁才生了宝宝,要注意哪些问题? ID: 4494591
标题: 爬楼梯是「最笨的运动」吗? ID: 4493922
标题: 正常饮食蛋白质也「超标」?且慢 ID: 4495520
标题: 留学美国名校的毕业生,很多回国后办起了留学中介 ID: 4494345
标题: 雅虎剥离阿里巴巴 15% 的股份,是如何操作的? ID: 4494036
标题: 有了强大的 iPhone 6,还要另买照相机吗?(多图) ID: 4495369
标题: 怎样让孩子知道自己不是世界的中心?注意方法和火候 ID: 4495269
标题: 我是歌手第三季第五场:一个人干了三位国际大牌的活 ID: 4494219
标题: 相比其他社会科学家,经济学家「特别」有优越感 ID: 4494262
标题: 碰上亲友请求「帮忙献血」,不要想得太复杂 ID: 4495274
标题: 瞎扯 · 如何正确地吐槽 ID: 4495409
>>>

相关文章

返回
  1. mark

  2. 请问 你的是 python x.x ?啊? 我运行时 出现下面的提示:
    import urllib.request as http
    ImportError: No module named request

    • LOSTYOU
    • 二月 16th, 2016

    请问,一楼说的问题,在2.7版本下怎么解决的?谢谢

  1. 暂无 Trackback

You must be logged in to post a comment.