您的位置:首页 > 编程语言 > Python开发

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

2017-09-19 20:29 656 查看

需求:

爬取全部新浪新闻

切入点:





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

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

分析网页

进入新浪滚动新闻页面:

新浪滚动新闻

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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: