目标
#.5.22
#author:pmy
#目标:爬取最爱的绵羊的微博,包含时间,文本内容,点赞数,评论数与转发数
#在更换博主时主要在于修改headers中的referer和参数中的containerid
分析
首先要简单讲一下Ajax。它是利用JavaScript在保证页面不被刷新、页面链接不改变的情况下与服务器交换数据并更新部分网页的技术。
它具体体现在:
在刷微博时,我们能明显能发现,当一个页面划完,就能出现新的画面,新的内容,而此时,网页并没有刷新。
Ajax在网页中的请求类型是xhr,在其中便可以找到每次往下划获得的信息。它响应的内容是JSON格式,很方便操作,可以说是十分方便了。
具体的在我们要抓取的网页中怎么看xhr,怎么获得JSON响应呢。下面我们就来看。
我们这里爬取的是我最近最喜欢的b站up主绵羊料理的新浪微博,最喜欢大姨了嘿嘿。
我们从微博手机端网页版进入,要爬取的网页地址为:/profile/1733152694
往下划,查看网络:
发现没有之前那种适合我们爬取的html文档,那么将筛选器选择XHR呢。
发现如上图所示,便能够看到我们需要抓取的微博信息来自XHR类型的getlndex?containerid···中便是JSON格式,其中就有我们需要的信息。
那么ok,我们确认要抓取的就是这个getlndex?containerid···了。查看其请求头参数,发现几个重要的参数。
请求URL:/api/container/getIndex?containerid=2304131733152694_-_WEIBO_SECOND_PROFILE_WEIBO
referer:/p/2304131733152694_-_WEIBO_SECOND_PROFILE_WEIBO
X-Requested-With:XMLHttpRequest
page:2
重要的参数就是这么多,page参数用来换页,虽说没有分页,只要往下划就能看到新内容,但新内容其实也是新的一页,本质上没有变化。
而请求的URL可以看出,我们其实是通过新浪微博的api获得的数据。
referer和containerid明显是来确定确定所有微博属于哪个用户的。如果要爬取别的用户,可以修改这两个参数,便可以方便的爬取。
然后得到了JSON格式数据之后,我们打开任意一个文件,可以看到其中数据如下图所示。
我们需要找到文本,时间,点赞量等等。简单的浏览可以发现,我们需要的数据的结构如下:
data
cards
mblog
0
1
···
text:"xxx"
created_at:"xxx"
attitudes_count:xxx
comments_count:xxx
reposts_count:xxx
···
2
3
4
···
那么提取就很简单了(其中有的没有mblog,所以需要用if判断一下)
代码实现如下:
def parse_json(data):
if data:
items = data.get('data').get('cards')
for item in items:
item = item.get('mblog')
#有的card没有mblog
if(item):
weibo = {}
#抓取信息
weibo['date'] = pq(item.get('created_at')).text()#日期
weibo['text'] = pq(item.get('text')).text()#文本
weibo['attitudes'] = item.get('attitudes_count')#点赞次数
weibo['comments'] = item.get('comments_count')#评论次数
weibo['reposts'] = item.get('reposts_count')#转发次数
# 一个一个返回weibo
yield weibo
完整代码
#.5.22
#author:pmy
#目标:爬取最爱的绵羊的微博,包含时间,文本内容,点赞数,评论数与转发数
#在更换博主时主要在于修改headers中的referer和参数中的containerid
from urllib.parse import urlencode
import requests
import json
import time
from pyquery import PyQuery as pq
base_url = '/api/container/getIndex?'
#host用于指定internet主机和端口号,http1.1必须包含,不然系统返回400,
headers = {
'Referer':'/p/2304131733152694_-_WEIBO_SECOND_PROFILE_WEIBO',
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36 Edg/80.0.361.111',
'Host':'',
'X-Requested-With':'XMLHttpRequest'
}
#获取网页的json
def get_page(page):
para={
'containerid':'2304131733152694_-_WEIBO_SECOND_PROFILE_WEIBO',
'page':page
}
url = base_url+urlencode(para)
try:
response = requests.get(url, headers=headers)
if response.status_code == 200:
return response.json()
except requests.ConnectionError as e:
print("Error:",e.args)
#分析JSON格式的数据,抓取目标信息
def parse_json(data):
if data:
items = data.get('data').get('cards')
for item in items:
item = item.get('mblog')
#有的card没有mblog
if(item):
weibo = {}
#抓取信息
weibo['date'] = pq(item.get('created_at')).text()#日期
weibo['text'] = pq(item.get('text')).text()#文本
weibo['attitudes'] = item.get('attitudes_count')#点赞次数
weibo['comments'] = item.get('comments_count')#评论次数
weibo['reposts'] = item.get('reposts_count')#转发次数
# 一个一个返回weibo
yield weibo
#存储到txt文件中
def save_data(data,count):
filename = 'result'+str(count)+'.txt'
with open(filename, 'a', encoding='utf-8') as f:
f.write(json.dumps(data, ensure_ascii=False) + '\n')
f.close()
if __name__ =='__main__':
for page in range(1, 10):
data = get_page(page)
results = parse_json(data)
for result in results:
save_data(result,page)
print('第'+str(page)+'页抓取完成')
time.sleep(0.5)
结果