python 爬取小红书

本文章已经生成可运行项目,

爬虫实现基本流程

一.明确需求

明确采集的网站及数据内容

  • 目标:根据小红书作者主页链接,采集作者主页所有笔记,并保存为excel表格。
    采集的字段包括作者、笔记类型、标题、点赞数、笔记链接。
  • 网址:https://www.xiaohongshu.com/user/profile/64c38af4000000000e026b43
    在这里插入图片描述

二. 分析思路

分析爬虫思路,概括如下:

  1. 打开小红书主页与登录
  2. 打开小红书作者主页,获取作者信息
  3. 提取页面笔记数据
  4. 循环下滑页面刷新数据,循环获取笔记数据

三. 代码实现

1.导入库

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

2. 登录小红书网站

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()步骤注释掉。

3. 打开小红书作者主页,获取作者信息

与登录小红书方法一样,只是要把打开的网址改为作者主页链接
在这里使用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

4. 提取页面笔记数据

使用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)

5. 向下滑动页面刷新数据

为了防止被检测到,每次下滑页面设置一个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)

6. 循环调用采集函数和翻页函数

在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}")

7. 保存数据

继续使用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)

8. 处理excel数据去重,排序

定义一个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)

9. 删除初始excel文件

由于已经得到一个最终的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} ")

三. 全部代码

import math
import random
import time

from DataRecorder import Recorder
from DrissionPage import ChromiumPage

# 初始化数据记录器时添加列名
current_time = time.localtime()
formatted_time = time.strftime("%Y-%m-%d %H%M%S", current_time)
init_file_path = f'爬取数据-{formatted_time}.xlsx'  # 也可以换成csv后缀
r = Recorder(path=init_file_path, cache_size=1)


def get_info():
    """提取当前页面所有信息"""
    data_list = []
    container = page.ele('.feeds-container')
    sections = container.eles('.note-item')

    for section in sections:
        try:
            # 笔记类型
            if section.ele('.play-icon', timeout=0):
                note_type = "视频"
            else:
                note_type = "图文"
            # 标题
            footer = section.ele(".footer")
            title = footer.ele('.title', timeout=0).text
            # 作者
            author = footer.ele('css: .author-wrapper a span').text
            # 点赞
            like = footer.ele('.count').text

            data_list.append({"笔记类型": note_type, "作者": author, "标题": title, "点赞": like})

        except Exception as e:
            print(f"提取信息时出错: {e}")
            continue

    return data_list


def crawler(scroll_times):
    """执行爬取操作"""
    global total_num
    total_num=0
    for _ in range(scroll_times):
        # 获取当前页所有信息
        data_list = get_info()
        if data_list:
            total_num += len(data_list)
            r.add_data(data_list)  # 批量添加数据
            print(f'已爬取 {len(data_list)} 条数据')

        # 滚动加载下一页
        page.scroll.to_bottom()
        time.sleep(random.uniform(5, 10))  # 随机等待防止被封




if __name__ == '__main__':
    page = ChromiumPage()
    page.get('https://www.xiaohongshu.com/user/profile/5b598e4c6b58b77b59b54c6f?xsec_token=ABs4_eQ_hT4p1-3Q4-ZXhD7nLYG6D7qxZ621HF1Iih7Us=&xsec_source=pc_feed')

    # 执行搜索
    page.wait.ele_displayed('.feeds-container', timeout=10)  # 等待商品加载
    get_info()

    # note_num是笔记数量
    note_num = 50
    # times是计算得到的翻页次数,笔记数量除以20,调整系数,再向上取整
    times = math.ceil(note_num / 20 * 1.1)

    # 开始爬取
    crawler(times)

    # 保存数据(DataRecorder会自动保存,此操作用于确保写入文件)
    r.record()


    global  total_num
    print(f"总共爬取:{total_num}")



本文章已经生成可运行项目
### 小红书地图爬虫的技术实现 为了实现小红书地图爬虫,可以采用 Python 的 Scrapy 框架进行数据抓取,并结合地理信息分析工具对用户地理位置数据进行处理和可视化。以下是一个完整的实现思路: #### 1. 数据抓取 Scrapy 是一个强大的爬虫框架,支持异步处理,适合高效地抓取大量数据[^3]。以下是使用 Scrapy 抓取小红书用户地理位置数据的基本步骤: - **创建 Scrapy 项目** 使用以下命令创建一个新的 Scrapy 项目: ```bash scrapy startproject xiaohongshu_crawler ``` - **定义 Spider** 在 `spiders` 文件夹中创建一个 Spider 文件,例如 `xiaohongshu_spider.py`,并定义爬取逻辑: ```python import scrapy class XiaohongshuSpider(scrapy.Spider): name = "xiaohongshu" allowed_domains = ["xiaohongshu.com"] start_urls = ["https://www.xiaohongshu.com/explore"] def parse(self, response): for post in response.css('div.post-item'): location = post.css('span.location::text').get() yield { 'location': location, } ``` - **设置请求头与代理** 小红书可能会对频繁访问的 IP 进行限制,因此需要设置合适的请求头和代理池以避免被封禁: ```python USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' ``` #### 2. 数据存储 抓取到的数据可以通过 Scrapy 提供的管道功能存储到文件或数据库中。例如,将数据保存为 JSON 文件: ```python class JsonPipeline: def open_spider(self, spider): self.file = open('locations.json', 'w') def close_spider(self, spider): self.file.close() def process_item(self, item, spider): line = json.dumps(dict(item)) + "\n" self.file.write(line) return item ``` #### 3. 地理数据分析 抓取到的地理位置数据可以进一步分析,例如统计各地区的用户分布情况。可以使用 Pandas 和 Matplotlib 进行数据处理和可视化: ```python import pandas as pd import matplotlib.pyplot as plt # 加载数据 data = pd.read_json('locations.json') # 统计各地区的用户数量 location_counts = data['location'].value_counts() # 可视化 location_counts.plot(kind='bar') plt.title('User Distribution by Location') plt.xlabel('Location') plt.ylabel('Number of Users') plt.show() ``` #### 4. 地图可视化 为了更直观地展示用户分布情况,可以使用 `pyecharts` 或 `folium` 绘制地图。以下是一个基于 `pyecharts` 的示例: ```python from pyecharts.charts import Map from pyecharts import options as opts # 创建地图对象 map_chart = Map() # 添加数据 map_chart.add("Users", [list(z) for z in zip(location_counts.index, location_counts.values)], "china") # 设置全局配置项 map_chart.set_global_opts( title_opts=opts.TitleOpts(title="小红书用户分布地图"), visualmap_opts=opts.VisualMapOpts(max_=max(location_counts.values)) ) # 渲染为 HTML 文件 map_chart.render('user_distribution_map.html') ``` ### 注意事项 - 小红书的数据可能受到 API 接口限制或动态加载的影响,建议研究其前端代码以找到合适的抓取点。 - 爬取过程中需遵守网站的 `robots.txt` 文件规定,避免对目标网站造成负担。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值