这里的微博爬虫,我主要实现的是输入你关心的某个大 V 的微博名称,以及某条微博的相关内容片段,即可自动爬取相关该大 V 一段时间内发布的微博信息和对应微博的评论信息。
Cookie 获取与上面的 Boss 直聘网站类似,爬取微博也需要获取响应的 cookie。
用浏览器打开微博页面,拷贝出对应的 Cookie,保存到本地。
微博搜索
既然是某位大 V,这里就肯定涉及到了搜索的事情,我们可以先来尝试下微博自带的搜索,地址如下:
s.weibo.com/user?q=林志玲
同样是先放到 Postman 里请求下,看看能不能直接访问: 是可以的,这就省去了我们很多的麻烦。下面就是来分析并解析响应消息,拿到对我们有用的数据。 经过观察可知,这个接口返回的数据中,有一个 UID 信息,是每个微博用户的唯一 ID,我们可以拿过来留作后面使用。
至于要如何定位到这个 UID,我也已经在图中做了标注,相信你只要简单分析下就能明白。
'''
更多Python学习资料以及源码教程资料,可以在群1136201545免费获取
'''
def get_uid(name):
try:
url = 'https://s.weibo.com/user?q=%s' % name
res = requests.get(url).text
content = BeautifulSoup(res, 'html.parser')
user = content.find('div', attrs={'class': 'card card-user-b s-pg16 s-brt1'})
user_info = user.find('div', attrs={'class': 'info'}).find('div')
href_list = user_info.find_all('a')
if len(href_list) == 3:
title = href_list[1].get('title')
if title == '微博个人认证':
uid = href_list[2].get('uid')
return uid
elif title == '微博会员':
uid = href_list[2].get('uid')
return uid
else:
print("There are something wrong")
return False
except:
raise
还是通过 BeautifulSoup 来定位获取元素,最后返回 UID 信息。
M 站的利用
M 站一般是指手机网页端的页面,也就是为了适配 mobile 移动端而制作的页面。一般的网站都是在原网址前面加“m.”来作为自己 M 站的地址,比如:m.baidu.com 就是百度的 M 站。 我们来打开微博的 M 站,再进入到林志玲的微博页面看看 Network 中的请求,有没有什么惊喜呢? 我们首先发现了这样一个 URL:
https://m.weibo.cn/api/container/getIndex?uid=1312412824&luicode=10000011&lfid=100103type%3D1%26q%3D%E6%9E%97%E5%BF%97%E7%8E%B2&containerid=1005051312412824
接着继续拖动网页,发现 Network 中又有类似的 URL:
https://m.weibo.cn/api/container/getIndex?uid=1312412824&luicode=10000011&lfid=100103type%3D1%26q%3D%E6%9E%97%E5%BF%97%E7%8E%B2&containerid=1076031312412824
URL 类似,但是第一个返回的数据是用户信息,而第二个返回的则是用户的微博信息,显然第二个 URL 是我们需要的。同样道理,把第二个 URL 放到 Postman 中,看看哪些参数是可以省略的。 最后我们发现,只要传入正确的 containerid 信息,就能够返回对应的微博信息,可是 containerid 信息又从哪里来呢?我们刚刚获得了一个 UID 信息,现在来尝试下能不能通过这个 UID 来获取到 containerid 信息。 这里就又需要一些经验了,我可以不停的尝试给接口“m.weibo.cn/api/container/getIndex”添加不同的参数,看看它会返回些什么信息,比如常见的参数名称 type、id、value、name 等。最终,在我不懈的努力下,发现 type 和 value 的组合是成功的,可以拿到对应的 containerid 信息。
这个地方真的不有任何捷径了,只能靠尝试和经验。 现在就可以编写代码,获取对应的 containerid 了(如果你细心的话,还可以看到这个接口还返回了很多有意思的信息,可以自己尝试着抓取)。
def get_userinfo(uid):
try:
url = 'https://m.weibo.cn/api/container/getIndex?type=uid&value=%s' % uid
res = requests.get(url).json()
containerid = res['data']['tabsInfo']['tabs'][1]['containerid']
mblog_counts = res['data']['userInfo']['statuses_count']
followers_count = res['data']['userInfo']['followers_count']
userinfo = {
"containerid": containerid,
"mblog_counts": mblog_counts,
"followers_count": followers_count
}
return userinfo
except:
raise
代码里都是基本操作,不过多解释了。 拿到 containerid 信息之后,我们就可以使用上面第二个 URL 来获取微博信息了,这里还是同样的问题——分页。怎么处理分页呢,继续改造这个 getIndex 接口,继续尝试传递不同的参数给它。 这次给它传递 containerid 和 page 信息,就可以完成分页请求了。 传递的 page 为 3 时,其实是获取当前新浪微博的第 4 页数据,后面我们就可以用这个 URL 来获取微博信息了。 该接口返回的是 JSON 数据,解析起来就比较方便了。 微博信息就保存在 res[‘data’][‘cards’] 下面,有评论、转发、点赞数量等信息。于是我们解析该 JSON 数据的函数就有了:
def get_blog_info(cards, i, name, page):
blog_dict = {}
if cards[i]['card_type'] == 9:
scheme = cards[i]['scheme'] # 微博地址
mblog = cards[i]['mblog']
mblog_text = mblog['text']
create_time = mblog['created_at']
mblog_id = mblog['id']
reposts_count = mblog['reposts_count'] # 转发数量
comments_count = mblog['comments_count'] # 评论数量
attitudes_count = mblog['attitudes_count'] # 点赞数量
with open(name, 'a', encoding='utf-8') as f:
f.write("----第" + str(page) + "页,第" + str(i + 1) + "条微博----" + "\n")
f.write("微博地址:" + str(scheme) + "\n" + "发布时间:" + str(create_time) + "\n"
+ "微博内容:" + mblog_text + "\n" + "点赞数:" + str(attitudes_count) + "\n"
+ "评论数:" + str(comments_count) + "\n" + "转发数:" + str(reposts_count) + "\n")
blog_dict['mblog_id'] = mblog_id
blog_dict['mblog_text'] = mblog_text
blog_dict['create_time'] = create_time
return blog_dict
else:
print("没有任何微博哦")
return False
函数参数:
- 第一个参数,接受的值为 res[‘data’][‘cards’] 的返回值,是一个字典类型数据;
- 第二个参数,是外层调用函数的循环计数器;
- 第三个参数,是要爬取的大 V 名称;
- 第四个参数,是正在爬取的页码。
最后函数返回一个字典。
搜索微博信息我们还要实现通过微博的一些字段,来定位到某个微博,从而抓取该微博下的评论的功能。 再定义一个函数,调用上面的 get_blog_info 函数,从其返回的字典中拿到对应的微博信息,再和需要比对的我们输入的微博字段做比较,如果包含,那么就说明找到我们要的微博啦。
def get_blog_by_text(containerid, blog_text, name):
blog_list = []
page = 1
while True:
try:
url = 'https://m.weibo.cn/api/container/getIndex?containerid=%s&page=%s' % (containerid, page)
res_code = requests.get(url).status_code
if res_code == 418:
print("访问太频繁,过会再试试吧")
return False
res = requests.get(url).json()
cards = res['data']['cards']
if len(cards) > 0:
for i in range(len(cards)):
print("-----正在爬取第" + str(page) + "页,第" + str(i+1) + "条微博------")
blog_dict = get_blog_info(cards, i, name, page)
blog_list.append(blog_dict)
if blog_list is False:
break
mblog_text = blog_dict['mblog_text']
create_time = blog_dict['create_time']
if blog_text in mblog_text:
print("找到相关微博")
return blog_dict['mblog_id']
elif checkTime(create_time, config.day) is False:
print("没有找到相关微博")
return blog_list
page += 1
time.sleep(config.sleep_time)
else:
print("没有任何微博哦")
break
except:
pass
这里调用了一个工具函数 checkTime 和一个配置文件 config。 checkTime 函数定义如下:
def checkTime(inputtime, day):
try:
intime = datetime.datetime.strptime("2019-" + inputtime, '%Y-%m-%d')
except:
return "时间转换失败"
now = datetime.datetime.now()
n_days = now - intime
days = n_days.days
if days
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?