目的
由于工作需要,尝试爬取雪球7*24小时信息。
需要的数据就是下图红框框起来的部分。
运行环境
操作系统:windows 10
浏览器:Chrome
Python版本:3.8
使用的第三方库:requests
、json
、time
查看数据
我们需要知道目标数据是一次性加载全部,还是动态地从某个特定的接口不断的获取数据,所以我们需要先在浏览器上查看一些数据。
将页面往下翻一段之后,发现网页内容是动态加载的,往下翻一段加载一段。继续往下翻,发现网页停住了,出现了一个加载更多的按钮。点一次按钮就会加载一部分数据
至此,我们可以确定目标数据是动态加载的,那么我们下一步就是得到数据接口。
抓包获取数据接口
抓包(packet capture)就是将网络传输发送与接收的数据包进行截获、重发、编辑、转存等操作,也用来检查网络安全 。
我们打开浏览器的检查模式(通常在网页点击右键就会出现),选中网络或network。可以看到我们当前捕获了部分数据。
点开捕获的数据包,里面会有一些请求数据。其中非常重要的就是URL和请求方式,在我们后续编写爬虫程序时需要使用到这些信息。可以尝试直接打开URL,查看返回的是什么数据。
我们刷新整个网页,让数据重新加载,捕获所有的数据包。切记,刷新网页前进入检查模式,并切换到Network页面。
可以看到返回了非常多的数据包,网页正是由这些数据包构成的,接下来我们的任务就是从这些数据包中选出我们需要的那个数据包。
首先我们可以排除掉一些数据包。
- 第一个数据包,通常第一个数据包请求的网址就是我们现在打开的网站的网址。
- 以
.js
、.css
结尾的数据包,这类数据包请求的是加载页面需要的代码。 - 以
.png
结尾的数据包,这类数据包请求的是网站上显示的图片。
剩下的数据包,我们依次打开,查看其内容。有些数据包的网站打开后有大段的文字,与我们需要的数据非常相似,但又无法确定,这时我们可以复制一段我们需要的数据中的文字,在打开的网站中搜索(Ctrl + F),如果没有就肯定不是啦。
最终确定了我们需要的网址(https://xueqiu.com/statuses/livenews/list.json?since_id=-1&max_id=-1&count=10)
尝试抓取一条数据
获取了数据接口的网址,那么我们就可以开始写代码获取数据啦。这里使用Python
中的requests
库来获取数据。
import requests
# 需要请求的网址
url = 'https://xueqiu.com/statuses/livenews/list.json?since_id=-1&max_id=-1&count=10'
# 伪装成浏览器
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36 Edg/91.0.864.41'}
# 获取并输出数据
# 请求方式与浏览器保持一致,使用get
res = requests.get(url=url, headers=headers)
print(res.text)
# 输出
# {"error_description":"遇到错误,请刷新页面或者重新登录帐号后再试","error_uri":"/statuses/livenews/list.json","error_data":null,"error_code":"400016"}
返回的数据显示发生了错误,并且提示我们请登录后再试。但是浏览器明明可以加载数据的,说明服务器通过某种手段记住了我们的登录状态等信息,并通过这种手段识别出了爬虫程序。这种手段通常就是Cookie
,在此处就不过多的介绍了。我们可以从刚刚获取的数据包中得到我们自己的Cookie
信息,在刚刚获取网址的下方就有Cookie
的信息。
那么在给代码加上Cookie
再试一次。
import requests
# 需要请求的网址
url = 'https://xueqiu.com/statuses/livenews/list.json?since_id=-1&max_id=-1&count=10'
# 伪装成浏览器
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36 Edg/91.0.864.41',
'Cookie': '你的Cookie信息',
}
# 获取并输出数据
res = requests.get(url=url, headers=headers)
print(res.text)
# 输出
# {"next_max_id":1964760,"items":[{"id":1964777,"text":"【中信证券:二季度盈利确定性强,持续推荐能源金属、高端制造、铜铝板块配置机会】 中信证券指出,周期板块风云再起...
返回的数据为json
格式,可以用json.loads()
解析数据。
t = res.text
d = json.loads(t)
print(d.keys())
# 输出
# dict_keys(['next_max_id', 'items', 'next_id'])
解析后为一字典,共有三项,其中我们需要的数据存储在items
中。
获取更多数据
为了获取更多数据,我们需要解析上面获取的网址中的参数含义。
往下翻网页,让浏览器加载更多的数据,查看新的数据包的网址和返回数据的变化。
网址:https://xueqiu.com/statuses/livenews/list.json?since_id=-1&max_id=-1&count=10
数据:{"next_max_id":1964848,"items":[...
网址:https://xueqiu.com/statuses/livenews/list.json?since_id=-1&max_id=1964848&count=15
数据:{"next_max_id":1964829,"items":[...
网址:https://xueqiu.com/statuses/livenews/list.json?since_id=-1&max_id=1964829&count=15
数据:{"next_max_id":1964803,"items":[...
网址:https://xueqiu.com/statuses/livenews/list.json?since_id=-1&max_id=1964803&count=15
数据:{"next_max_id":1964786,"items":[...
我们可以发现,网址主要的变化在max_id
这个数值上,除了第一次获取的数值为-1
,后续的网址的max_id
为前一数据的next_max_id
都数值。有了这个信息,我们就可以自动的构造网址,循环上面抓取一条数据的内容,就可以获取更多的数据了。
next_id = d['next_max_id']
url = f'https://xueqiu.com/statuses/livenews/list.json?since_id=-1&max_id={next_id}&count=15'
代码获取
本文完整代码可关注公众号<卡卡写代码>,回复<雪球爬虫>获取
本文首发于微信公众号<卡卡写代码>,欢迎关注