Python爬取新闻动态评论

四年前的文章了,现在才看见没通过。。。。当初明明过了的。。。

1.前些天打开网易新闻,于是点开爬取该新闻的评论。

2.以前爬取的网页都是静态的,都是源代码中直接就有,一眼就可以观察到的,而这次打开却不一样,根本没有自己想要的评论内容。然后通过搜索学习,知道了获取数据的办法。主要是html中的JavaScript和Python中json模块。

具体步骤如下:

1.输入网址,用谷歌浏览器获取json数据

输入网址后,按F12,出现该界面

Python爬取新闻动态评论_第1张图片

2.查找所需要的数据

观察加载的这些内容可以发现,有图片,有html文件等。一开始并不知道评论内容存在哪里,搜索html依次查看

Python爬取新闻动态评论_第2张图片

点击Preview进行查看,发现红框里的内容才是需要的数据

3.点击headers获取url

Python爬取新闻动态评论_第3张图片

这个url只有一个,加载的是“热门跟帖”的内容,而加载“最新跟帖”的到现在有17个

Python爬取新闻动态评论_第4张图片

Python爬取新闻动态评论_第5张图片

打开一个网址,是以json数据进行显示的

这里附了张图,应该不合法。。。。

其他的页面的显示形式也是相同的。

4.写代码爬取数据,一开始只对一页内容进行爬取

一开始从来没有接触过json数据,不知道怎么爬取,开始的思路是想用BeautifulSoup模块,可是这是用js写的,于是就想用正则匹配将没用的全部替换掉,留下想要的内容。后来发现这是不可行的。然后便去了解json。

最后明白,获取的网页中json数据声明了一个变量,然后该变量用花括号将所有评论内容包含进去了。

思路转换为通过Python中字典的用法,用key进行取值,得到想要的内容。

json.dumps()方法可以将Python对象编码为json字符串(encoding)

json.loads()方法可以将json格式的字符串解码为Python对象(decoding)

可以看这个关于Python处理json的文章:

http://liuzhijun.iteye.com/blog/1859857

http://www.cnblogs.com/coser/archive/2011/12/14/2287739.html

所以爬取第一页的代码为:

#coding:utf-8
import urllib
import re
import json
#用户id+评论+顶
def getHtml(url):
    page=urllib.urlopen(url)
    html=page.read()
    return html
def getItems(html):
    #一开始写的时候还在该函数的开始加了这两句代码,主要就是这两个方法没有了解清楚
    #data1=json.dumps(html)
    #data=json.loads(data1)
    #这是没必要的,直接替换再转换就可以。将开头的var replyData=和结尾的;替换掉再转成Python时才能对字典进行处理
    reg=re.compile(" \[")
    data=reg.sub(' ',html)
    reg1=re.compile("var replyData=")
    data=reg1.sub(' ',data)
    reg2=re.compile('<\\\/a>\]')
    data=reg2.sub('',data)
    reg3=re.compile(';')
    data=reg3.sub('',data)
    reg4=re.compile('')#(.*?)这样匹配是不对的,替换不掉(还不清楚原因)
    data=reg4.sub('',data)
    reg5=re.compile('')
    data=reg5.sub('',data)
    data=json.loads(data)#这句代码的作用是将数据转换成Python对象,然后根据字典的key取值得到想要的内容
    f=open('wy.txt','a+')
    for i in data['hotPosts']:
        f.write(i['1']['f'].encode('utf-8')+'\n')
        f.write(i['1']['b'].encode('utf-8')+'\n')
        f.write(i['1']['v'].encode('utf-8')+'\n')
    f.close()

url='http://comment.news.163.com/data/news_guonei8_bbs/df/B9C8EJDC0001124J_1.html'#(热门跟帖)
html=getHtml(url)
getItems(html)

5.爬取多页数据 

#coding:utf-8
import urllib2
import re
import json
class WYTie():
    def __init__(self):
        self.pageIndex=1
        self.usr_agent="Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36"
        self.headers={'Usr_Agent':self.usr_agent}
        self.url1='http://comment.news.163.com/data/news_guonei8_bbs/df/B9C8EJDC0001124J_1.html'
    def getUrl(self,pageIndex):
        url2='http://comment.news.163.com/cache/newlist/news_guonei8_bbs/B9C8EJDC0001124J_'+str(pageIndex)+'.html'
        return url2
    def getHtml(self,url):
        try:
            request=urllib2.Request(url,headers=self.headers)
            page=urllib2.urlopen(request)
            html=page.read()
            return html
        except urllib2.URLError,e:
            if hasattr(e,'reason'):
                print u'连接失败',e.reason
                return None
    #网址打开第一页有热门跟帖和最新跟帖,而第二页往后显示的都是最新跟帖
    #先处理热门跟帖,因为网址是固定的只有一个。然后处理多页的最新跟帖
    #获取热门跟帖的内容。
    def getReply(self):
        url=self.url1
        data=self.getHtml(url)
        rep=re.compile(" \[")
        data=rep.sub(' ',data)
        rep1=re.compile("<\\\/a>\]")
        data=rep1.sub(' ',data)
        rep2=re.compile("")
        data=rep2.sub(' ',data)
        rep3=re.compile("var replyData=")
        data=rep3.sub(' ',data)
        rep4=re.compile(";")
        data=rep4.sub(' ',data)
        data0=json.loads(data)#进行转换,得到dict类型,访问字典
        f=open('wyNews.txt','a')
        for i in data0['hotPosts']:
            f.write(i['1']['f'].encode('utf-8')+'\n')
            f.write(i['1']['b'].encode('utf-8')+'\n')
            f.write(i['1']['v'].encode('utf-8')+'\n')
        f.close()
    #获取多页的热门跟帖
    def getPostlist(self):
        L=range(1,18)
        for pageIndex in L:
            url=self.getUrl(pageIndex)
            data=self.getHtml(url)
            rep=re.compile(" \[")
            data=rep.sub(' ',data)
            rep1=re.compile("<\\\/a>\]")
            data=rep1.sub(' ',data)
            rep2=re.compile("")
            data=rep2.sub(' ',data)
            rep3=re.compile("var newPostList=")
            data=rep3.sub(' ',data)
            rep4=re.compile(";")
            data=rep4.sub(' ',data)
            data1=json.loads(data)#进行转换,得到dict类型,访问字典
            f=open('wyNews.txt','a')
            for i in data1['newPosts']:
                f.write(i['1']['f'].encode('utf-8')+'\n')
                f.write(i['1']['b'].encode('utf-8')+'\n')
                f.write(i['1']['v'].encode('utf-8')+'\n')
            f.close()


spider=WYTie()
spider.getReply()
spider.getPostlist()

代码是正确的,内容也都完全爬取下来,不过写完后发现一个问题就是,两次替换都差不多,每个函数重复一遍让代码显得很不简洁。然后就把替换的内容写成一个函数而后调用就可以了。

下面是代码:

# encoding=utf-8
import urllib2
import json
import re
class WYTie():
    def __init__(self):
        self.user_agent='Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36'
        self.headers={'User-Agent':self.user_agent}
        self.url1='http://comment.news.163.com/data/news_guonei8_bbs/df/B9C8EJDC0001124J_1.html'
    def getUrl(self,pageIndex):
        url2='http://comment.news.163.com/cache/newlist/news_guonei8_bbs/B9C8EJDC0001124J_'+str(pageIndex)+'.html'
        return url2
    def getHtml(self,url):
        try:
            request=urllib2.Request(url,headers=self.headers)
            page=urllib2.urlopen(request)
            html=page.read()
            return html
        except urllib2.URLError,e:
            if hasattr(e,'reason'):
                print u"连接失败",e.reason
                return  None
    #将所有替换写成函数,在后面进行调用
    def getRaplace(self,data,i):
        if i==1:
            data=data.replace('var replyData=','')
        else:
            data=data.replace('var newPostList=','')
        rep=re.compile(" \[")
        data=rep.sub('--',data)
        rep2=re.compile('<\\\/a>\]')
        data=rep2.sub('',data)
        rep3=re.compile("")
        data=rep3.sub(' ',data)
        rep4=re.compile(";")
        data=rep4.sub(' ',data)
        return data
    #将数据转换并进行存储
    def getItems(self):
        with open('wynewsssss.txt','a') as f:
            f.write('用户名'+'|'+'评论'+'|'+'顶'+'\n')
        for pageIndex in range(1,18):
            if pageIndex==1:
                url=self.url1
                data=self.getHtml(url)
                data=self.getRaplace(data,pageIndex)
                value=json.loads(data)
                f=open('wynewsssss.txt','a')
                for item in value['hotPosts']:
                    f.write(item['1']['f'].encode('utf-8')+'|')
                    f.write(item['1']['b'].encode('utf-8')+'|')
                    f.write(item['1']['v'].encode('utf-8')+'\n')
                f.close()
            else:
                url=self.getUrl(pageIndex)
                data=self.getHtml(url)
                data=self.getRaplace(data,pageIndex)
                value=json.loads(data)
                f=open('wynewsssss.txt','a')
                for item in value['newPosts']:
                    f.write(item['1']['f'].encode('utf-8')+'|')
                    f.write(item['1']['b'].encode('utf-8')+'|')
                    f.write(item['1']['v'].encode('utf-8')+'\n')
                f.close()


spider=WYTie()
spider.getItems()

 

你可能感兴趣的:(json,正则表达式)