python3+urllib撸新浪滚动新闻爬虫

需求:

爬取全部新浪新闻

切入点:

这里写图片描述
这里写图片描述
新浪新闻主页组织很杂,但是通过观察可知,新浪滚动新闻中罗列了所有新闻,而且可以通过类别或日期选择查看,所以,要想爬取所有新闻,我们把切入点变为:

爬取新浪滚动新闻(腾讯新闻等其他新闻网站也是如此)

分析网页

进入新浪滚动新闻页面:

新浪滚动新闻

http://roll.news.sina.com.cn/s/channel.php?ch=01#col=89&spec=&type=&ch=01&k=&offset_page=0&offset_num=0&num=60&asc=&page=1

查看网页源代码:

这里写图片描述

居然可以看到一条条a标签的新闻,简直方便了spider!

然而高兴太早,后来发现这些新闻和页面显示的根本不一样,而且翻页操作后这些内容也不会变。

利索当然的想到这些是ajax请求的,不然怎么滚动。

F12看看吧:

这里写图片描述

果不其然,可以看到,每条新闻以json的形式干净利索的展示出来,再看看url请求:

这里写图片描述

请求url为:

http://roll.news.sina.com.cn/interface/rollnews_ch_out_interface.php?col=89&spec=&type=&ch=01&k=&offset_page=0&offset_num=0&num=60&asc=&page=12&r=0.23150597515105287

将url复制到浏览器里,直接返回了json数据!完美!相当于良心的sina把数据接口开放出来了。

为了获取所有的新闻,我们需要分析url的规律,以获取所有数据:

今天是2017年9月19日,滚动新闻有200多页,而翻到最后一页发现新闻时间为9月8日,担心页面下有个时间选项,可以选择更早时间的新闻,选择后,url发生了变化:

http://roll.news.sina.com.cn/interface/rollnews_ch_out_interface.php?col=89&spec=&type=&date=2017-09-01&ch=01&k=&offset_page=0&offset_num=0&num=60&asc=&page=1&r=0.11767799118102595

分析一下这个url,很明显了吧已经,变量有:date(时间)、col(类别)、num(每页条数)、asc(增序)、page(第几页)、r(随机量,据说防止缓存用的),我们爬虫时要控制的有:

date、page、col(如果所有类别都爬则不用管)

所以,爬每个date的所有page里的链接就OK

上码:

from bs4 import BeautifulSoup
import urllib.request,re,os

date="2017-09-19"
init_url = 'http://roll.news.sina.com.cn/interface/rollnews_ch_out_interface.php?col=89&spec=&type=&date='+date+'&ch=01&k=&offset_page=0&offset_num=0&num=60&asc=&page='  

targetPath = "E:\\workspace\\pachong\\新浪新闻"

#定义保存文件函数  
def saveFile(data,title,types,link):  
    path = targetPath+"\\"+title+".txt"  
    file = open(path,'wb')  
    page = '题目:'+title+'\n'+'类别:'+types+'\n'+'链接:'+link+'\n'+'日期:'+date+'\n'  
    file.write(page.encode('utf-8'))  

    for d in data:   
        file.write(d.encode('utf-8'))  
    file.close() 

def get_sina_content(link):
    response = urllib.request.urlopen(link)  
    data = response.read()
    data = data.decode('UTF-8')
    soup=BeautifulSoup(data)

    content = ""
    for one in soup(class_="content"):
        content = str(one)
    dr = re.compile(r'<[^>]+>',re.S)
    dd = dr.sub('',content)
    print(dd)    
    return dd

page = 1
while page: 
    #请求  
    request = urllib.request.Request(init_url+str(page))    
    #爬取结果  
    response = urllib.request.urlopen(request)  

    data = response.read()  

    #设置解码方式  
    data = data.decode('gbk')  
    if data.count('channel')==0:
        page = 0
        break  
    reg_str = r'channel.*?title : "(.*?)",id.*?title : "(.*?)",url : "(.*?)",type' 
    pattern = re.compile(reg_str,re.DOTALL)  
    items = re.findall(pattern,data) 
    for item in items: 
                print("类别"+item[0]+"题目:"+item[1]+"链接:"+item[2])
                data = get_sina_content(item[2])
                saveFile(data,item[1],item[0],item[2])
    page+=1
tips:通过判断返回的json中是否有channel判断该页是否还有新闻。

bug:

测试后发现,很多新闻正文爬取有误,仔细分析发现新闻正文部分所在的标签无规律可寻,需要正文提取算法的辅助,研究后给与解决办法。

反思:

本文只用了urllib,加了一点点bs4,之前想爬腾讯滚动新闻,发现页面同样是ajax渲染数据,但是无法通过url获得json数据,今后的几天攻克一下还有scrapy、request等包留在以后学。

love py

猜你喜欢

转载自blog.csdn.net/lk7688535/article/details/78034252
今日推荐