爬取新浪微博热搜
一、准备工作
在搜索中查看榜单,先爬取实时热搜榜
老样子,在Chrome中检查下元素,可以发现我们想要的内容
但在网页源代码里并没有,看来这用到了 js 了。
对于 js 动态网页,还是老样子俩种方法,但我们如果我们想要的是定时多次爬取热搜呢,这样子的话用 selenium 模仿浏览器显然效率很低,就用第一种吧,通过 json 数据爬取。详情见以前的文章
监视下 XHR ,只有一个,并不是我们想要的
那 js 呢。都找了一遍也没发现符合的,那怎么办?得来个详细的查找
检查下大的标签,发现热搜标题都在 "star_name" 里,在网页源代码里搜下
找到了50个匹配项,热搜榜正好是50个。看下都在<script> 这个javascript里,再仔细看下,里面有些链接不正是网页链接么,只是怪怪的。
复制下 href 里的这个
%E6%9C%9D%E9%B2%9C%E9%98%85%E5%85%B5
这不是中文在网址的格式么,老样子,处理下
>>> import urllib
>>> a = '%E6%9C%9D%E9%B2%9C%E9%98%85%E5%85%B5'
>>> urllib.parse.unquote(a)
'朝鲜阅兵'
咦,就是热搜第一个!
每个热搜的链接只要在前面加上 'http://s.weibo.com/weibo/' 就行了。
那么直接用 requests + re 获取 "star_name" 里的 href 的热搜关键词。
这时又碰到了问题了,居然一直找不到,把 requests 获得的代码输出下
比网页源代码中的文件多了些 \ , 25 。前面我们查看网页源代码时,热搜是存在 <script> 里的,这个 js 的作用是应该就是把这些链接加上一些字符干扰,不让轻易爬取。
现在在回到 js 里找找,点开 player.js,复制下链接打开
在里面发现大量的 replace。估计就是这页啦
原理知道了,就没什么难了,用正则获取网页源代码中包含热搜链接的内容,再处理下就 OK 了
二、代码
import requests
import re
import urllib
r = requests.get('http://s.weibo.com/top/summary?cate=realtimehot')
html = r.text
raw = re.findall(r'class=\\"star_name\\"><a href=\\"\\/weibo\\/(.*?)&Refer=top', html)
titles = []
names = []
links = []
for i in raw:
titles.append(i.replace('25', ''))
for i in titles:
names.append(urllib.parse.unquote(i))
link = 'http://s.weibo.com/weibo/' + i
links.append(link)
for k,v in enumerate(names, 1):
print(k, v, links[int(k)-1])
运行下
1 朝鲜阅兵 http://s.weibo.com/weibo/%E6%9C%9D%E9%B2%9C%E9%98%85%E5%85%B5
2 baby+小海绵 http://s.weibo.com/weibo/baby%2B%E5%B0%8F%E6%B5%B7%E7%BB%B5
3 土豪这么滑雪 http://s.weibo.com/weibo/%E5%9C%9F%E8%B1%AA%E8%BF%99%E4%B9%88%E6%BB%91%E9%9B%AA
4 学霸关晓彤 http://s.weibo.com/weibo/%E5%AD%A6%E9%9C%B8%E5%85%B3%E6%99%93%E5%BD%A4
5 邓超+小何 http://s.weibo.com/weibo/%E9%82%93%E8%B6%85%2B%E5%B0%8F%E4%BD%95
6 陈羽凡发文 http://s.weibo.com/weibo/%E9%99%88%E7%BE%BD%E5%87%A1%E5%8F%91%E6%96%87
7 小镇诞生50年来唯一婴儿 http://s.weibo.com/weibo/%E5%B0%8F%E9%95%87%E8%AF%9E%E7%94%9F50%E5%B9%B4%E6%9D%A5%E5%94%AF%E4%B8%80%E5%A9%B4%E5%84%BF
8 七岁女儿顺手牵羊 http://s.weibo.com/weibo/%E4%B8%83%E5%B2%81%E5%A5%B3%E5%84%BF%E9%A1%BA%E6%89%8B%E7%89%B5%E7%BE%8A
9 大学其实是把整容刀 http://s.weibo.com/weibo/%E5%A4%A7%E5%AD%A6%E5%85%B6%E5%AE%9E%E6%98%AF%E6%8A%8A%E6%95%B4%E5%AE%B9%E5%88%80
10 雄安新区凌晨发布政策 http://s.weibo.com/weibo/%E9%9B%84%E5%AE%89%E6%96%B0%E5%8C%BA%E5%87%8C%E6%99%A8%E5%8F%91%E5%B8%83%E6%94%BF%E7%AD%96
三、优化
要爬别的榜单只要换个榜单的网址就行了,那如果我们要更深入的分析呢,比如说爬取每个热点的热门评论等
干脆用个类
import requests
import re
import urllib
class Top(object):
def __init__(self, banner):
self.banner = banner
self.titles = []
self.names = []
self.links = []
def get_top(self, url):
r = requests.get(url)
html = r.text
raw = re.findall(r'class=\\"star_name\\"><a href=\\"\\/weibo\\/(.*?)&Refer=top', html)
for i in raw:
self.titles.append(i.replace('25', ''))
for i in self.titles:
self.names.append(urllib.parse.unquote(i))
link = 'http://s.weibo.com/weibo/' + i
self.links.append(link)
def out_put(self):
print(self.banner)
for k,v in enumerate(self.names, 1):
print(k, v, self.links[int(k)-1])
if __name__ == '__main__':
realtimehot = Top('实时热搜榜')
realtimehot.get_top("http://s.weibo.com/top/summary?cate=realtimehot")
realtimehot.out_put()
pointhot = Top('热点热搜榜')
pointhot.get_top("http://s.weibo.com/top/summary?cate=total&key=all")
pointhot.out_put()
运行下
================= RESTART: C:/Users/Why Me/Desktop/爬微博热搜2.py =================
实时热搜榜
1 卓伟回应陈羽凡 http://s.weibo.com/weibo/%E5%8D%93%E4%BC%9F%E5%9B%9E%E5%BA%94%E9%99%88%E7%BE%BD%E5%87%A1
2 范冰冰弟弟 http://s.weibo.com/weibo/%E8%8C%83%E5%86%B0%E5%86%B0%E5%BC%9F%E5%BC%9F
3 Xplay6库里定制版 http://s.weibo.com/weibo/Xplay6%E5%BA%93%E9%87%8C%E5%AE%9A%E5%88%B6%E7%89%88
4 许昕+丹羽孝希 http://s.weibo.com/weibo/%E8%AE%B8%E6%98%95%2B%E4%B8%B9%E7%BE%BD%E5%AD%9D%E5%B8%8C
5 张信哲薛之谦 http://s.weibo.com/weibo/%E5%BC%A0%E4%BF%A1%E5%93%B2%E8%96%9B%E4%B9%8B%E8%B0%A6
6 女子遭家暴身亡 http://s.weibo.com/weibo/%E5%A5%B3%E5%AD%90%E9%81%AD%E5%AE%B6%E6%9A%B4%E8%BA%AB%E4%BA%A1
7 你是手机的爸爸 http://s.weibo.com/weibo/%E4%BD%A0%E6%98%AF%E6%89%8B%E6%9C%BA%E7%9A%84%E7%88%B8%E7%88%B8
8 郑渊洁买10套房 http://s.weibo.com/weibo/%E9%83%91%E6%B8%8A%E6%B4%81%E4%B9%B010%E5%A5%97%E6%88%BF
9 交警一查朋友也是酒驾 http://s.weibo.com/weibo/%E4%BA%A4%E8%AD%A6%E4%B8%80%E6%9F%A5%E6%9C%8B%E5%8F%8B%E4%B9%9F%E6%98%AF%E9%85%92%E9%A9%BE
10 陈羽凡朋友圈 http://s.weibo.com/weibo/%E9%99%88%E7%BE%BD%E5%87%A1%E6%9C%8B
...
爬取热搜里的有关内容
如果要获取每个热搜里面的相关新闻呢
例如下面这些
还是一样,我们找到内容的大标签,这次我们先在网页源代码里找找看
居然跟前面找热搜榜是一样的,这次文字以 utf-8 的形式存在里面,如下面这些,怎么转化为中文呢,可以直接print,以前关于编码的文章有别的方法介绍,这里就不多说了。
还是老样子加了点干扰防止爬的。。提取的好辛苦。直接上代码了,有点麻烦。
import requests
import re
import urllib
import time
class Top(object):
def __init__(self, banner):
self.banner = banner
self.titles = []
self.names = []
self.links = []
self.summary = {}
self.headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36"}
def get_top(self, url):
r = requests.get(url, headers=self.headers)
html = r.text
raw = re.findall(r'class=\\"star_name\\"><a href=\\"\\/weibo\\/(.*?)&Refer=top', html)
for i in raw:
self.titles.append(i.replace('25', ''))
for i in self.titles:
self.names.append(urllib.parse.unquote(i))
link = 'http://s.weibo.com/weibo/' + i
self.links.append(link)
time.sleep(1.5)
self.get_news(link)
#print('Down One Hot')
def get_news(self, link):
new = []
ne = []
n = []
z = []
r2 = requests.get(link, headers=self.headers)
html2 = r2.text
news = re.findall(r'node-type=\\"feed_list_content\\" nick-name=\\"(.*?) <', html2)
for i in news:
c = i.encode()
new.append(c.decode('unicode_escape'))
for i in new:
a = re.sub(r'\s', '',i).replace('"><emclass="red">', "-").replace('<\\/em>', '-')
ne.append(a)
for i in ne:
s = re.sub(r'<.*?>|\u200b','', i)
n.append(s)
for i in n:
z.append(i.split('">'))
self.summary[link] = z
def out_put(self):
print(self.banner.center(75))
for k,v in enumerate(self.names, 1):
print(k, v, self.links[int(k)-1])
for i in self.summary[self.links[int(k)-1]]:
try:
print('{} : {}'.format(i[0], i[1]))
except:
print('信息缺失')
if __name__ == '__main__':
realtimehot = Top('实时热搜榜')
realtimehot.get_top("http://s.weibo.com/top/summary?cate=realtimehot")
realtimehot.out_put()
pointhot = Top('热点热搜榜')
pointhot.get_top("http://s.weibo.com/top/summary?cate=total&key=all")
pointhot.out_put()
运行下:
1 白百何颁奖 http://s.weibo.com/weibo/%E7%99%BD%E7%99%BE%E4%BD%95%E9%A2%81%E5%A5%96
南都娱乐周刊 : #第八届导演协会年度盛典#范冰冰凭借《我不是潘金莲》获得2017导演协会年度盛典最佳女演员奖,再得影后!白-百何-作为颁奖-嘉宾上台为冰冰颁奖-。(内场图via@吴尊家的宝)新浪电影的...
明星那些事儿 : #白百合颁奖#
北京晨报 : #第八届导演协会年度盛典#范冰冰凭借《我不是潘金莲》获得2017导演协会年度盛典最佳女演员奖,再得影后!白-百何-作为颁奖-嘉宾上台为冰冰颁奖-。白-百何-现场穿的非常低调。
信息缺失
吐槽污 : 2017年4月22日,第八届中国电影导演协会年度盛典举行,刚经历了出轨风波的白-百何-在颁奖-环节登台亮相,为范冰冰颁发年度女演员奖项。P.S.范冰冰:第一次被别人抢了风头
娱乐圈avi : #白百何颁奖-#导演协会年度表彰盛典@范冰冰凭借《我不是潘金莲》获最佳女演员,白百何登场为其颁奖。恭喜范冰冰再拿影后!
方晓东 : 范冰冰凭借《我不是潘金莲》获得2017导演协会年度盛典最佳女演员奖!#白百何颁奖-#,现场穿着非常低调。这个颁奖人你服不服!秒拍视频
信息缺失
直播新合肥 : #白百何颁奖-#恭喜范冰冰凭借《我不是潘金莲》获得2017导演协会年度盛典最佳女演员奖,演技棒!当之无愧影后!最近舆论不断的白百何作为颁奖嘉宾。又一次上了头条。
就是不吃饭呢 : 【白百何颁奖-前片场照曝光还在剧组智斗小朋友】白百何在“出轨门”后,便“销声匿迹”,除了一封迟来的声明,大众便再没见到她的身影。22日,白百何意外现身某盛典,终于再度现身。其实,此前也有博主曝光过白百何近照,这天她一身商务范look,举手投足间满满的白骨精画风
g王传民 : 哈哈哈大家好
sherry向斯瑞 : 今天一看微博又是关于白-百何-的,说什么白-百何-出轨后颁奖-我想问,人家怎么出轨了。陈羽凡和白百何两年前就离婚了,只是没有公布,在这期间人家不可以有新欢吗?真的是奇了怪了,离了婚找新欢还算出轨了不成,真的是太没有道理了。这真心不叫出轨好嘛,关于陈羽凡,两个人之间没有了感情离婚了也的确让人...展开全文c
信息缺失
申请个人微博加V-互粉橙V服务 : 有时候,一个人生气是因为他认为你拒绝的不仅仅是他的建议,而是你根本瞧不起他这个人。所以,在白百何颁奖-拒绝某个人建议的时候,要简单地陈述两个你赞成李宏毅的原因,然后再陈述你为什么要按自己skt的方式来做。如果可能,征询地球护卫队对其他一些事情的意见,让他明白,你其实是非常尊重他的。
首都在线 : #白百何颁奖-#在#第八届导演协会年度盛典#上,#白百何#给范冰冰颁奖。@中国电影导演协会
护肤达人__David : #白百何颁奖-#看到说出轨门的白百何我是有点不大理解的,陈羽凡和白百何不是已经发表声明说是已经离婚了吗?那么白百何就不能找男人了?何来的出轨?还有白百何给范冰冰颁奖这不是对白百何演技的肯定吗?不说白百何演的怎么怎么好,我觉得最起码看的过去
...
有些错误的地方有时间再查看下,现在先直接异常处理跳过,打印 "信息缺失"
发现了个问题,在 20 条热搜后,查不到对应的内容了
用浏览器打开热搜看下,原来是被新浪封ip了
奇怪,都设置 1.5 秒 延时了
那就只能设置更久或用selenium了,或者再看看有别的方法不
暂时先这样子,得先破解了验证码再继续完善别的功能了