根据关键词抓取新浪微博 一、背景
很多人可能遇到过想通过某些关键词获取新浪微博数据的情况。 目前有两种方式。
使用官方api
官方API的优点是使用起来简单方便。 但是有两个问题。
这里还是一个api地址,参数和例子,token可以换成自己的,以下代码仅供参考
import requestsurl = 'https://api.weibo.com/2/search/topics.json'"""access_token true string 采用OAuth授权方式为必填参数,OAuth授权后获得。q true string 搜索的话题关键字,必须进行URLencode,utf8编码。count false int 单页返回的记录条数,默认为10,最大为50。page false int 返回结果的页码,默认为1。"""load = { 'access_token': '2.00AqpTsHXXXXXXXXXXXXXXXXXXXXX', 'q': '新冠', 'count': 50, 'page': 2}html = requests.get(url, params=load)print(html.json())
通过网络抓取
这种方法是我们文章的重点。 优点是不需要获取token,其次获取的数据量比较大。 但是缺点也很明显获取微博评论,就是比较麻烦。 本文也会详细分析每个步骤,让爬取变得简单。
2.分析目标网站
分析目标网站,输入关键字搜索后,可以在搜索栏右侧看到高级搜索选项,如下图
微博高级搜索
我们先不设置参数,调出f12看看搜索过程中可能会产生哪些请求(如下图)。
这就是我们需要的数据。 很明显这是一个get请求,里面包含了几个参数,我们可以先猜测一下这些参数的含义。
很容易看出“q”一定代表你需要查找的字段。 “”、“”、“Refer”具体代表什么不清楚,不过没关系,我们可以通过更改参数重新请求获取更多信息。
f12分析
我们更改参数,空间范围设置为北京,时间范围设置为20200501 0:0020200502 23:00同时翻到第8页。 再次请求我们可以得到下图中的数据。
可以看到肯定代表了空间范围,如下:11:1000代表北京。 它代表时间范围, :202005010:20200502:23 代表我们设置的时间范围。 page 必须是页码。 其余三个参数不影响我们整体的结果(可能是设置抓取类型,读者可以自行尝试),暂时先不管。
至此我们分析了整个请求的参数表示的含义。 接下来,我们可以考虑如何从页面中提取我们需要的信息。
3. 页面分析与代码编写 3.1 爬取前的准备 3.2 元素定位
通过查看原文我们可以定位到每条微博所在的位置,找出该元素唯一定位的标签。
我们发现每条微博都有一个标签。 找到所有标签我们可以找到每个微博。 然后根据自己的需要找到自己需要的资料。
本文以搜索微博文字、用户、创建时间为例。
3.3 代码示例
下面开始编写相关代码。 第一种是发送请求以获取相关的 HTML 文本。 我们需要的是:
这是一个简单的例子
import requestsfrom bs4 import BeautifulSoup# 请求的网址url = "https://s.weibo.com/weibo"# 请求头的文本,可以直接从网页中复制h = """Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signedexchange;v=b3;q=0.9AcceptEncoding: gzip, deflate, brAcceptLanguage: zh,enUS;q=0.9,en;q=0.8,zhCN;q=0.7Connection: keepaliveCookie: XXXX(填自己的cookie)Host: s.weibo.comReferer: https://s.weibo.com/weibo/%25E7%258C%25AA%25E7%2598%259F?topnav=1&wvr=6&b=1SecFetchDest: documentSecFetchMode: navigateSecFetchSite: sameoriginSecFetchUser: ?1UpgradeInsecureRequests: 1UserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Safari/537.36"""# 将复制得到的str处理成标准的字典格式def handle_header(s): dic = {} li = s.split('\n') for l in li: dic[l.split(': ')[0]] = l.split(': ')[1] return dic # 处理请求def handle(page, year, month, day, hour): #请求的参数,页面和时间等 load = { 'q': '郭涛道歉', 'typeall': '1', 'suball': '1', 'timescope': f'custom:{year}{month}{day}{hour}:{year}{month}{day}{hour + 1}', 'Refer': 'g', 'page': page } # 发送请求 j = requests.get(url, headers=handle_header(h), params=load, timeout=(10, 10)) return j.text
这里可以通过函数获取html。 然后获取相关信息。相关代码如下
# 转换成soup的对象soup = BeautifulSoup(handle(1, 2020, 05, 01, 00), 'lxml')# 使用find_all获取这页所有weibo的信息, {'class': 'cardwrap'} 定位微博内容信息contents = soup.find_all('div', {'class': 'cardwrap'})
最后就是提取每条微博中有用的信息
def filter_info(content, _date, _mid): """ 过滤无效信息 :param content: :param _date: :param _mid: :return: """ # 这里传入的content是一个微博包含的所有信息,也就是一个 {'class': 'cardwrap'} 的定位信息 _content = content.find('div', {'class': 'content'}) # 获取用户名 nick_name = _content.find('p')['nickname'] # 获取微博文本 blog = _content.find_all('p', {'class': 'txt'})[1].text.replace('郭涛道歉', '郭涛道歉').strip().replace('\n', '\\n') # 获取时间 create = _content.find_all('p', {'class': 'from'})[1].a.text.strip().replace('\n', '\\n') date_str = "".join(_date) data = {'mid': _mid, 'nick_name': nick_name, 'create': create, 'blog': blog, 'date_str': date_str} # 返回json格式的数据 return data
至此获取微博评论,整个流程就完成了,返回的数据就是本页面的微博信息。
剩下的就是组合上述代码并添加您自己的逻辑,例如设置数据库和获取更多信息。
完整参考代码请回复微博爬虫。