文章首发自个人公众号【poython3xxx】。未经受权,禁止转载。html
做为一名十好青年,微博也关注了许多互联网&科技类的博主。本着学习的心态平常刷着微博。忽然看到一条微博。node
点开评论,瞬间惊呆了。python
下图可能引发不适,未成年人,请在家长的陪同下观看。git
评论1.5W条,一页一页的去翻,身为程序员这显然不是咱们的风格。本着学习为主的心态,我决定把他们都保存在个人硬盘里!!!程序员
俗话说,能爬移动端就不要爬PC端,可是在操做手机抓包爬的过程当中,遇到了不少坑。一时没有解决。因而转移阵地到PC端微博。github
F12打开开发者工具,刷新页面。看到有这样一条Get请求 weibo.com/aj/v6/comment/big,当咱们点击加载更多时,又会从新发送一次这样的请求。json
请求参数以下: 微信
响应为一个json串,微博的内容以html的形式返回。 cookie
通过对比发现,请求参数 ajwvr为定值6;id为该微博动态的ID,也能够理解为定值;from的值也为定值,_rnd 参数无关紧要并不会影响最终的结果。ide
一开始 root_comment_max_id这个参数让我比较疑惑,第一次请求中并无这个参数,后面的请求中都必需要传这个参数,不然会影响最后的响应结果。 根据字面意思,大概是父级内容的id,因而我把上一次请求的html数据复制到VSCode,直接Ctrl+F 全局搜索root_comment_max_id。果真不出所料。
至此,每一个参数的含义,基本都清楚了。必传参数总结以下:
ajwvr :定值6,必传。
id : 该条微博动态的id。
from : 定值 singleWeiBo
root_comment_max_id:在上一个请求响应的html中提供。也有提供分页的做用
分析相应的html,经过xpath提取出咱们想要的字段。
也许你们只对最终的结果感兴趣,那我就不具体讲了。只展现一下关键的代码。
微博爬虫中,作了必定的反爬措施。
同一IP不能访问频繁。
请求头中须要携带Cookie
headers = {
'Cookie': '你的cookie',
}
# 参数信息
params = {
'ajwvr': 6,
'id': '4367970740108457',
'from': 'singleWeiBo',
'root_comment_max_id':''
}
# 访问url
URL = 'https://weibo.com/aj/v6/comment/big'
resp = requests.get(URL, params=params, headers=headers)
resp = json.loads(resp.text)
if resp['code'] == '100000':
html = resp['data']['html']
print(html)
from lxml import etree
html = etree.HTML(html)
# 获取该页面的root_comment_max_id ,为下一次请求提供参数
max_id_json = html.xpath('//div[@node-type="comment_loading"]/@action-data')[0]
node_params = parse_qs(max_id_json)
# max_id
max_id = node_params['root_comment_max_id'][0]
params['root_comment_max_id'] = max_id
# data = html.xpath('//div[@class="list_ul"]/div[@node-type="root_comment"]/div[@class="list_con"]')
# 获取每一条动态的节点信息
data = html.xpath('//div[@node-type="root_comment"]')
# 遍历每一条东岱
for i in data:
# 评论人昵称
nick_name = i.xpath('.//div[@class="WB_text"]/a/text()')[0]
# 评论内容。
wb_text = i.xpath('.//div[@class="WB_text"][1]/text()')
# 简单的清洗,出去空格和换行符
string = ''.join(wb_text).strip().replace('\n', '')
# 封装了一个方法,将留言信息写入文本
write_comment(string)
# 评论id , 用于获取评论内容
comment_id = i.xpath('./@comment_id')[0]
# 评论的图片地址
pic_url = i.xpath('.//li[@class="WB_pic S_bg2 bigcursor"]/img/@src')
pic_url = 'https:' + pic_url[0] if pic_url else ''
# 封装的下载图片方法
download_pic(pic_url, nick_name)
复制代码
以上是获取评论信息,可是每条评论下还有不少别的小姐姐的评论(胸照),这咱们确定不能放过。
点击相似放上的按钮,发现依旧有个请求,地址与上面提到的地址同样。区别在于参数的不一样。具体你们能够实际操做一下。
经过分析子评论的图的获取方式有所不一样,他是经过get请求 weibo.com/aj/photo/popview, 参数可有从子评论响应的html获取。下图标注部分。
经过请求构造出的url,会返回一个一个图片列表,第一个就是咱们须要的图。
获取子评论方法,代码中只获取了第一页的子评论,由于后面大部分是水文,感兴趣的同窗能够去试试,方法跟获取父级留言同样,须要的参数在源码中均可以找到。
def get_child_comment(root_comment_id):
comment_params['root_comment_id'] = root_comment_id
resp = requests.get(URL, params=comment_params, headers=headers)
resp = json.loads(resp.text)
if resp['code'] == '100000':
html = resp['data']['html']
print(html)
from lxml import etree
html = etree.HTML(html)
# 每一个子评论的节点
data = html.xpath('//div[@class="WB_text"]')
for i in data:
nick_name = ''.join(i.xpath('./a/text()')).strip().replace('\n', '')
comment = ''.join(i.xpath('./text()')).strip().replace('\n', '')
write_comment(comment)
# 获取图片对应的html节点
pic = i.xpath('.//a[@action-type="widget_photoview"]/@action-data')
pic = pic[0] if pic else ''
if pic:
# 拼接另外两个必要参数
pic = pic + 'ajwvr=6&uid=5648894345'
# 构造出一个完整的图片url
url = 'https://weibo.com/aj/photo/popview?' + pic
resp = requests.get(url, headers=headers)
resp = resp.json()
if resp.get('code') == '100000':
# 从忽然url中,第一个就是评论中的图
url = resp['data']['pic_list'][0]['clear_picSrc']
# 下载图片
download_pic(pic_url, nick_name)
复制代码
好了,知道你们已经火烧眉毛的想看结果了。部分截图以下。
也能够经过PIL模块生成照片墙。
微博里,你们都在说什么?能够经过词云的方式进行展现
今天下班已经十点了,路上刷微博,忽然想尝试爬一下微博评论,时间仓促,代码可能不够严谨。因此各位看官多担待,完整源码。已上传github。 地址:github.com/python3xxx/…
最后欢迎你们关注个人公众号,微信搜索【python3xxx】。天天都会有不同的Python干货。