明确采集的网站及数据内容
分析爬虫思路,概括如下:
from DrissionPage import ChromiumPage
from DataRecorder import Recorder
import pandas as pd
from tqdm import tqdm
import time
import random
import re
import openpyxl
import os
import math
def countdown(n):
for i in range(n, 0, -1):
print(f'\r倒计时{i}秒', end='') # \r让光标回到行首 ,end=''--结束符为空,即不换行
time.sleep(1) # 让程序等待1秒
else:
print('\r倒计时结束')
使用 DrissionPage 库,打开小红书主页https://www.xiaohongshu.com,设置 30 秒延时,这时可以使用手机扫码登录账号。在登录的函数里调用倒计时函数。
def sign_in():
sign_in_page = ChromiumPage()
sign_in_page.get('https://www.xiaohongshu.com')
# 第一次运行需要扫码登录
print("请扫码登录")
# 倒计时30s
countdown(30)
只有第 1 次运行代码需要登录,浏览器会保存登录状态信息。第 2 次之后再运行代码,就免登录了,可以把 sign_in()步骤注释掉。
与登录小红书方法一样,只是要把打开的网址改为作者主页链接
在这里使用DrissionPage 库的定位元素方法,定位提取作者名字,方便后续写入excel文件和给excel文件命名。
def open(url):
global page, author
page = ChromiumPage()
page.get(f'{url}')
# 页面最大化
page.set.window.max()
# 定位作者信息
user = page.ele('.info')
# 作者名字
author = user.ele('.user-name', timeout=0).text
使用DrissionPage库定位元素方法,定位到包含笔记信息的sections,定位标题,点赞,笔记链接信息。
def get_info():
# notes列表存放当前页面的笔记
notes = []
# 定位包含笔记信息的sections
container = page.ele('.feeds-container')
sections = container.eles('.note-item')
for section in sections:
# 笔记类型
if section.ele('.play-icon', timeout=0):
note_type = "视频"
else:
note_type = "图文"
# 文章链接
note_link = section.ele('tag:a', timeout=0).link
# 标题
footer= section.ele(".footer")
title = footer.ele('.title', timeout=0).text
# 作者
author_wrapper = footer.ele('.author-wrapper')
# 点赞
like = author_wrapper.ele('.count').text
notes.append([note_type,like])
# 写入数据,r为全局变量
r.add_data(notes)
为了防止被检测到,每次下滑页面设置一个1秒至2秒之前的随机睡眠时间。使用DrissionPage库scroll.to_bottom()操作页面方法,将页面滑到底部,小红书会刷新出新的数据
def page_scroll_down():
print(f"********下滑页面********")
page.scroll.to_bottom()
# 生成一个1-2秒随机时间
random_time = random.uniform(1, 2)
# 暂停
time.sleep(random_time)
在crawler(times)函数中,调用get_info()函数自动提取页面数据,调用page_scroll_down()函数自动下滑页面,程序会跟踪笔记总数,计算出向下滑动页面次数,可以自动刷新数据,提取数据。
def crawler(times):
global i
for i in tqdm(range(1, times + 1)):
get_info()
page_scroll_down()
计算向下滑动页面次数的方法如下
#note_num是笔记数量
note_num=630
#times是计算得到的翻页次数,笔记数量除以20,调整系数,再向上取整
times= math.ceil(note_num/20*1.1)
printf(f"需要执行翻页次数为: {times}")
继续使用DataReCorder库来记录数据到文件,这个库使用方便,代码简洁,用起来很可靠,省心,非常适合爬虫使用
# 获取当前时间
current_time = time.localtime()
# 格式化当前时间
formatted_time = time.strftime("%Y-%m-%d %H%M%S", current_time)
# 初始化文件
init_file_path = f'小红书作者主页所有笔记-{formatted_time}.xlsx'
r = Recorder(path=init_file_path, cache_size=100)
#记录数据到缓存
r.add_data(notes)
定义一个re_save_excel()函数,负责处理excel表格数据去重,排序,计算总数,再将总数信息加到文件命中。
使用pandas库,读取初始化的excel文件,对笔记数据去重处理,然后根据笔记的点赞数降序排列。再加上作者名和笔记数量,给excel重新命名
最后,再给excel表重新调整表格列宽,方便查看数据。
def re_save_excel(file_path):
# 读取excel文件
df = pd.read_excel(file_path)
print(f"总计向下翻页{times}次,获取{df.shape[0]}条笔记(含重复获取)。")
# 将点赞数转换为整数
df['点赞数'] = df['点赞数'].apply(convert_likes).astype(int)
# 删除重复行
df = df.drop_duplicates()
# 按点赞 降序排序
df = df.sort_values(by='点赞数', ascending=False)
# 文件路径
final_file_path = f"小红书作者主页所有笔记-{author}-{df.shape[0]}条.xlsx"
df.to_excel(final_file_path, index=False)
print(f"总计向下翻页{times}次,笔记去重后剩余{df.shape[0]}条,保存到文件:{final_file_path}。")
print(f"数据已保存到:{final_file_path}")
同时为了更好处理点赞数带有“万”的数据,因此需要对点赞数进行转换。
# 定义转换点赞数的函数
def convert_likes(likes):
# 移除'+'字符
likes = likes.replace('+', '')
# 检查是否包含'万'或'千'单位,并进行相应的转换
if '万' in likes:
return int(likes.replace('万', '')) * 10000
elif '千' in likes:
return int(likes.replace('千', '')) * 1000
else:
return int(likes)
由于已经得到一个最终的excel文件,这个文件是去重,排序的,最终效过很方便查看,因此可以删除初始的excel文件
def delete_file(file_path):
# 检查文件是否存在
if os.path.exists(file_path):
# 删除文件
os.remove(file_path)
print(f"已删除初始化excel文件:{file_path}")
else:
print(f"文件不存在:{file_path} ")
最后通过指定author_url和note_num就可以爬取指定作者的笔记了。
# 1、第1次运行需要登录,需要执行sign_in()步骤。第2次之后不用登录,可以注释掉sign_in()步骤。
# sign_in()
# 2、设置主页地址url
author_url = "https://www.xiaohongshu.com/user/profile/64c38af4000000000e026b43"
# 3、设置向下翻页爬取次数
# 根据小红书作者主页“当前发布笔记数”计算浏览器下滑次数。
# “当前发布笔记数” 获取方法参考https://www.sohu.com/a/473958839_99956253
# note_num是笔记数量
note_num = 62
# times是计算得到的翻页次数,笔记数量除以20,调整系数,再向上取整
times = math.ceil(note_num / 20 * 1.1)
print(f"需要执行翻页次数为:{times}")
# 4、设置要保存的文件名file_path
# 获取当前时间
current_time = time.localtime()
# 格式化当前时间
formatted_time = time.strftime("%Y-%m-%d %H%M%S", current_time)
# 初始化文件
init_file_path = f'小红书作者主页所有笔记-{formatted_time}.xlsx'
r = Recorder(path=init_file_path, cache_size=100)
# 下面不用改,程序自动执行
# 打开主页
open(author_url)
# 根据设置的次数,开始爬取数据
crawler(times)
# 避免数据丢失,爬虫结束时强制保存excel文件
r.record()
# 数据去重、排序,另存为新文件
re_save_excel(init_file_path)