前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >百度新闻热搜词及其对应新闻的抓取 原

百度新闻热搜词及其对应新闻的抓取 原

作者头像
Gaussic
发布2018-08-17 15:26:43
1.4K0
发布2018-08-17 15:26:43
举报
文章被收录于专栏:GaussicGaussic

转载请注明出处:Gaussic(一个致力于AI研究却不得不兼顾项目的研究生)。

代码已放到Github:Gaussic Github

1、关键词来源

百度新闻的首页显示了当前的热搜新闻词:

点击红框中的更多就会进入全部的热搜词的页面,其页面链接是:http://news.baidu.com/n?cmd=1&class=reci

检查后面的代码,发现这些关键词都是后台JS获取的,直接爬取是不可行的:

代码语言:javascript
复制
<div class="main">
    <div class="content">
        <div class="content_tagstage"></div>
	    <script type="text/javascript">
		    F.use("/static/widget/channel/hotwords/tagstage/tagstage.js");
	    </script>
    </div>
	<div class="aside"><a href="javascript:void(0);"></a></div>
</div>

可以看到这段代码使用了 /static/widget/channel/hotwords/tagstage/tagstage.js。

查看Sources发现了类似的的目录文件:

打开hotwords_c3621a7e.js,发现了如下获取数据的代码:

代码语言:javascript
复制
    a.getdata = function() {
        var e = this;
        var f = "/n?m=rddata&v=hot_word&type=" + e._hash + "&date=" + e._date;
        c.ajax.request(f, {
            onsuccess: function(h) {
                try {
                    e._json = c.json.parse(h.responseText).data;
                    if (e._json.length < e._unitNum) {
                        return
                    }
                    e.randomBlock();
                    e.setPosi();
                    e.setContentStage();
                    e.event();
                    e.rmloading();
                    e.viewDate()
                } catch(g) {}
            },
            onfailure: function() {
                e.log("get json error")
            }
        })
    };

这段代码ajax访问的是下面这个链接,需要传入 e._hash 和 e._date 两个参数:

代码语言:javascript
复制
var f = "/n?m=rddata&v=hot_word&type=" + e._hash + "&date=" + e._date;

e._date 是所需要的日期的数据,在 a.init 中定义了如下代码:

代码语言:javascript
复制
    a.init = function() {
        var e = this;
        e._width = c.page.getViewWidth() > e._minWidth ? c.page.getViewWidth() : e._minWidth;
        e._height = c.page.getViewHeight() || 512;
        e._unitWidth = Math.floor((e._width - e._widthMinus - (2 * e._col - 1) * e._unitMargin) / (e._col * 2));
        e._unitHeight = Math.floor(e._unitWidth / e._imgWHRatio);
        e._hash = location.hash.replace("#", "") || 0
    };

说明它要么是0,要么是 一个包含 "#" 的码。再网上继续查 _hash 出现位置:

代码语言:javascript
复制
F.module("/static/widget/channel/hotwords/tagstage/tagstage.js",
function(d, b) {
    var c = baidu = d("/static/common/lib/tangram/base/base.js");
    var a = {
        _imgWHRatio: 1.4,
        _unitNum: 20,
        _row: 2,
        _col: 4,
        _minWidth: 1000,
        _width: 0,
        _height: 0,
        _widthMinus: 140,
        _unitMargin: 10,
        _unitWidth: 0,
        _unitHeight: 0,
        _subRow: 2,
        _subCol: 2,
        _posi: [],
        _firstRender: true,
        _hasevent: false,
        _date: "",
        _hash: 0,
        _el: c.dom.q("content_tagstage")[0]
    };

发现 _date 默认为空字符串,_hash 默认为0。

尝试在浏览器中访问 http://news.baidu.com/n?m=rddata&v=hot_word&type=0,得到了如下的JSON格式的数据:

(转载请注明出处:Gaussic(一个致力于AI研究却不得不兼顾项目的研究生)。)

在Postman中以JSON格式打开如下图所示:

结果一目了然,返回的是最初始页面的关键词,把type换成1,显示了国际这一页面的关键词:

代码语言:javascript
复制
{
  "errno": 0,
  "data": [
    {
      "title": "狗狗咬爆百个气球",
      "desc": "快如闪电 宠物狗39秒咬爆100个气球",
      "query_word": "狗狗咬爆百个气球",
      "image": "",
      "image_v": ""
    },
    {
      "title": "自拍死75%是男性",
      "desc": "“自拍死”已成全球现象 75%死者是男性",
      "query_word": "自拍死75%是男性",
      "image": "",
      "image_v": ""
    },
    {
      "title": "缅甸女被卖到大陆",
      "desc": "为打工大批缅甸女被卖大陆沦为人妻 强迫...",
      "query_word": "缅甸女被卖到大陆",
      "image": "http://timg01.baidu-img.cn/timg?tc&size=c378_m272&sec=0&quality=100&di=2cc7d845ea7feb12718f12cad937b0d7&src=http%3A%2F%2Ffj.china.com.cn%2Fuploadfile%2F2016%2F0706%2F1467785414204871.jpg",
      "image_v": "http://timg01.baidu-img.cn/timg?tc&size=c184_m272&sec=0&quality=100&di=2cc7d845ea7feb12718f12cad937b0d7&src=http%3A%2F%2Ffj.china.com.cn%2Fuploadfile%2F2016%2F0706%2F1467785414204871.jpg"
    },
    {
      "title": "大妈成国宝级匠人",
      "desc": "",
      "query_word": "大妈成国宝级匠人",
      "image": "",
      "image_v": ""
    }
    ...
  ]
}

注:一楼的哥们给了个更简单的方法,作为一个前端小白真是涨了姿势,右键 > Network > XHR 就能直接看到这个URL了。

2、获取关键词数据

现在,获取数据的接口就有了,用python简单地抓下看:

代码语言:javascript
复制
import requests
from bs4 import BeautifulSoup
import urllib

# 基本Url
base_url = 'http://news.baidu.com/n?m=rddata&v=hot_word'
hot_type = '0'

parameters = {'type': hot_type}

# 获取 JSON 数据
r = requests.get(base_url, params=parameters)
print(r.url)

hot_words_dict = r.json()

# 输出热搜关键词
for hot_word in hot_words_dict.get('data'):
    print(hot_word.get('query_word'))

输出结果:

代码语言:javascript
复制
http://news.baidu.com/n?m=rddata&v=hot_word&type=0
习近平会见联合国秘书长
习近平会见巴布亚新几内亚总理
东南沿海将迎暴雨
南京南动车所塌方
湖南暴雨过后各地频频捡到大鱼
6.6亿造诺亚方舟
带4000元钱穷游中国
好声音更名
葡萄牙2-0威尔士进决赛
霍建华林心如婚礼没请胡歌
中国正式加入国际移民组织
房地产税法最快2017年通过
43人中国旅行团护照在瑞典被抢
长江中下游水位全线超警
上海垃圾偷倒太湖
里约奥运计划发900万避孕套
孕妇被赶下车产子剧情反转
开车吃棒冰被罚
胡歌祝福霍建华林心如结婚
万科A跌停
陈晓陈妍希领证
林心如霍建华宣布婚期
交通违规优惠券
朱诺进入木星轨道
4000吨垃圾偷运太湖
合建马六甲港口
61岁高龄产妇产子
男子4年写150万字日记给亡妻
江苏等6省区将有大暴雨
湖北多地降雨量百年一遇

再添加日期参数:

代码语言:javascript
复制
hot_type = '2'
hot_date = '20160705'

parameters = {'type': hot_type, 'date': hot_date}

# 获取 JSON 数据
r = requests.get(base_url, params=parameters)
print(r.url)

hot_words_dict = r.json()

# 输出热搜关键词
for hot_word in hot_words_dict.get('data'):
    print(hot_word.get('query_word'))

输出结果:

代码语言:javascript
复制
http://news.baidu.com/n?m=rddata&v=hot_word&type=2&date=20160705
金价5连涨创新高
结婚没嫁妆遭轮奸
乡村小学减员潮
最帅交警一夜成网红
宜家回应商场裸照门
男子拿驾照喜极而泣
陈冠希晒近照苍老
身份证异地办理
10岁男童重192公斤
女特工过110岁生日
10省区市大暴雨
一批新规明日起实施
防二手烟神器
扶贫大会上演全武行
医院雇人骗医保
胚胎沉睡18年被唤醒
京城商圈大尺度雕塑
少年开发机器人律师
中国香港迪士尼每况愈下
北影毕业照美女如云
球场上钓鱼打枪
少女被关铁笼成性奴
单身汪娶手机当老婆
孙俪12岁起恨透父亲
学生当街看色情片
杰克逊家中物品曝光
贵州特大暴雨
太阳的后裔拍中国版
国足复制冰岛奇迹
周杰伦胖13公斤

3、按关键词抓取新闻

每一个关键词的方块,点进去就是该关键词的新闻页面:

在之前的JS文件中,各方块对应的代码如下所示:

代码语言:javascript
复制
    a.setContentStageInfo = function() {
        var j = this;
        var i = c.dom.q("content_tagstage_unit"),
        h = "",
        g = "http://news.baidu.com/ns?tn=news&word=",
        e = "";
        function f(k) {
            return k.replace(/\[br\]/ig, "")
        }
        c.array.each(i,
        function(o, m) {
            var l = j._json[m],
            k = j._posi[m];
            e = ['<div class="mask"><div class="cont_mask">', '<span class="cont_title">' + f(l.title) + "</span>", '<span class="cont_desc">' + f(l.desc) + "</span>", "</div></div>"].join("");
            if (k.wordonly || !l.image || Math.random() > 0.6) {
                h = ['<a href="' + g + f(l.query_word) + '" class="' + k.color + '" target="_blank">', '<span class="title">' + f(l.title) + "</span>", e, "</a>"].join("")
            } else {
                h = ['<a href="' + g + f(l.query_word) + '" target="_blank">', '<img src="' + (k.imgv ? l.image_v: l.image) + '">', e, "</a>"].join("")
            }
            o.innerHTML = h
        });
        j.setFontStyle();
        j.setcontentStageCenter()
    };

基本url为 http://news.baidu.com/ns?tn=news&word=,接参数word为 JSON数据的 query_word 字段。

按关键词抓取新闻标题、链接、数据源与发布时间:

代码语言:javascript
复制
query_word = '43人中国旅行团护照在瑞典被抢'    
news_base_url = 'http://news.baidu.com/ns?tn=news'

news_url = news_base_url + query_word
parameters = {'word': query_word}

# 获取 源码 数据
r = requests.get(news_base_url, params=parameters)
print(r.url)

soup = BeautifulSoup(r.text, 'lxml')
news_html_list = soup.select('div.result')
news_list = []
for news_html in news_html_list:
    news = {}
    news['标题'] = news_html.a.get_text().strip()
    news['链接'] = news_html.a['href']
    source = news_html.find('p', 'c-author').get_text().strip().replace('\xa0\xa0', ' ').split(' ')
    news['来源'] = source[0]
    news['发布日期'] = source[1]
    
    news_list.append(news)

for news in news_list:
    print(news)

输出结果:

代码语言:javascript
复制
http://news.baidu.com/ns?tn=news&word=43%E4%BA%BA%E4%B8%AD%E5%9B%BD%E6%97%85%E8%A1%8C%E5%9B%A2%E6%8A%A4%E7%85%A7%E5%9C%A8%E7%91%9E%E5%85%B8%E8%A2%AB%E6%8A%A2
{'链接': 'http://news.ifeng.com/a/20160706/49300638_0.shtml', '来源': '凤凰网', '发布日期': '2016年07月06日', '标题': '43人中国旅行团护照在瑞典被抢'}
{'链接': 'http://bj.people.com.cn/n2/2016/0706/c233086-28617563.html', '来源': '人民网', '发布日期': '2016年07月06日', '标题': '43人中国旅行团护照瑞典被抢 旅行社将负责赔偿'}
{'链接': 'http://www.dzwww.com/xinwen/shehuixinwen/201607/t20160706_14581063.htm', '来源': '大众网', '发布日期': '2016年07月06日', '标题': '在瑞典吃饭时突然护照被抢 43名中国游客无奈回国'}
{'链接': 'http://news.shm.com.cn/2016-07/06/content_4497629.htm', '来源': '水母网', '发布日期': '2016年07月06日', '标题': '43人中国旅行团护照在瑞典被抢 游客正分批回国'}
{'链接': 'http://new.qi-che.com/shehuiredia/xinwen-20160706270778.html', '来源': '汽车中国', '发布日期': '2016年07月06日', '标题': '今日头条新闻43人中国旅行团护照在瑞典被抢劫丢失 正分批回国最'}
{'链接': 'http://news.k618.cn/society/rd/201607/t20160706_7981118.html', '来源': '未来网', '发布日期': '2016年07月06日', '标题': '43人中国旅行团护照瑞典被抢 旅行社将负责赔偿'}
{'链接': 'http://www.rmzxb.com.cn/c/2016-07-06/903304.shtml?n2m=1', '来源': '人民政协网', '发布日期': '2016年07月06日', '标题': '中国43人旅行团在瑞典被抢 所有人护照丢失 (1)'}
{'链接': 'http://news.jschina.com.cn/system/2016/07/06/029103019.shtml', '来源': '中国江苏网', '发布日期': '2016年07月06日', '标题': '43人中国旅行团护照瑞典被抢 旅行社将负责赔偿'}

结果远不止这些,还需要加几个参数才能拿到所有数据,这个就不再讨论了。

转载请注明出处:Gaussic(一个致力于AI研究却不得不兼顾项目的研究生)。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016/07/07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、关键词来源
  • 2、获取关键词数据
  • 3、按关键词抓取新闻
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档