高校新闻抓取分析之百度新闻篇—数据抓取
tips:
- 本文代码使用python3编写
- 代码仓库
- 使用
urllib
抓取数据
百度新闻网页界面分析
在我读大学的时候(18年前),百度新闻还能基于新闻标题或者新闻全文搜索新闻。后面某一天百度新闻的改版,新闻栏目下线,资讯上线。原来的新闻界面找不到了,不过经过一番苦寻,还是找出来了。
1. 数据地址
- 新闻地址:https://news.baidu.com/ns?word=title:(北京大学)&pn=0&cl=2&ct=0&tn=newstitle&rn=20&ie=utf-8&bt=0&et=0
- 尝试搜索北京大学
2. URL分析
序号 | 参数 | 值 | 备注 |
---|---|---|---|
1 | tn | newstitle | 基于新闻标题搜索 |
2 | word | title:(北京大学) | 搜索关键字 |
3 | pn | 0 | 当前页面数据起始位置 |
4 | rn | 20 | 当前页面新闻数 |
5 | ie | utf-8 | 编码 |
6 | bt | 0 | 未知 |
6 | et | 0 | 未知 |
6 | cl | 2 | 未知 |
6 | ct | 0 | 未知 |
3.Html分析
废话不多说,直接上截图:
提取的字段:新闻标题,新闻来源,新闻时间,更多新闻,在Html中其格式都是比较规整。新闻部分html结构如下:
<div class="result title" id="1">
•
<h3 class="c-title">
<a href="http://www.thepaper.cn/newsDetail_forward_8438609" data-click="{
'f0':'77A717EA',
'f1':'9F63F1E4',
'f2':'4CA6DE6E',
'f3':'54E5243F',
't':'1595752997'
}" target="_blank">
中国科协“老科学家学术成长资料采集工程”<em>北京大学</em>联合采集启动...
</a>
</h3>
<div class="c-title-author">澎湃新闻
7小时前
<a href="/ns?word=title%3A%28%E5%8C%97%E4%BA%AC%E5%A4%A7%E5%AD%A6%29+cont:1782421700&same=2&cl=1&tn=newstitle&rn=30&fm=sd" class="c-more_link" data-click="{'fm':'sd'}">查看更多相关新闻>></a>
</div>
</div>
<div class="result title" id="2">
•
<h3 class="c-title">
<a href="http://sc.people.com.cn/n2/2020/0726/c345509-34183157.html" data-click="{
'f0':'77A717EA',
'f1':'9F63F1E4',
'f2':'4CA6DD6E',
'f3':'54E5243F',
't':'1595752997'
}" target="_blank">
<em>北京大学</em>、清华大学等17所高校在川招生行程安排和咨询地址、电话...
</a>
</h3>
<div class="c-title-author">人民网四川站
9小时前
</div>
</div>
实现简单的抓取
1. 构建URL
前面分析了url链接的参数信息,只需要根据关键字和页数来构建url即可。
import urllib.parse
key_word = '北京大学'
# 页码
page = 1
url_query_parse = {
"tn": "newstitle",
"word": "title:({})".format(key_word),
"pn": (page- 1) * 20,# 控制页码
"rn": 20,
"ie": 'utf-8',
'bt': 0,
'et': 0,
'cl': 2,
'ct': 0,
}
# 生成url参数
url_query_parse = urllib.parse.urlencode(url_query_parse)
print(url_query_parse)
# word=title%3A%28%E5%8C%97%E4%BA%AC%E5%A4%A7%E5%AD%A6%29&pn=0&cl=2&ct=0&tn=newstitle&rn=20&ie=utf-8&bt=0&et=0
url = 'https://news.baidu.com/ns?{}'.format(url_query_parse)
print(url)
# https://news.baidu.com/ns?word=title%3A%28%E5%8C%97%E4%BA%AC%E5%A4%A7%E5%AD%A6%29&pn=0&cl=2&ct=0&tn=newstitle&rn=20&ie=utf-8&bt=0&et=0
2. 构建请求头
一般来说,抓取数据需要尽量模仿正常的人访问数据,防止被数据来源网站ban了。所以尽可能模仿浏览器行为。比如请求带请求头,控制请求频率,更换请求IP等。当然,数据采集还是需要准守一定的行业规则,不能把来源网站搞死了。那样大家都没得玩。
经过试验,百度新闻主要检查User-Agent
,Host
,Accept
参数,所以请求时带上这个几个参数。
import random
ua_list = [
'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko',
'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36',
]
headers = {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
'Host': 'news.baidu.com',
}
# 随机设置User-Agent
ua = random.choice(ua_list)
headers.update({"User-Agent": ua})
print(headers)
#{
#"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
#'Host': 'news.baidu.com',
# "User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"
#}
3. 请求数据
首先需要构建请求,然后请求内容,设置超时时间等。请求这部分内容不清楚的话就网站搜索,现在有很多教程都有讲解。拿到请求内容后需要进行解码。
import urllib.request
req = urllib.request.Request(url=url, headers=headers, method='GET')
html = urllib.request.urlopen(req, timeout=5).read().decode('utf-8')
print(html)
4. 完整代码
到这来就完成了爬虫的第一部分,请求数据。当然请求这部分内容还可以再封装函数及优化。
import random
import urllib.parse
import urllib.request
key_word = '北京大学'
page = 1
url_query_parse = {
"tn": "newstitle",
"word": "title:({})".format(key_word),
"pn": (page - 1) * 20,
"rn": 20,
"ie": 'utf-8',
'bt': 0,
'et': 0,
'cl': 2,
'ct': 0,
}
url_query_parse = urllib.parse.urlencode(url_query_parse)
print(url_query_parse)
url = 'https://news.baidu.com/ns?{}'.format(url_query_parse)
print(url)
ua_list = [
'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko',
'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.113 Safari/537.36',
]
headers = {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
'Host': 'news.baidu.com',
}
# 随机设置User-Agent
ua = random.choice(ua_list)
headers.update({"User-Agent": ua})
print(headers)
req = urllib.request.Request(url=url, headers=headers, method='GET')
html = urllib.request.urlopen(req, timeout=5).read().decode('utf-8')
# 保存到本地
print(html)
with open('test.html', 'w', encoding='utf-8') as f:
f.write(html)
总结
- 通过分析百度新闻URL链接,大致弄个清楚URL参数含义及构造方法。
- 通过分析请求头,大致摸清请求头的构造。
- 基于以上成果完成了百度新闻的请求构造及成功请求数据。