前言
大家好,我是海鸽。今天我要介绍一款功能强大的社交媒体内容抓取工具。
它能够一键抓取包括xhs
、某音、某手、B站、以及微博在内的多个平台上的图片、视频、评论、点赞、转发等信息,让您轻松获取所需内容。
这个项目开源不到一年,目前在Github
上拥有15k+ stars
和5k+ forks
,曾经更是登上Github Trending
。
因为热度过高,作者担心某些很
刑
的原因,还曾经删库。不过还是被某些有心之人偷了代码,在网上卖钱用于商业行为。因此作者补充了免责声明,重新开源,并提醒大家不要上当受骗。
项目简介
MediaCrawler
,由NanmiCoder
精心打造,是一个在Github
上广受好评的开源项目。它专注于高效地抓取小红书、抖音、快手、B站和微博等热门社交平台的视频与帖子评论,开箱即用。
MediaCrawler
提供定制化数据抓取,配备IP代理池
以规避封锁风险,并支持多种数据格式保存,满足多样化的数据处理需求。
采用Python
作为核心开发语言,原生支持并发,MediaCrawler
不仅实现了强大的数据抓取功能,更以其开放的源代码,方便实现二次开发,为广大开发者和学习者提供了一个学习和探索网络爬虫技术的理想平台。
功能列表
平台 | 关键词搜索 | 指定帖子ID爬取 | 二级评论 | 指定创作者主页 | 登录态缓存 | IP代理池 | 生成评论词云图 |
---|---|---|---|---|---|---|---|
小红书 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
抖音 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
快手 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
B 站 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
微博 | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ |
贴吧 | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ |
这个项目如何使用呢
MediaCrawler
作为一个Python
项目,其使用前提自然是确保您的系统已安装了Python
环境。
至于如何使用MediaCrawler
,作者已经非常贴心地在项目的README文件
中提供了详尽的指导。只需按照README
中的步骤操作,即使是初学者也能轻松上手。简而言之,您需要做的只是阅读README文件
,然后跟随其中的指引,即可开始您的爬虫之旅。
下载/克隆项目到本地
shell
git clone https://github.com/NanmiCoder/MediaCrawler.git
创建并激活 python 虚拟环境
shell
# 进入项目根目录
cd MediaCrawler
# 创建虚拟环境
# 注意python 版本需要3.7 - 3.9 高于该版本可能会出现一些依赖包兼容问题
python -m venv venv
# macos & linux 激活虚拟环境
source venv/bin/activate
# windows 激活虚拟环境
venv\Scripts\activate
安装依赖库
shell
pip install -r requirements.txt
安装 playwright 浏览器驱动
shell
playwright install
数据保存
MediaCrawler
的数据存储模块经过精心封装,简化了大量数据的存储过程。源代码完全开放,便于深入研究和定制,可以在config/base_config.py
进行配置。
- 支持保存到关系型数据库(
Mysql
、PgSQL
等)- 执行
python db.py
初始化数据库数据库表结构(只在首次执行)
- 执行
- 支持保存到
csv
中(data/目录下
) - 支持保存到
json
中(data/目录下
)
运行爬虫程序
shell
### 项目默认是没有开启评论爬取模式,如需评论请在config/base_config.py中的 ENABLE_GET_COMMENTS 变量修改
### 一些其他支持项,也可以在config/base_config.py查看功能,写的有中文注释
# 从配置文件中读取关键词搜索相关的帖子并爬取帖子信息与评论
python main.py --platform xhs --lt qrcode --type search
# 从配置文件中读取指定的帖子ID列表获取指定帖子的信息与评论信息
python main.py --platform xhs --lt qrcode --type detail
# 打开对应APP扫二维码登录
# 其他平台爬虫使用示例,执行下面的命令查看
python main.py --help
以xhs
(二维码登录)关键字搜索为例,当我们执行启动命令后,MediaCrawler
将为我们拉起无头浏览器,并弹出小红书二维码。
MediaCrawler
提供了3
种登录小红书的方式:QRCode
、手机号
、Cookie
,登录相关代码都在media_platform/xhs/login.py
文件中。
我们扫码登录后,MediaCrawler
将通过无头浏览器技术识别并保存您的身份信息。这样一来,我们就可以在后续的会话中,以该身份为基础,安全地抓取所需的数据(我胆小,我选择用小号)。
数据就被这么简单地抓取下来了。
项目架构与代码结构
原理 :利用playwright
搭桥,保留登录成功后的上下文浏览器环境,通过执行JS表达式
获取一些加密参数。通过使用此方式,免去了复现核心加密JS代码
,逆向难度大大降低。
MediaCrawler
是一款开箱即用的Python
项目,它采用Python
的原生协程模式进行开发,具备清晰的分层架构,这种设计不仅简化了代码的编写,而且极大地提高了代码的可读性和可维护性。这种模式为二次开发提供了极大的便利,同时也为实现高并发的爬虫模型打下了坚实的基础。
shell
# 源自官网,未更新微博、贴吧目录,仅供参考
MediaCrawler
├── base
│ └── base_crawler.py # 项目的抽象类
├── browser_data # 换成用户的浏览器数据目录
├── config
│ ├── account_config.py # 账号代理池配置
│ ├── base_config.py # 基础配置
│ └── db_config.py # 数据库配置
├── data # 数据保存目录
├── libs
│ ├── douyin.js # 抖音Sign函数
│ └── stealth.min.js # 去除浏览器自动化特征的JS
├── media_platform
│ ├── douyin # 抖音crawler实现
│ ├── xhs # 小红书crawler实现
│ ├── bilibili # B站crawler实现
│ └── kuaishou # 快手crawler实现
├── modles
│ ├── douyin.py # 抖音数据模型
│ ├── xiaohongshu.py # 小红书数据模型
│ ├── kuaishou.py # 快手数据模型
│ └── bilibili.py # B站数据模型
├── tools
│ ├── utils.py # 暴露给外部的工具函数
│ ├── crawler_util.py # 爬虫相关的工具函数
│ ├── slider_util.py # 滑块相关的工具函数
│ ├── time_util.py # 时间相关的工具函数
│ ├── easing.py # 模拟滑动轨迹相关的函数
| └── words.py # 生成词云图相关的函数
├── db.py # DB ORM
├── main.py # 程序入口
├── var.py # 上下文变量定义
└── recv_sms_notification.py # 短信转发器的HTTP SERVER接口
此外,MediaCrawler
的解决方案同样适用于那些具有较高逆向工程难度的网站。它能够提供有效的策略来规避这些挑战,确保数据抓取的效率和稳定性。
核心原理(以xhs为例)
xhs
相关逻辑位于以下几个文件中:
xhs
的代码并不是很多,主要逻辑在core.py
、client.py
、login.py
、help.py
中。
Sign签名算法
小红书浏览器端接口有做sign验签
,media_platform/xhs/client.py
文件中的_pre_headers
方法生成sign
相关参数。
python
async def _pre_headers(self, url: str, data=None) -> Dict:
"""
请求头参数签名
Args:
url:
data:
Returns:
"""
encrypt_params = await self.playwright_page.evaluate("([url, data]) => window._webmsxyw(url,data)", [url, data])
local_storage = await self.playwright_page.evaluate("() => window.localStorage")
signs = sign(
a1=self.cookie_dict.get("a1", ""),
b1=local_storage.get("b1", ""),
x_s=encrypt_params.get("X-s", ""),
x_t=str(encrypt_params.get("X-t", ""))
)
headers = {
"X-S": signs["x-s"],
"X-T": signs["x-t"],
"x-S-Common": signs["x-s-common"],
"X-B3-Traceid": signs["x-b3-traceid"]
}
self.headers.update(headers)
return self.headers
主要签名逻辑sign
函数则是位于media_platform/xhs/help.py
文件中。
python
def sign(a1="", b1="", x_s="", x_t=""):
"""
takes in a URI (uniform resource identifier), an optional data dictionary, and an optional ctime parameter. It returns a dictionary containing two keys: "x-s" and "x-t".
"""
common = {
"s0": 3, # getPlatformCode
"s1": "",
"x0": "1", # localStorage.getItem("b1b1")
"x1": "3.7.8-2", # version
"x2": "Mac OS",
"x3": "xhs-pc-web",
"x4": "4.27.2",
"x5": a1, # cookie of a1
"x6": x_t,
"x7": x_s,
"x8": b1, # localStorage.getItem("b1")
"x9": mrc(x_t + x_s + b1),
"x10": 154, # getSigCount
}
encode_str = encodeUtf8(json.dumps(common, separators=(',', ':')))
x_s_common = b64Encode(encode_str)
x_b3_traceid = get_b3_trace_id()
return {
"x-s": x_s,
"x-t": x_t,
"x-s-common": x_s_common,
"x-b3-traceid": x_b3_traceid
}
反反爬虫
python
async def start(self) -> None:
playwright_proxy_format, httpx_proxy_format = None, None
if config.ENABLE_IP_PROXY:
ip_proxy_pool = await create_ip_pool(config.IP_PROXY_POOL_COUNT, enable_validate_ip=True)
ip_proxy_info: IpInfoModel = await ip_proxy_pool.get_proxy()
playwright_proxy_format, httpx_proxy_format = self.format_proxy_info(ip_proxy_info)
async with async_playwright() as playwright:
# Launch a browser context.
chromium = playwright.chromium
self.browser_context = await self.launch_browser(
chromium,
None,
self.user_agent,
headless=config.HEADLESS
)
# stealth.min.js is a js script to prevent the website from detecting the crawler.
await self.browser_context.add_init_script(path="libs/stealth.min.js")
# add a cookie attribute webId to avoid the appearance of a sliding captcha on the webpage
await self.browser_context.add_cookies([{
'name': "webId",
'value': "xxx123", # any value
'domain': ".xiaohongshu.com",
'path': "/"
}])
self.context_page = await self.browser_context.new_page()
await self.context_page.goto(self.index_url)
# Create a client to interact with the xiaohongshu website.
self.xhs_client = await self.create_xhs_client(httpx_proxy_format)
if not await self.xhs_client.pong():
login_obj = XiaoHongShuLogin(
login_type=config.LOGIN_TYPE,
login_phone="", # input your phone number
browser_context=self.browser_context,
context_page=self.context_page,
cookie_str=config.COOKIES
)
await login_obj.begin()
await self.xhs_client.update_cookies(browser_context=self.browser_context)
crawler_type_var.set(config.CRAWLER_TYPE)
if config.CRAWLER_TYPE == "search":
# Search for notes and retrieve their comment information.
await self.search()
elif config.CRAWLER_TYPE == "detail":
# Get the information and comments of the specified post
await self.get_specified_notes()
elif config.CRAWLER_TYPE == "creator":
# Get creator's information and their notes and comments
await self.get_creators_and_notes()
else:
pass
utils.logger.info("[XiaoHongShuCrawler.start] Xhs Crawler finished ...")
可以看到作者在media_platform/xhs/core.py
的start
函数实现了诸如以下的反反爬策略:
- 支持设置IP代理
- 反headless浏览器检测
- 预置cookies防止出现滑块验证码
- 登录状态确认
小结
总体而言,MediaCrawler
不仅是一个值得深入研究的项目,更是一个卓越的学习典范。它不仅为我们提供了一个全新的视角来深入理解和探索爬虫技术,还为我们在爬虫
领域的学习和实践提供了宝贵的参考和启发。
希望大家在学习的过程中,能够遵守相关法规法条,合理合法使用爬虫技术。
最后
今天的分享就到这里。如果觉得不错,点赞
,关注
安排起来吧。