Skip to content

Commit c24e27d

Browse files
author
Taois
committed
feat: 完善php写源标准
1 parent d0a09fa commit c24e27d

File tree

11 files changed

+2055
-141
lines changed

11 files changed

+2055
-141
lines changed
Lines changed: 80 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,44 @@
11
<?php
2-
// B站视频爬虫 - 简洁可用版(移除search相关代码)
3-
header('Content-Type: application/json; charset=utf-8');
2+
/**
3+
* B站视频爬虫 - PHP 适配版 (道长重构)
4+
* 按照 BaseSpider 结构重写
5+
*/
46

5-
class BiliBiliSpider {
6-
private $extendDict = [];
7-
private $cookie = [];
8-
private $header = [
9-
"User-Agent" => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 Safari/537.36",
10-
"Referer" => "https://www.bilibili.com"
11-
];
12-
13-
public function __construct() {
14-
$this->extendDict = $this->getExtendDict();
15-
$this->cookie = $this->getCookie();
16-
}
17-
18-
private function getExtendDict() {
19-
return [
20-
'cookie' => $this->getConfigCookie(),
21-
'thread' => '0'
22-
];
23-
}
7+
require_once __DIR__ . '/spider.php';
8+
9+
class Spider extends BaseSpider {
2410

25-
private function getConfigCookie() {
26-
// 配置您的B站Cookie
27-
return 'buvid3=xxxx; SESSDATA=xxxx;';
11+
private $cookie = [];
12+
13+
public function init($extend = '') {
14+
$this->headers['Referer'] = "https://www.bilibili.com";
15+
// 配置初始 Cookie
16+
// 实际使用时,建议通过 ext 传入 cookie
17+
$configCookie = 'buvid3=xxxx; SESSDATA=xxxx;';
18+
19+
// 尝试从 extend 获取 cookie (假设 extend 是 JSON 字符串或直接是 cookie 字符串)
20+
// 这里简化处理:如果 extend 包含 SESSDATA,则认为是 cookie
21+
if (!empty($extend)) {
22+
if (strpos($extend, 'SESSDATA') !== false) {
23+
$configCookie = $extend;
24+
} elseif (is_array($extend) && isset($extend['cookie'])) {
25+
$configCookie = $extend['cookie'];
26+
} else {
27+
// 尝试解析 json
28+
$json = json_decode($extend, true);
29+
if (isset($json['cookie'])) {
30+
$configCookie = $json['cookie'];
31+
}
32+
}
33+
}
34+
35+
$this->cookie = $this->parseCookie($configCookie);
2836
}
2937

30-
private function getCookie() {
31-
$cookie = $this->extendDict['cookie'] ?? '';
32-
if (empty($cookie)) return [];
33-
38+
private function parseCookie($cookieStr) {
39+
if (empty($cookieStr)) return [];
3440
$cookies = [];
35-
$pairs = explode(';', $cookie);
41+
$pairs = explode(';', $cookieStr);
3642
foreach ($pairs as $pair) {
3743
$pair = trim($pair);
3844
if (strpos($pair, '=') !== false) {
@@ -43,34 +49,6 @@ private function getCookie() {
4349
return $cookies;
4450
}
4551

46-
private function httpRequest($url, $params = []) {
47-
$ch = curl_init();
48-
49-
if (!empty($params)) {
50-
$url .= '?' . http_build_query($params);
51-
}
52-
53-
$headers = [];
54-
foreach ($this->header as $key => $value) {
55-
$headers[] = $key . ': ' . $value;
56-
}
57-
58-
curl_setopt_array($ch, [
59-
CURLOPT_URL => $url,
60-
CURLOPT_RETURNTRANSFER => true,
61-
CURLOPT_TIMEOUT => 10,
62-
CURLOPT_HTTPHEADER => $headers,
63-
CURLOPT_COOKIE => $this->buildCookieString(),
64-
CURLOPT_SSL_VERIFYPEER => false,
65-
CURLOPT_FOLLOWLOCATION => true
66-
]);
67-
68-
$response = curl_exec($ch);
69-
curl_close($ch);
70-
71-
return json_decode($response, true) ?: [];
72-
}
73-
7452
private function buildCookieString() {
7553
$pairs = [];
7654
foreach ($this->cookie as $name => $value) {
@@ -79,8 +57,18 @@ private function buildCookieString() {
7957
return implode('; ', $pairs);
8058
}
8159

82-
// homeContent - 首页分类
83-
public function homeContent() {
60+
// 覆盖父类 fetch 以自动添加 cookie
61+
protected function fetch($url, $options = [], $headers = []) {
62+
if (!isset($options['cookie'])) {
63+
$cookieStr = $this->buildCookieString();
64+
if (!empty($cookieStr)) {
65+
$options['cookie'] = $cookieStr;
66+
}
67+
}
68+
return parent::fetch($url, $options, $headers);
69+
}
70+
71+
public function homeContent($filter = []) {
8472
$classes = [
8573
["type_id" => "沙雕仙逆", "type_name" => "傻屌仙逆"],
8674
["type_id" => "沙雕动画", "type_name" => "沙雕动画"],
@@ -126,14 +114,12 @@ public function homeContent() {
126114
["type_id" => "软件教程", "type_name" => "软件教程"],
127115
["type_id" => "Windows", "type_name" => "Windows"]
128116
];
129-
130117
return ['class' => $classes];
131118
}
132-
133-
// homeVideoContent - 首页推荐视频
119+
134120
public function homeVideoContent() {
135-
$url = 'https://api.bilibili.com/x/web-interface/popular';
136-
$data = $this->httpRequest($url, ['ps' => 20, 'pn' => 1]);
121+
$url = 'https://api.bilibili.com/x/web-interface/popular?ps=20&pn=1';
122+
$data = json_decode($this->fetch($url), true);
137123

138124
$videos = [];
139125
if (isset($data['data']['list'])) {
@@ -146,22 +132,21 @@ public function homeVideoContent() {
146132
];
147133
}
148134
}
149-
150135
return ['list' => $videos];
151136
}
152-
153-
// categoryContent - 分类内容(使用搜索API)
154-
public function categoryContent($tid, $page, $filters = []) {
155-
$page = max(1, intval($page));
137+
138+
public function categoryContent($tid, $pg = 1, $filter = [], $extend = []) {
139+
$page = max(1, intval($pg));
156140

157141
$url = 'https://api.bilibili.com/x/web-interface/search/type';
158142
$params = [
159143
'search_type' => 'video',
160144
'keyword' => $tid,
161145
'page' => $page
162146
];
147+
$url .= '?' . http_build_query($params);
163148

164-
$data = $this->httpRequest($url, $params);
149+
$data = json_decode($this->fetch($url), true);
165150

166151
$videos = [];
167152
if (isset($data['data']['result'])) {
@@ -180,19 +165,19 @@ public function categoryContent($tid, $page, $filters = []) {
180165
$pageCount = $data['data']['numPages'] ?? 1;
181166
$total = $data['data']['numResults'] ?? count($videos);
182167

183-
return [
184-
'list' => $videos,
185-
'page' => $page,
186-
'pagecount' => $pageCount,
187-
'limit' => 20,
188-
'total' => $total
189-
];
168+
return $this->pageResult($videos, $page, $total, 20);
190169
}
191-
192-
// detailContent - 视频详情
193-
public function detailContent($vid) {
194-
$url = 'https://api.bilibili.com/x/web-interface/view';
195-
$data = $this->httpRequest($url, ['aid' => $vid]);
170+
171+
public function searchContent($key, $quick = false, $pg = 1) {
172+
return $this->categoryContent($key, $pg);
173+
}
174+
175+
public function detailContent($ids) {
176+
if (empty($ids)) return ['list' => []];
177+
$vid = $ids[0];
178+
179+
$url = 'https://api.bilibili.com/x/web-interface/view?aid=' . $vid;
180+
$data = json_decode($this->fetch($url), true);
196181

197182
if (!isset($data['data'])) {
198183
return ['list' => []];
@@ -204,7 +189,7 @@ public function detailContent($vid) {
204189
$playUrl = '';
205190
foreach ($video['pages'] as $index => $page) {
206191
$part = $page['part'] ?: '' . ($index + 1) . '';
207-
$duration = $this->formatDuration($page['duration']);
192+
// 构造 playId: avid_cid
208193
$playUrl .= "{$part}\${$vid}_{$page['cid']}#";
209194
}
210195

@@ -219,35 +204,34 @@ public function detailContent($vid) {
219204

220205
return ['list' => [$vod]];
221206
}
222-
223-
// playContent - 播放地址(高清优化)
224-
public function playContent($vid) {
225-
if (strpos($vid, '_') !== false) {
226-
list($avid, $cid) = explode('_', $vid);
207+
208+
public function playContent($flag, $id, $vipFlags = []) {
209+
if (strpos($id, '_') !== false) {
210+
list($avid, $cid) = explode('_', $id);
227211
} else {
228-
return $this->errorResponse('无效的视频ID格式');
212+
return ['parse' => 0, 'url' => '', 'error' => '无效的视频ID格式'];
229213
}
230214

231-
// 使用高质量参数
232215
$url = 'https://api.bilibili.com/x/player/playurl';
233216
$params = [
234217
'avid' => $avid,
235218
'cid' => $cid,
236219
'qn' => 112, // 原画质量
237220
'fnval' => 0,
238221
];
222+
$url .= '?' . http_build_query($params);
239223

240-
$data = $this->httpRequest($url, $params);
224+
$data = json_decode($this->fetch($url), true);
241225

242226
if (!isset($data['data']) || $data['code'] !== 0) {
243-
return $this->errorResponse('获取播放地址失败');
227+
return ['parse' => 0, 'url' => '', 'error' => '获取播放地址失败'];
244228
}
245229

246230
// 直接返回第一个播放地址
247231
if (isset($data['data']['durl'][0]['url'])) {
248232
$playUrl = $data['data']['durl'][0]['url'];
249233

250-
$headers = $this->header;
234+
$headers = $this->headers;
251235
$headers['Referer'] = 'https://www.bilibili.com/video/av' . $avid;
252236
$headers['Origin'] = 'https://www.bilibili.com';
253237

@@ -259,9 +243,9 @@ public function playContent($vid) {
259243
];
260244
}
261245

262-
return $this->errorResponse('无法获取播放地址');
246+
return ['parse' => 0, 'url' => '', 'error' => '无法获取播放地址'];
263247
}
264-
248+
265249
// 工具函数
266250
private function formatDuration($seconds) {
267251
if ($seconds <= 0) return '00:00';
@@ -277,50 +261,6 @@ private function formatSearchDuration($duration) {
277261
}
278262
return '00:00';
279263
}
280-
281-
private function errorResponse($message) {
282-
return [
283-
'parse' => 0,
284-
'url' => '',
285-
'error' => $message
286-
];
287-
}
288264
}
289265

290-
// 主处理逻辑
291-
$ac = $_GET['ac'] ?? 'detail';
292-
$t = $_GET['t'] ?? '';
293-
$pg = $_GET['pg'] ?? '1';
294-
$f = $_GET['f'] ?? '';
295-
$ids = $_GET['ids'] ?? '';
296-
$id = $_GET['id'] ?? '';
297-
298-
$spider = new BiliBiliSpider();
299-
300-
try {
301-
switch ($ac) {
302-
case 'detail':
303-
if (!empty($ids)) {
304-
echo json_encode($spider->detailContent($ids));
305-
} elseif (!empty($t)) {
306-
$filters = !empty($f) ? json_decode($f, true) : [];
307-
echo json_encode($spider->categoryContent($t, $pg, $filters));
308-
} else {
309-
$result = $spider->homeContent();
310-
$videoResult = $spider->homeVideoContent();
311-
$result['list'] = $videoResult['list'];
312-
echo json_encode($result);
313-
}
314-
break;
315-
316-
case 'play':
317-
echo json_encode($spider->playContent($id));
318-
break;
319-
320-
default:
321-
echo json_encode(['error' => '未知操作: ' . $ac]);
322-
}
323-
} catch (Exception $e) {
324-
echo json_encode(['error' => $e->getMessage()]);
325-
}
326-
?>
266+
(new Spider())->run();

spider/php/config.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
<?php
2+
/**
3+
* Copyright 道长所有
4+
* Date: 2026/01/23
5+
*/
26
header('Content-Type: application/json; charset=utf-8');
37
// http://127.0.0.1:9980/config.php
48
// ==================
@@ -15,7 +19,7 @@
1519
continue;
1620
}
1721

18-
if ($file === $self || $file === 'index.php') {
22+
if (in_array($file, [$self, 'index.php', 'spider.php', 'example_t4.php', 'test_runner.php'])) {
1923
continue;
2024
}
2125

0 commit comments

Comments
 (0)