PHPackages                             zyan/u2p - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Image &amp; Media](/categories/media)
4. /
5. zyan/u2p

ActiveLibrary[Image &amp; Media](/categories/media)

zyan/u2p
========

网页图片抓取 SDK：输入网页链接，返回图片链接数组。内置微信公众号文章等专项抓取，支持 ajax 与源码两种图片加载方式。

1.0.1(2w ago)040MITHTMLPHP &gt;=7.4

Since Jun 18Pushed 1w agoCompare

[ Source](https://github.com/aa24615/u2p)[ Packagist](https://packagist.org/packages/zyan/u2p)[ RSS](/packages/zyan-u2p/feed)WikiDiscussions main Synced 2w ago

READMEChangelogDependencies (2)Versions (3)Used By (0)

zyan/u2p
========

[](#zyanu2p)

网页图片抓取 SDK —— 输入网页链接，返回图片链接数组。

内置微信公众号文章、豆包 / 千问 AI 分享页、今日头条文章等专项抓取，支持懒加载、ajax 接口等多种图片加载方式，可扩展自定义网站处理器。

环境要求
----

[](#环境要求)

- PHP &gt;= 7.4
- ext-json
- ext-mbstring
- Guzzle（HTTP 客户端）
- Symfony DomCrawler + CssSelector（HTML 解析）

安装
--

[](#安装)

```
composer require zyan/u2p
```

快速开始
----

[](#快速开始)

```
use Zyan\U2P\U2P;

$u2p = new U2P();

// 输入网页链接，返回图片链接数组
$images = $u2p->get('https://mp.weixin.qq.com/s/-iRttNYNtn4z4qGGQ_fbvw');

print_r($images);
// [
//     'https://mmbiz.qpic.cn/mmbiz_png/xxxx/640?wx_fmt=png&from=appmsg',
//     'https://mmbiz.qpic.cn/mmbiz_png/xxxx/640?wx_fmt=png&from=appmsg&tp=webp&wxfrom=5&wx_lazy=1',
//     ...
// ]
```

SDK 会根据 URL 自动匹配对应的处理器。未匹配到专项处理器时，回退到通用处理器。

内置处理器
-----

[](#内置处理器)

### 微信公众号文章（WeChatHandler）

[](#微信公众号文章wechathandler)

公众号文章的正文图片采用懒加载，真实地址写在 `` 中而非 `src`，图床域名为 `mmbiz.qpic.cn`。处理器会自动过滤头像、二维码、表情等非正文图片。

```
use Zyan\U2P\Handlers\WeChatHandler;

$handler = new WeChatHandler();

// 仅正文图片
$images = $handler->handle('https://mp.weixin.qq.com/s/xxxx');

// 包含封面图（封面置于数组首位）
$images = $handler->withCover()->handle('https://mp.weixin.qq.com/s/xxxx');
```

**过滤规则：**

类型处理方式正文图片保留（`class` 含 `rich_pages`/`wxw-img`，或 URL 含 `from=appmsg`）头像排除（`wx_follow_avatar_pic`、`jump_author_avatar`）二维码排除（`qr_code_pc_img`、`js_qrcode_img` 等）表情排除（`we-emoji`、`icon_emotion_single`）封面图可选（`withCover()` 从 `msg_cdn_url` 变量提取）### 通用网页（GenericHandler）

[](#通用网页generichandler)

适用于任意网页的兜底处理器，解析页面源码中的 `` 标签，优先取懒加载地址（`data-src`、`data-original`、`data-lazy-src`），自动解析相对路径，过滤 base64 等无效地址。

```
use Zyan\U2P\Handlers\GenericHandler;

$handler = new GenericHandler();
$images = $handler->handle('https://example.com/article');
```

也可以直接传入 HTML 进行解析：

```
$images = $handler->extractImages($html, 'https://example.com/news/page');
```

### 豆包 AI 分享页（DoubaoHandler）

[](#豆包-ai-分享页doubaohandler)

豆包 AI 对话分享页的图片通过 `mergeLoaderData` 注入页面脚本，正文使用 `image_ori_raw` 无水印原图（而非带水印的预览地址）。处理器从页面脚本中提取 JSON 载荷，解析 `creation_block` 中的图片。

```
use Zyan\U2P\Handlers\DoubaoHandler;

$handler = new DoubaoHandler();

// 抓取豆包分享页中的无水印图片
$images = $handler->handle('https://www.doubao.com/thread/xxxx');
```

解析逻辑参考 [ihmily/doubao-nomark](https://github.com/ihmily/doubao-nomark)。

### 千问 AI 分享页（QianwenHandler）

[](#千问-ai-分享页qianwenhandler)

千问分享页为 SPA，图片数据需通过 `share/info` 接口获取。处理器提取 `share_id` 后调用接口，取 `display_list[].image[].url` 作为无水印原图，自动排除水印图与缩略图。

```
use Zyan\U2P\Handlers\QianwenHandler;

$handler = new QianwenHandler();

// 抓取千问分享页图片
$images = $handler->handle('https://www.qianwen.com/share/chat/xxxx');

// 也可单独提取 share_id
$id = $handler->extractShareId('https://www.qianwen.com/share/chat/xxxx');
```

### 今日头条文章（ToutiaoHandler）

[](#今日头条文章toutiaohandler)

今日头条 PC 页面有反爬（需浏览器指纹），直接抓取 HTML 拿不到正文，故改走移动端 API（`m.toutiao.com/i{id}/info/v2/`）。正文 HTML 在 `data.content`，图片为 ``，封面图在 `data.poster_url`。

```
use Zyan\U2P\Handlers\ToutiaoHandler;

$handler = new ToutiaoHandler();

// 抓取头条文章图片
$images = $handler->handle('https://www.toutiao.com/article/7652651188260700699/');

// 将封面图（poster_url）置于结果首位
$images = $handler->withCover()->handle($url);
```

自定义处理器
------

[](#自定义处理器)

实现 `HandlerInterface` 接口并注册即可支持更多网站。对于通过 ajax 接口返回图片的网站，在 `handle()` 中抓取接口并解析 JSON 即可。

```
use Zyan\U2P\AbstractHandler;
use Zyan\U2P\U2P;
use Symfony\Component\DomCrawler\Crawler;

class MySiteHandler extends AbstractHandler
{
    public function supports(string $url): bool
    {
        return (bool) preg_match('#https?://mysite\.com/#i', $url);
    }

    public function handle(string $url): array
    {
        $html = $this->fetch($url);
        $crawler = $this->loadDom($html);

        $images = [];
        $crawler->filter('.article img')->each(function (Crawler $node) use (&$images) {
            $src = $this->resolveSrc($node);
            if ($src) {
                $images[] = $src;
            }
        });

        return $images;
    }
}

$u2p = new U2P();
$u2p->registerHandler(new MySiteHandler());

$images = $u2p->get('https://mysite.com/post/123');
```

自定义 HTTP 客户端
------------

[](#自定义-http-客户端)

如需自定义请求头、代理、超时等，可注入底层 Guzzle 客户端：

```
use Zyan\U2P\HttpClient;
use Zyan\U2P\U2P;
use GuzzleHttp\Client as GuzzleClient;

$guzzle = new GuzzleClient([
    'timeout' => 60,
    'proxy'   => 'http://127.0.0.1:7890',
    'headers' => ['Cookie' => 'session=xxx'],
]);

$client = new HttpClient($guzzle);
$u2p = new U2P($client);

$images = $u2p->get('https://mp.weixin.qq.com/s/xxxx');
```

API
---

[](#api)

### `U2P`

[](#u2p)

方法说明`get(string $url): string[]`抓取指定链接中的图片，返回图片链接数组`registerHandler(HandlerInterface $handler): self`注册自定义处理器（优先匹配）`setFallback(HandlerInterface $handler): self`设置兜底处理器`make(): U2P`快速创建实例### `HandlerInterface`

[](#handlerinterface)

方法说明`supports(string $url): bool`判断是否支持该链接`handle(string $url): string[]`抓取图片，返回链接数组### `WeChatHandler`

[](#wechathandler)

方法说明`withCover(bool $withCover = true): self`是否包含封面图（置于首位）`handle(string $url): string[]`抓取公众号文章图片`extractContentImages(string $html): string[]`从 HTML 中提取正文图片### `GenericHandler`

[](#generichandler)

方法说明`handle(string $url): string[]`抓取任意网页图片`extractImages(string $html, string $baseUrl = ''): string[]`从 HTML 中提取图片### `DoubaoHandler`

[](#doubaohandler)

方法说明`handle(string $url): string[]`抓取豆包 AI 分享页图片`extractContentImages(string $html): string[]`从页面 HTML 中提取无水印图片### `QianwenHandler`

[](#qianwenhandler)

方法说明`handle(string $url): string[]`抓取千问 AI 分享页图片`extractShareId(string $url): string`提取分享链接中的 `share_id``extractContentImages(string $jsonBody): string[]`从 API 响应 JSON 中提取无水印图片### `ToutiaoHandler`

[](#toutiaohandler)

方法说明`handle(string $url): string[]`抓取今日头条文章图片`withCover(bool $withCover = true): self`是否包含封面图（置于结果首位）`extractArticleId(string $url): string`提取文章 ID`extractContentImages(string $jsonBody): string[]`从 API 响应 JSON 中提取正文图片`extractCover(string $jsonBody): string`提取封面图（`poster_url`）技术栈
---

[](#技术栈)

- [Guzzle](https://github.com/guzzle/guzzle) — HTTP 客户端
- [Symfony DomCrawler](https://github.com/symfony/dom-crawler) — HTML 解析
- [Symfony CssSelector](https://github.com/symfony/css-selector) — CSS 选择器

License
-------

[](#license)

MIT

###  Health Score

38

—

LowBetter than 83% of packages

Maintenance97

Actively maintained with recent releases

Popularity11

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity35

Early-stage or recently created project

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~25 days

Total

2

Last Release

20d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/33275679?v=4)[读心印](/maintainers/aa24615)[@aa24615](https://github.com/aa24615)

---

Tags

imagecrawlerwechatweixinscrapermpu2p

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/zyan-u2p/health.svg)

```
[![Health](https://phpackages.com/badges/zyan-u2p/health.svg)](https://phpackages.com/packages/zyan-u2p)
```

###  Alternatives

[intervention/image

PHP Image Processing

14.4k214.2M2.7k](/packages/intervention-image)[league/glide

Wonderfully easy on-demand image manipulation library with an HTTP based API.

2.6k54.0M155](/packages/league-glide)[liip/imagine-bundle

This bundle provides an image manipulation abstraction toolkit for Symfony-based projects.

1.7k40.6M261](/packages/liip-imagine-bundle)[spatie/image

Manipulate images with an expressive API

1.4k63.1M200](/packages/spatie-image)[intervention/image-laravel

Laravel Integration of Intervention Image

1589.8M208](/packages/intervention-image-laravel)[intervention/gif

PHP GIF Encoder/Decoder

6131.5M16](/packages/intervention-gif)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
