文档章节

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

Gaussic
 Gaussic
发布于 2016/07/07 21:53
字数 2318
阅读 2927
收藏 37

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

代码已放到Github:Gaussic Github

1、关键词来源

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

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

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

<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,发现了如下获取数据的代码:

    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 两个参数:

var f = "/n?m=rddata&v=hot_word&type=" + e._hash + "&date=" + e._date;

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

    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 出现位置:

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,显示了国际这一页面的关键词:

{
  "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简单地抓下看:

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'))

输出结果:

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省区将有大暴雨
湖北多地降雨量百年一遇

再添加日期参数:

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'))

输出结果:

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

3、按关键词抓取新闻

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

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

    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 字段。

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

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)

输出结果:

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研究却不得不兼顾项目的研究生)。

© 著作权归作者所有

共有 人打赏支持
Gaussic
粉丝 406
博文 28
码字总数 66971
作品 0
宝山
私信 提问
加载中

评论(4)

Gaussic
Gaussic

引用来自“SimpleFast”的评论

很简单,下载下来这个页面 在解析html文件就可以了,根本没有这么复杂,例子:JD商城
真正需要的代码其实并不多,只是我不知道楼上的URL获取方法导致费了点时间。这个页面是JS调的数据,直接下载还不行,拿到接口就可以直接拿数据了。
Gaussic
Gaussic

引用来自“lqianger”的评论

找个地址不需要这么费劲的,右键-》检查-》network-》XHR-》就只有一条地址 就是最后你说的那个地址
原来可以这样,涨姿势了,谢谢,这是临时做的一个小任务,为了后面每天定期抓取百度新闻数据,为大数据舆情分析准备数据用的。
金贞花
金贞花
很简单,下载下来这个页面 在解析html文件就可以了,根本没有这么复杂,例子:JD商城
l
lqianger
找个地址不需要这么费劲的,右键-》检查-》network-》XHR-》就只有一条地址 就是最后你说的那个地址
原创 | 一点资讯分类新闻爬虫及其文本挖掘

【通往数据自由之路导读】好久不见,手提代码来见,这篇文章分享的是一点资讯新闻网站的抓取和数据分析,机器学习。直接放代码! 流程思路:一点资讯是一个类似今日头条的新闻资讯类网站,我...

何红亮
2017/04/10
0
0
与曹总讨论爬虫方向

@全体成员(all) 曹总 07:50:58 之前说的那个想法,是利用百度或者360的搜索帮助我们查找企业的相关新闻。因为我们能够解析的新闻网站数量毕竟有限,有许多的中小企业在外面所解析的那些有限的...

dotrabbit
2015/10/14
2
1
我为什么讨厌百度

本人闲睱之余跟几个哥们做了个网站,给广大开发队友提供高质量的icon。如今备案上线已经快2月了,但是目前在百度上还是搜不到。还请广大open 队友帮忙看看哪里出了问题。 百度搜索: 可以看到...

java9
2016/05/11
6.4K
58
如果你要做一个百度新闻的功能,你要如何考虑?

如果你要做一个百度新闻的功能,你要如何考虑? ①新闻有一定的时效性,总不能等一个编辑看到一条新闻,然后讨论合不合适上百度新闻首页,再编辑,所以我理解百度新闻应该是从各大媒体、门户...

menxin
2014/01/20
432
6
谷歌 2017 年热搜榜发布,「how to」榜单成最大亮点

摘要 「墙外」人民今年最关心什么,看看谷歌热搜关键词,你就知道。 昨晚,谷歌发布了一年一度的搜索关键词榜单,本次榜单共分为综合、技术、新闻等十五大板块。评定以 2016 年的搜索数据为对...

geekerdeng
2017/12/14
0
0

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周四乱弹 —— Im fine

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @LuckyXu:分享戴荃的单曲《小荃拳之歌》: 手机党少年们想听歌,请使劲儿戳(这里) 今天遇到倒霉事了, @ FalconChen :电梯宕机了我靠 但是...

小小编辑
31分钟前
32
4
【转载】uclibc和glibc的差别

转载自:http://blog.163.com/huangnan0727@126/blog/static/30626184201042022011225/ CC的标准库,就是glibc这个库,里面有GCC各种标准函数的实现,还有各种unix系的函数在里面。 当初创建...

shzwork
40分钟前
2
0
关于360插件化Replugin Activity动态修改父类的字节码操作

近期在接入360插件化方案Replugin时,发现出现崩溃情况。 大概崩溃内容如下: aused by: java.lang.ClassNotFoundException: Didn't find class "x.x.x.xActivity" on path: 我自己在插件代码......

Gemini-Lin
今天
1
0
mybatis缓存的装饰器模式

一般在开发生产中,对于新需求的实现,我们一般会有两种方式来处理,一种是直接修改已有组件的代码,另一种是使用继承方式。第一种显然会破坏已有组件的稳定性。第二种,会导致大量子类的出现...

算法之名
昨天
22
0
单元测试

右键方法 Go To --> Test,简便快速生成测试方法。 相关注解 @RunWith(SpringRunner.class) 表示要在测试环境中跑,底层实现是 jUnit测试工具。 @SpringBootTest 表示启动整个 Spring工程 @A...

imbiao
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部