├── .editorconfig
├── .gitattributes
├── .gitignore
├── .travis.yml
├── BilibiliLink.wl
├── BilibiliLinkLoader.m
├── Config
├── BundleInfo.m
├── DocInfo.m
└── LoadInfo.m
├── Kernel
├── Format.wl
├── init.m
└── scripts.m
├── LICENSE
├── Packages
├── !APIs.m
├── !Directories.m
├── BilibiliCore.m
├── BilibiliDDOS.m
├── BilibiliDataServer.m
├── BilibiliPhoto.m
├── BilibiliUI.m
├── BilibiliVideoSection.m
├── Crawlers
│ ├── ArchiveCrawlers.nb
│ └── TagCrawlers.nb
├── ObjectAlbum.m
├── ObjectDownload.m
├── ObjectVideoSection.m
└── __Dev
│ ├── !BilibiliColumns.m
│ ├── Album.m
│ ├── BilibiliSearch.m
│ └── Proxy.m
├── PacletInfo.m
├── Readme.md
├── Resources
└── ico
│ ├── BilibiliAlbumObject.jpg
│ ├── BilibiliDownloadObject.png
│ ├── BilibiliVideoSectionObject.png
│ └── Readme.md
├── docs
├── .vuepress
│ ├── config.js
│ └── override.styl
├── Crawler
│ ├── Readme.md
│ ├── Tag.md
│ └── Video.md
├── Photo
│ ├── Object.md
│ └── Readme.md
├── Readme.md
├── Start
│ ├── Design.md
│ ├── Guide.md
│ └── Readme.md
├── Toys
│ └── Readme.md
└── Video
│ ├── CP.md
│ ├── Object.md
│ └── Readme.md
├── package.json
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = tab
6 | indent_size = 4
7 | end_of_line = CRLF
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 | # 屏蔽文档与 build 文件统计
3 | Documentation/ linguist-documentation
4 | # make things fun, lol
5 | *.md linguist-language=vue
6 | *.wl linguist-language=bash
7 | Config/ linguist-language=perl
8 | BilibiliLinkLoader.m linguist-language=ruby
9 | Packages/__Dev/*.m linguist-language=mercury
10 | # lfs track notebook
11 | *.nb filter=lfs diff=lfs merge=lfs -text
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Idea Project
2 | *.iml
3 | .idea/
4 |
5 | # yarn
6 | node_modules/
7 | npm-debug.log*
8 | yarn-debug.log*
9 | yarn-error.log*
10 |
11 | # Build Temp
12 | .DS_Store
13 | docs/.build/
14 |
15 |
16 | # Notebook
17 | # *.nb
18 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: required
2 | dist: trusty
3 | # 只需要自定义下面五个量
4 | env:
5 | global:
6 | - GITHUB_NAME: Gal@Builder # 瞎填都可以
7 | - GITHUB_MAIL: GAL@moe-net.tech # 瞎填都可以
8 | - GITHUB_USER: Moe-Net # 你的用户名
9 | - GITHUB_REPO: BilibiliLink # 你的项目名
10 | # 还有一个 TRAVIS_KEY 填在 travis settings 里!
11 | # 教程: https://github.com/settings/tokens
12 | before_script:
13 | - export TZ='Asia/Shanghai'
14 | - git config --global user.name "${GITHUB_NAME}"
15 | - git config --global user.email "${GITHUB_MAIL}"
16 | script:
17 | # 使用要求 10 次提交之类有 tag 存在, 名称必须为 v1.0.0 类似的形式
18 | - git clone --depth 10 --branch master --single-branch https://github.com/${GITHUB_USER}/${GITHUB_REPO}
19 | - cd ${GITHUB_REPO}
20 | - ver=`git describe --abbrev=0 --tags`
21 | - nVer=`echo $ver | awk -F. '{printf "%s.%s.%s\n",$1,$2,$3+1}'`
22 | - echo $nVer
23 | - cd ..
24 | before_deploy:
25 | - git tag -a "$nVer" -m "$(date +'%Y%m%d%H%M%S')-$(git log --format=%h -1)"
26 | - cd ${GITHUB_REPO}
27 | # 清理工程文件
28 | - rm -rf Packages/Crawlers
29 | - rm -rf Packages/__Dev
30 | - rm -rf docs
31 | - rm -f .gitignore
32 | - rm -f .gitattributes
33 | - rm -f .editorconfig
34 | - rm -f .travis.yml
35 | - rm -f *.json
36 | - rm -f yarn.lock
37 | # 清理文档(可选)
38 | # - rm -rf Documentation
39 | - ls && cd ..
40 | - tar -cJf ${GITHUB_REPO}.tar.xz ${GITHUB_REPO}
41 | deploy:
42 | provider: releases
43 | api_key: ${TRAVIS_KEY}
44 | name: AutoBuild-$nVer
45 | skip_cleanup: true
46 | file:
47 | - ${GITHUB_REPO}.tar.xz
48 | prerelease: true
49 |
--------------------------------------------------------------------------------
/BilibiliLink.wl:
--------------------------------------------------------------------------------
1 | If[!TrueQ[BilibiliLink`PackageScope`Private`$LoadCompleted],
2 | << BilibiliLink`BilibiliLinkLoader`
3 | ]
--------------------------------------------------------------------------------
/BilibiliLinkLoader.m:
--------------------------------------------------------------------------------
1 | (* ::Title:: *)
2 | (*BilibiliLink`*)
3 |
4 |
5 | (* ::Text::GrayLevel[0.5]:: *)
6 | (* Autogenerated BilibiliLink loader file *)
7 |
8 |
9 | Unprotect[BilibiliLink`PackageScope`Private`$TopLevelLoad];
10 | BilibiliLink`PackageScope`Private`$TopLevelLoad =
11 | MemberQ[$ContextPath, "Global`"];
12 |
13 |
14 | BeginPackage["BilibiliLink`"];
15 |
16 |
17 | BilibiliLink::usage =
18 | "BilibiliLink is a manager head for the BilibiliLink package";
19 |
20 |
21 | (* ::Subsubsection::Closed:: *)
22 | (*$ContextPath*)
23 |
24 |
25 | $ContextPath =
26 | Join[$ContextPath,
27 | "BilibiliLink`" <>
28 | StringReplace[
29 | FileNameDrop[#, FileNameDepth@DirectoryName@$InputFileName],
30 | $PathnameSeparator -> "`"
31 | ]& /@
32 | Select[
33 | DirectoryQ@# &&
34 | StringMatchQ[
35 | StringReplace[
36 | FileNameDrop[#, FileNameDepth@DirectoryName@$InputFileName],
37 | $PathnameSeparator -> "`"
38 | ],
39 | ("$" | WordCharacter)..
40 | ]
41 | &]@
42 | FileNames["*",
43 | FileNameJoin@{
44 | DirectoryName@$InputFileName,
45 | "Packages"
46 | },
47 | Infinity
48 | ]
49 | ]
50 |
51 |
52 | (* ::Section:: *)
53 | (* Package Functions *)
54 |
55 |
56 | Unprotect["`PackageScope`Private`*"];
57 | Begin["`PackageScope`Private`"];
58 |
59 |
60 | Clear[BilibiliLink];
61 |
62 |
63 | (* ::Subsection:: *)
64 | (*Constants*)
65 |
66 |
67 | (* ::Subsubsection::Closed:: *)
68 | (*Naming*)
69 |
70 |
71 | BilibiliLink["Directory"] :=
72 | $PackageDirectory;
73 | $PackageDirectory =
74 | DirectoryName@$InputFileName;
75 |
76 |
77 | BilibiliLink["Name"] :=
78 | $PackageName;
79 | $PackageName =
80 | "BilibiliLink";
81 |
82 |
83 | (* ::Subsubsection::Closed:: *)
84 | (*Loading*)
85 |
86 |
87 | BilibiliLink["PackageListing"] := $PackageListing;
88 | $PackageListing = <||>;
89 | BilibiliLink["Contexts"] := $PackageContexts;
90 | $PackageContexts = {
91 | "BilibiliLink`",
92 | "BilibiliLink`PackageScope`Private`",
93 | "BilibiliLink`PackageScope`Package`"
94 | };
95 | $PackageDeclared =
96 | TrueQ[$PackageDeclared];
97 |
98 |
99 | (* ::Subsubsection::Closed:: *)
100 | (*Scoping*)
101 |
102 |
103 | BilibiliLink["FEScopedSymbols"] := $PackageFEHiddenSymbols;
104 | $PackageFEHiddenSymbols = {};
105 | BilibiliLink["PackageScopedSymbols"] := $PackageScopedSymbols;
106 | $PackageScopedSymbols = {};
107 | BilibiliLink["LoadingParameters"] := $PackageLoadSpecs
108 | $PackageLoadSpecs =
109 | Merge[
110 | {
111 | With[
112 | {
113 | f =
114 | Append[
115 | FileNames[
116 | "LoadInfo." ~~ "m" | "wl",
117 | FileNameJoin@{$PackageDirectory, "Config"}
118 | ],
119 | None
120 | ][[1]]
121 | },
122 | Replace[
123 | Quiet[
124 | Import@f,
125 | {
126 | Import::nffil,
127 | Import::chtype
128 | }
129 | ],
130 | Except[KeyValuePattern[{}]] :>
131 | {}
132 | ]
133 | ],
134 | With[
135 | {
136 | f =
137 | Append[
138 | FileNames[
139 | "LoadInfo." ~~ "m" | "wl",
140 | FileNameJoin@{$PackageDirectory, "Private", "Config"}
141 | ],
142 | None
143 | ][[1]]},
144 | Replace[
145 | Quiet[
146 | Import@f,
147 | {
148 | Import::nffil,
149 | Import::chtype
150 | }
151 | ],
152 | Except[KeyValuePattern[{}]] :>
153 | {}
154 | ]
155 | ]
156 | },
157 | Last
158 | ];
159 |
160 |
161 | (* ::Subsubsection::Closed:: *)
162 | (*Allow flags*)
163 |
164 |
165 | BilibiliLink["AllowRescoping"] := $AllowPackageRescoping;
166 | $AllowPackageRescoping =
167 | Replace[
168 | Lookup[$PackageLoadSpecs, "AllowRescoping"],
169 | Except[True | False] -> $TopLevelLoad
170 | ];
171 | BilibiliLink["AllowRecoloring"] := $AllowPackageRecoloring;
172 | $AllowPackageRecoloring =
173 | Replace[
174 | Lookup[$PackageLoadSpecs, "AllowRecoloring"],
175 | Except[True | False] -> $TopLevelLoad
176 | ];
177 | BilibiliLink["AllowAutocompletions"] := $AllowPackageAutocompletions;
178 | $AllowPackageAutocompletions =
179 | Replace[
180 | Lookup[$PackageLoadSpecs, "AllowAutocompletions"],
181 | Except[True | False] -> $TopLevelLoad
182 | ];
183 | (* ::Subsection:: *)
184 | (*Paths*)
185 |
186 |
187 | (* ::Subsubsection::Closed:: *)
188 | (*PackageFilePath*)
189 |
190 |
191 | PackageFilePath[p__] :=
192 | FileNameJoin[Flatten@{
193 | $PackageDirectory,
194 | p
195 | }];
196 |
197 |
198 | (* ::Subsubsection::Closed:: *)
199 | (*PackageFEFile*)
200 |
201 |
202 | PackageFEFile[p___, f_] :=
203 | FrontEnd`FileName[
204 | Evaluate@
205 | Flatten@{
206 | $PackageName,
207 | p
208 | },
209 | f
210 | ];
211 |
212 |
213 | (* ::Subsubsection::Closed:: *)
214 | (*PackagePathSymbol*)
215 |
216 |
217 | PackagePathSymbol[parts___String, sym_String] :=
218 | ToExpression[StringRiffle[{$PackageName, parts, sym}, "`"], StandardForm, HoldPattern];
219 | PackagePathSymbol[parts___String, sym_Symbol] :=
220 | PackagePathSymbol[parts, Evaluate@SymbolName@Unevaluated[sym]];
221 | PackagePathSymbol ~ SetAttributes ~ HoldRest;
222 | (* ::Subsection:: *)
223 | (*Loading*)
224 |
225 |
226 | (* ::Subsubsection:: *)
227 | (*Constants*)
228 |
229 |
230 | BilibiliLink["FileContexts"] := $PackageFileContexts;
231 | If[Not@AssociationQ@$PackageFileContexts,
232 | $PackageFileContexts =
233 | <||>
234 | ];
235 |
236 |
237 | BilibiliLink["DeclaredPackages"] := $DeclaredPackages;
238 | If[Not@AssociationQ@$DeclaredPackages,
239 | $DeclaredPackages =
240 | <||>
241 | ];
242 |
243 |
244 | BilibiliLink["LoadedPackages"] := $LoadedPackages;
245 | If[Not@ListQ@$LoadedPackages,
246 | $LoadedPackages = {}
247 | ];
248 |
249 |
250 | (* ::Subsubsection::Closed:: *)
251 | (*PackageFileContext*)
252 |
253 |
254 | PackageFileContextPath[f_String?DirectoryQ] :=
255 | FileNameSplit[FileNameDrop[f, FileNameDepth[$PackageDirectory] + 1]];
256 | PackageFileContextPath[f_String?FileExistsQ] :=
257 | PackageFileContextPath[DirectoryName@f];
258 |
259 |
260 | PackageFileContext[f_String?DirectoryQ] :=
261 | With[{s = PackageFileContextPath[f]},
262 | StringRiffle[Append[""]@Prepend[s, BilibiliLink], "`"]
263 | ];
264 | PackageFileContext[f_String?FileExistsQ] :=
265 | PackageFileContext[DirectoryName[f]];
266 |
267 |
268 | (* ::Subsubsection::Closed:: *)
269 | (*PackageExecute*)
270 |
271 |
272 | PackageExecute[expr_] :=
273 | CompoundExpression[
274 | Block[{$ContextPath = {"System`"}},
275 | BeginPackage["BilibiliLink`"];
276 | $ContextPath =
277 | DeleteDuplicates[
278 | Join[$ContextPath, $PackageContexts]
279 | ];
280 | CheckAbort[
281 | With[{res = expr},
282 | EndPackage[];
283 | res
284 | ],
285 | EndPackage[]
286 | ]
287 | ]
288 | ];
289 | PackageExecute ~ SetAttributes ~ HoldFirst
290 |
291 |
292 | (* ::Subsubsection::Closed:: *)
293 | (*PackagePullDeclarations*)
294 |
295 |
296 | PackagePullDeclarationsAction // Clear
297 | PackagePullDeclarationsAction[
298 | Hold[
299 | _Begin | _BeginPackage |
300 | CompoundExpression[_Begin | _BeginPackage, ___]
301 | ]
302 | ] :=
303 | Throw[Begin];
304 | PackagePullDeclarationsAction[
305 | p :
306 | Hold[
307 | _PackageFEHiddenBlock | _PackageScopeBlock |
308 | CompoundExpression[
309 | _PackageFEHiddenBlock | _PackageScopeBlock,
310 | ___]
311 | ]
312 | ] /; TrueQ[$AllowPackageRecoloring] :=
313 | (
314 | ReleaseHold[p];
315 | Sow[p];
316 | );
317 | PackagePullDeclarationsAction[e : Except[Hold[Expression]]] :=
318 | Sow@e;
319 |
320 |
321 | PackagePullDeclarations[pkgFile_] :=
322 | pkgFile ->
323 | Cases[
324 | Reap[
325 | With[{f = OpenRead[pkgFile]},
326 | Catch@
327 | Do[
328 | If[
329 | Length[
330 | ReadList[
331 | f,
332 | PackagePullDeclarationsAction@Hold[Expression],
333 | 1
334 | ]
335 | ] === 0,
336 | Throw[EndOfFile]
337 | ],
338 | Infinity
339 | ];
340 | Close[f]
341 | ]
342 | ][[2, 1]],
343 | s_Symbol?(
344 | Function[Null,
345 | Quiet[Context[#] === $Context],
346 | HoldAllComplete
347 | ]
348 | ) :>
349 | HoldPattern[s],
350 | Infinity
351 | ]
352 |
353 |
354 | (* ::Subsubsection::Closed:: *)
355 | (*PackageLoadPackage*)
356 |
357 |
358 | PackageLoadPackage[heldSym_, context_, pkgFile_ -> syms_] :=
359 | Block[{
360 | $loadingChain =
361 | If[ListQ@$loadingChain, $loadingChain, {}],
362 | $inLoad = TrueQ[$inLoad],
363 | $ContextPath = $ContextPath
364 | },
365 | If[!MemberQ[$loadingChain, pkgFile],
366 | With[{$$inLoad = $inLoad},
367 | $inLoad = True;
368 | If[$AllowPackageRecoloring,
369 | Internal`SymbolList[False]
370 | ];
371 | Replace[Thread[syms, HoldPattern],
372 | Verbatim[HoldPattern][{s__}] :> Clear[s]
373 | ];
374 | If[Not@MemberQ[$ContextPath, context],
375 | $ContextPath = Prepend[$ContextPath, context];
376 | ];
377 | Block[{PackageFEHiddenBlock = Null},
378 | PackageAppGet[context, pkgFile];
379 | ];
380 | Unprotect[$LoadedPackages];
381 | AppendTo[$LoadedPackages, pkgFile];
382 | Protect[$LoadedPackages];
383 | If[!$$inLoad && $AllowPackageRecoloring,
384 | Internal`SymbolList[True]
385 | ];
386 | ReleaseHold[heldSym]
387 | ]
388 | ]
389 | ];
390 |
391 |
392 | (* ::Subsubsection::Closed:: *)
393 | (*PackageDeclarePackage*)
394 |
395 |
396 | PackageDeclarePackage[pkgFile_ -> syms_] :=
397 | With[{c = $Context},
398 | $DeclaredPackages[pkgFile] = syms;
399 | $PackageFileContexts[pkgFile] = c;
400 | Map[
401 | If[True,
402 | # := PackageLoadPackage[#, c, pkgFile -> syms]
403 | ]&,
404 | syms
405 | ]
406 | ];
407 |
408 |
409 | (* ::Subsubsection::Closed:: *)
410 | (*PackageLoadDeclare*)
411 |
412 |
413 | PackageLoadDeclare[pkgFile_String] :=
414 | If[!MemberQ[$LoadedPackages, pkgFile],
415 | If[!KeyMemberQ[$DeclaredPackages, pkgFile],
416 | PackageDeclarePackage@
417 | PackagePullDeclarations[pkgFile]
418 | ],
419 | PackageAppGet[pkgFile]
420 | ];
421 |
422 |
423 | (* ::Subsubsection::Closed:: *)
424 | (*PackageAppLoad*)
425 |
426 |
427 | BilibiliLink["Load", args___] :=
428 | PackageAppLoad[args]
429 |
430 |
431 | packageAppLoad[dir_, listing_] :=
432 | With[
433 | {
434 | fileNames =
435 | Select[
436 | FileNames["*", dir],
437 | DirectoryQ@# || MatchQ[FileExtension[#], "m" | "wl"]&
438 | ]
439 | },
440 | Replace[
441 | Select[fileNames,
442 | StringMatchQ[
443 | ToLowerCase@FileNameTake[#],
444 | "__pre__." ~~ ("m" | "wl")
445 | ]&
446 | ],
447 | {f_} :> Get[f]
448 | ];
449 | PackageAppLoad[
450 | $PackageListing[listing] =
451 | Select[fileNames, StringFreeQ["__"]@*FileBaseName]
452 | ];
453 | Replace[
454 | Select[fileNames,
455 | StringMatchQ[
456 | ToLowerCase@FileNameTake[#],
457 | "__Post__." ~~ ("m" | "wl")
458 | ]&
459 | ],
460 | {f_} :> Get[f]
461 | ];
462 | ];
463 |
464 |
465 | PackageAppLoad[dir_String?DirectoryQ] :=
466 | If[StringMatchQ[FileBaseName@dir, (WordCharacter | "$")..],
467 | Begin["`" <> FileBaseName[dir] <> "`"];
468 | AppendTo[$PackageContexts, $Context];
469 | packageAppLoad[dir, FileNameDrop[dir, FileNameDepth[$PackageDirectory] + 1]];
470 | End[];
471 | ];
472 | PackageAppLoad[file_String?FileExistsQ] :=
473 | PackageLoadDeclare[file];
474 | PackageAppLoad[] :=
475 | PackageExecute@
476 | packageAppLoad[FileNameJoin@{$PackageDirectory, "Packages"}, $PackageName];
477 | PackageAppLoad ~ SetAttributes ~ Listable;
478 |
479 |
480 | (* ::Subsubsection::Closed:: *)
481 | (*PackageAppGet*)
482 |
483 |
484 | BilibiliLink["Get", f__] :=
485 | PackageAppGet[f];
486 | PackageAppGet[f_] :=
487 | PackageExecute@
488 | With[{fBase =
489 | If[FileExistsQ@f,
490 | f,
491 | PackageFilePath["Packages", f <> ".m"]
492 | ]
493 | },
494 | With[{cont =
495 | Most@
496 | FileNameSplit[
497 | FileNameDrop[fBase, FileNameDepth[PackageFilePath["Packages"]]]
498 | ]},
499 | If[Length[cont] > 0,
500 | Begin[StringRiffle[Append[""]@Prepend[""]@cont, "`"]];
501 | (End[];#)&@Get[fBase],
502 | Get[fBase]
503 | ]
504 | ]
505 | ];
506 | PackageAppGet[c_, f_] :=
507 | PackageExecute[
508 | Begin[c];
509 | (End[];#)&@
510 | If[FileExistsQ@f,
511 | Get@f;,
512 | Get@PackageFilePath["Packages", f <> ".m"]
513 | ]
514 | ];
515 |
516 |
517 | (* ::Subsubsection::Closed:: *)
518 | (*PackageAppNeeds*)
519 |
520 |
521 | BilibiliLink["Needs", f___] :=
522 | PackageAppNeeds[f];
523 |
524 |
525 | PackageAppNeeds[pkgFile_String?FileExistsQ] :=
526 | If[!MemberQ[$LoadedPackages, pkgFile],
527 | If[KeyMemberQ[$DeclaredPackages, pkgFile],
528 | PackageLoadDeclare[pkgFile],
529 | Do[PackageLoadDeclare[pkgFile], 2]
530 | ];
531 | ];
532 |
533 |
534 | PackageAppNeeds[pkg_String] :=
535 | If[FileExistsQ@PackageFilePath["Packages", pkg <> ".m"],
536 | PackageAppNeeds[PackageFilePath["Packages", pkg <> ".m"]],
537 | $Failed
538 | ];
539 |
540 |
541 | (* ::Subsubsection::Closed:: *)
542 | (*PackageScopeBlock*)
543 |
544 |
545 | $PackageScopeBlockEvalExpr = TrueQ[$PackageScopeBlockEvalExpr];
546 | PackageScopeBlock[
547 | e_,
548 | scope : _String?(StringFreeQ["`"]) : "Package",
549 | context : _String?(StringEndsQ["`"]) : "`PackageScope`"
550 | ] /; TrueQ[$AllowPackageRescoping] :=
551 | With[{
552 | newcont =
553 | If[StringStartsQ[context, "`"],
554 | "BilibiliLink" <> context <> scope <> "`",
555 | context <> scope <> "`"
556 | ],
557 | res = If[$PackageScopeBlockEvalExpr, e]
558 | },
559 | If[!MemberQ[$PackageContexts, newcont],
560 | Unprotect[$PackageContexts];
561 | AppendTo[$PackageContexts, newcont];
562 | ];
563 | Replace[
564 | Thread[
565 | Cases[
566 | HoldComplete[e],
567 | sym_Symbol?(
568 | Function[Null,
569 | MemberQ[$PackageContexts, Quiet[Context[#]]],
570 | HoldAllComplete
571 | ]
572 | ) :>
573 | HoldComplete[sym],
574 | \[Infinity]
575 | ],
576 | HoldComplete
577 | ],
578 | HoldComplete[{s__}] :>
579 | If[!$PackageDeclared && ListQ@$PackageScopedSymbols,
580 | $PackageScopedSymbols =
581 | {
582 | $PackageScopedSymbols,
583 | newcont ->
584 | HoldComplete[s]
585 | },
586 | Block[{$AllowPackageRecoloring = True},
587 | PackageFERehideSymbols[s]
588 | ];
589 | Map[
590 | Function[Null,
591 | Quiet[
592 | Check[
593 | Set[Context[#], newcont],
594 | Remove[#],
595 | Context::cxdup
596 | ],
597 | Context::cxdup
598 | ],
599 | HoldAllComplete
600 | ],
601 | HoldComplete[s]
602 | ] // ReleaseHold;
603 | ]
604 | ];
605 | res
606 | ];
607 | PackageScopeBlock[e_, scope_String : "Package"] /; Not@TrueQ[$AllowPackageRescoping] :=
608 | If[$PackageScopeBlockEvalExpr, e];
609 | PackageScopeBlock ~ SetAttributes ~ HoldFirst;
610 |
611 |
612 | (* ::Subsubsection::Closed:: *)
613 | (*PackageDecontext*)
614 |
615 |
616 | PackageDecontext[
617 | pkgFile_String?(KeyMemberQ[$DeclaredPackages, #]&),
618 | scope : _String?(StringFreeQ["`"]) : "Package",
619 | context : _String?(StringEndsQ["`"]) : "`PackageScope`"
620 | ] /; TrueQ[$AllowPackageRescoping] :=
621 | With[{
622 | names = $DeclaredPackages[pkgFile],
623 | ctx =
624 | If[StringStartsQ[context, "`"],
625 | "BilibiliLink" <> context <> scope <> "`",
626 | context <> scope <> "`"
627 | ]
628 | },
629 | Replace[names,
630 | Verbatim[HoldPattern][s_] :>
631 | Set[Context[s], ctx],
632 | 1
633 | ]
634 | ];
635 |
636 |
637 | (* ::Subsubsection::Closed:: *)
638 | (*PackageRecontext*)
639 |
640 |
641 | PackageRecontext[
642 | pkgFile_String?(KeyMemberQ[$DeclaredPackages, #]&)
643 | ] /; TrueQ[$AllowPackageRescoping] :=
644 | With[{
645 | names = $DeclaredPackages[pkgFile],
646 | ctx = PackageFileContext[pkgFile]
647 | },
648 | Replace[names,
649 | Verbatim[HoldPattern][s_] :>
650 | Set[Context[s], ctx],
651 | 1
652 | ]
653 | ];
654 | (* ::Subsection:: *)
655 | (*Dependencies*)
656 |
657 |
658 | BilibiliLink::nodep = "Couldn't load dependency `` of type ``";
659 |
660 |
661 | (* ::Subsubsection::Closed:: *)
662 | (*PackageExtendContextPath*)
663 |
664 |
665 | PackageExtendContextPath[cp : {__String}] :=
666 | (
667 | Unprotect[$PackageContextPath];
668 | $PackageContextPath =
669 | DeleteCases[
670 | DeleteDuplicates@
671 | Join[$PackageContextPath, cp],
672 | "System`" | "Global`"
673 | ];
674 | (* Should I protect it again? *)
675 | )
676 |
677 |
678 | (* ::Subsubsection::Closed:: *)
679 | (*PackageInstallPackageDependency*)
680 |
681 |
682 | Options[PackageInstallPackageDependency] =
683 | {
684 | "Permanent" -> False
685 | };
686 | PackageInstallPackageDependency[dep_String, ops : OptionsPattern[]] :=
687 | Block[{retcode, site, path, file, tmp},
688 | path =
689 | StringSplit[StringTrim[dep, "`"] <> If[FileExtension[dep] == "", ".m", ""], "`"];
690 | site =
691 | Replace[OptionValue["Site"],
692 | {
693 | s_String?(
694 | URLParse[#, "Domain"] === "github.com"&
695 | ) :>
696 | URLBuild@
697 | <|
698 | "Scheme" -> "http",
699 | "Domain" -> "raw.githubusercontent.com",
700 | "Path" ->
701 | Function[If[Length[#] == 2, Append[#, "master"], #]]@
702 | DeleteCases[""]@URLParse[s, "Path"]
703 | |>,
704 | _ ->
705 | "http://raw.githubusercontent.com/paclets/PackageServer/master/Listing"
706 | }
707 | ];
708 | file =
709 | If[TrueQ@OptionValue["Permanent"],
710 | FileNameJoin@{$UserBaseDirectory, "Applications", Last@path},
711 | FileNameJoin@{$TemporaryDirectory, "Applications", Last@path}
712 | ];
713 | tmp = CreateFile[];
714 | Monitor[
715 | retcode = URLDownload[URLBuild[Prepend[site], path], tmp, "StatusCode"],
716 | Internal`LoadingPanel[
717 | TemplateApply[
718 | "Loading package `` from site ``",
719 | {URLBuild@path, site}
720 | ]
721 | ]
722 | ];
723 | If[retcode < 300,
724 | CopyFile[tmp, file,
725 | OverwriteTarget -> Not@TrueQ@OptionValue["Permanent"]
726 | ];
727 | DeleteFile[tmp];
728 | file,
729 | Message[BilibiliLink::nodep, dep, "Package"];
730 | DeleteFile[tmp];
731 | $Failed
732 | ]
733 | ];
734 |
735 |
736 | (* ::Subsubsection::Closed:: *)
737 | (*PackageLoadPackageDependency*)
738 |
739 |
740 | Options[PackageLoadPackageDependency] =
741 | Options[PackageInstallPackageDependency];
742 | PackageLoadPackageDependency[dep_String, ops : OptionsPattern[]] :=
743 | Internal`WithLocalSettings[
744 | BeginPackage[dep];,
745 | If[Quiet@Check[Needs[dep], $Failed] === $Failed &&
746 | Quiet@Check[
747 | Get[FileNameJoin @@
748 | StringSplit[
749 | StringTrim[dep, "`"] <> If[FileExtension[dep] == "", ".m", ""],
750 | "`"
751 | ]
752 | ],
753 | $Failed] === $Failed,
754 | Replace[PackageInstallPacletDependency[dep, ops],
755 | f : _String | _File :> Get[f]
756 | ]
757 | ];
758 | PackageExtendContextPath@
759 | Select[$Packages, StringStartsQ[dep]];,
760 | EndPackage[];
761 | ]
762 |
763 |
764 | (* ::Subsubsection::Closed:: *)
765 | (*PackageInstallPacletDependency*)
766 |
767 |
768 | Options[PackageInstallPacletDependency] =
769 | Options[PacletInstall];
770 | PackageInstallPacletDependency[dep_String, ops : OptionsPattern[]] :=
771 | Check[
772 | Block[{site, pac},
773 | pac =
774 | StringTrim[dep, "`"];
775 | site =
776 | Replace[OptionValue["Site"],
777 | {
778 | s_String?(
779 | URLParse[#, "Domain"] === "github.com"&
780 | ) :>
781 | URLBuild@
782 | <|
783 | "Scheme" -> "http",
784 | "Domain" -> "raw.githubusercontent.com",
785 | "Path" ->
786 | Function[If[Length[#] == 2, Append[#, "master"], #]]@
787 | DeleteCases[""]@URLParse[s, "Path"]
788 | |>,
789 | None ->
790 | Automatic,
791 | _ ->
792 | "http://raw.githubusercontent.com/paclets/PacletServer/master"
793 | }
794 | ];
795 | Monitor[
796 | PacletInstall[
797 | pac,
798 | "Site" -> site,
799 | ops
800 | ],
801 | Internal`LoadingPanel[
802 | TemplateApply[
803 | "Loading paclet `` from site ``",
804 | {pac, site}
805 | ]
806 | ]
807 | ]
808 | ],
809 | Message[BilibiliLink::nodep, dep, "Paclet"];
810 | $Failed
811 | ]
812 |
813 |
814 | (* ::Subsubsection::Closed:: *)
815 | (*PackageLoadPacletDependency*)
816 |
817 |
818 | Options[PackageLoadPacletDependency] =
819 | Options[PackageInstallPacletDependency];
820 | PackageLoadPacletDependency[dep_String?StringEndsQ["`"], ops : OptionsPattern[]] :=
821 | Internal`WithLocalSettings[
822 | BeginPackage[dep];,
823 | Quiet@
824 | If[Check[Needs[dep], $Failed] === $Failed,
825 | Replace[PackageInstallPacletDependency[dep, ops],
826 | _PacletManager`Paclet :> Needs[dep]
827 | ]
828 | ];
829 | PackageExtendContextPath@
830 | Select[$Packages, StringStartsQ[dep]];,
831 | EndPackage[];
832 | ]
833 |
834 |
835 | (* ::Subsubsection::Closed:: *)
836 | (*PackageLoadResourceDependency*)
837 |
838 |
839 | (* ::Text:: *)
840 | (*Nothing I've implemented yet, but could be very useful for installing resources for a paclet*)
841 | (* ::Subsection:: *)
842 | (*Exceptions*)
843 |
844 |
845 | (* ::Subsubsection::Closed:: *)
846 | (*PackageThrow*)
847 |
848 |
849 | PackageThrow[value_, tag : _String : "Failure"] :=
850 | Throw[value, $PackageName <> tag];
851 |
852 |
853 | (* ::Subsubsection::Closed:: *)
854 | (*PackageCatch*)
855 |
856 |
857 | $PackageCatchCallback = (#&);
858 |
859 |
860 | PackageCatch[expr_, tag : _String : "Failure", callback_ : Automatic] :=
861 | Catch[expr, $PackageName <> tag,
862 | Replace[callback, Automatic :> $PackageCatchCallback]
863 | ];
864 | PackageCatch ~ SetAttributes ~ HoldFirst
865 |
866 |
867 | (* ::Subsubsection:: *)
868 | (*PackageMessage*)
869 |
870 |
871 | $PackageErrorMessage =
872 | "BilibiliLink encountered exception ``";
873 |
874 |
875 | Options[PackageMessage] =
876 | {
877 | "MessageParameters" :> {}
878 | };
879 | PackageMessage[
880 | msg_MessageName,
881 | body_String,
882 | ops : OptionsPattern[]
883 | ] :=
884 | (
885 | Set[msg, body];
886 | Message[msg, Sequence @@ OptionValue["MessageParameters"]]
887 | );
888 | PackageMessage[
889 | tag_?StringQ,
890 | body_String,
891 | ops : OptionsPattern[]
892 | ] :=
893 | PackageMessage[
894 | MessageName[BilibiliLink, tag],
895 | body,
896 | ops
897 | ];
898 | PackageMessage[
899 | tag_?StringQ
900 | ] :=
901 | PackageMessage[
902 | MessageName[BilibiliLink, tag],
903 | $PackageErrorMessage,
904 | "MessageParameters" -> {tag}
905 | ];
906 | PackageMessage ~ SetAttributes ~ HoldAll
907 |
908 |
909 | (* ::Subsubsection:: *)
910 | (*PackageCheck*)
911 |
912 |
913 | $PackageCheckMessage =
914 | "Check caught exceptions ``";
915 |
916 |
917 | $PackageCheckCallback =
918 | Function[
919 | PackageRaiseException[
920 | "Check",
921 | $PackageCheckMessage,
922 | "MessageParameters" -> Thread[HoldForm[$MessageList]]
923 | ]
924 | ];
925 |
926 |
927 | PackageCheck[
928 | expr_,
929 | failexpr_ : Automatic,
930 | msg : {___String} : {}
931 | ] :=
932 | Replace[
933 | Thread[Map[Hold[MessageName[BilibiliLink, #]]&, msg], Hold],
934 | {
935 | {} :>
936 | Check[expr,
937 | Replace[failexpr, {Automatic :> $PackageCheckCallback[]}]
938 | ],
939 | Hold[msgs_] :>
940 | Check[expr,
941 | Replace[failexpr, {Automatic :> $PackageCheckCallback[]}],
942 | msgs
943 | ],
944 | _ :>
945 | Replace[failexpr, {Automatic :> $PackageCheckCallback[]}]
946 | }
947 | ];
948 | PackageCheck ~ SetAttributes ~ HoldAll;
949 |
950 |
951 | (* ::Subsubsection:: *)
952 | (*PackageFailure*)
953 |
954 |
955 | Options[PackageFailure] =
956 | Join[
957 | Options[PackageMessage],
958 | {
959 | "FailureTag" -> Automatic
960 | }
961 | ];
962 | PackageFailure[
963 | msg_MessageName,
964 | body_?StringQ,
965 | ops : OptionsPattern[]
966 | ] :=
967 | Replace[
968 | OptionValue[Automatic, Automatic, "MessageParameters", Hold],
969 | Hold[params_] :>
970 | Failure[
971 | $PackageName <>
972 | Replace[OptionValue["FailureTag"],
973 | Automatic :> Hold[msg][[1, 2]]
974 | ],
975 | <|
976 | "MessageTemplate" :>
977 | msg,
978 | "MessageParameters" :>
979 | params
980 | |>
981 | ]
982 | ];
983 | PackageFailure[
984 | tag : _?StringQ : "Exception",
985 | body_?StringQ,
986 | ops : OptionsPattern[]
987 | ] :=
988 | (
989 | Set[MessageName[BilibiliLink, tag], body];
990 | PackageFailure[
991 | MessageName[BilibiliLink, tag],
992 | body,
993 | ops
994 | ]
995 | );
996 | PackageFailure ~ SetAttributes ~ HoldFirst
997 |
998 |
999 | (* ::Subsubsection:: *)
1000 | (*PackageRaiseException*)
1001 |
1002 |
1003 | Options[PackageRaiseException] =
1004 | Options[PackageFailure]
1005 | PackageRaiseException[
1006 | msg_MessageName,
1007 | body_?StringQ,
1008 | ops : OptionsPattern[]
1009 | ] :=
1010 | (
1011 | PackageMessage[msg, body,
1012 | FilterRules[{ops}, Options[PackageMessage]]
1013 | ];
1014 | PackageThrow[
1015 | PackageFailure[msg, body, ops]
1016 | ]
1017 | );
1018 | PackageRaiseException[
1019 | tag_?StringQ,
1020 | body_String,
1021 | ops : OptionsPattern[]
1022 | ] :=
1023 | PackageRaiseException[
1024 | MessageName[BilibiliLink, tag],
1025 | body,
1026 | ops
1027 | ];
1028 | PackageRaiseException[tag_?StringQ] :=
1029 | PackageRaiseException[
1030 | tag,
1031 | $PackageErrorMessage,
1032 | "MessageParameters" -> {tag}
1033 | ];
1034 | PackageRaiseException ~ SetAttributes ~ HoldFirst
1035 | (* ::Subsection:: *)
1036 | (*Autocompletion*)
1037 |
1038 |
1039 | (* ::Subsubsection::Closed:: *)
1040 | (*Formats*)
1041 |
1042 |
1043 | $PackageAutoCompletionFormats =
1044 | Alternatives @@ Join @@ {
1045 | Range[0, 9],
1046 | {
1047 | _String?(FileExtension[#] === "trie"&),
1048 | {
1049 | _String | (Alternatives @@ Range[0, 9]) | {__String},
1050 | (("URI" | "DependsOnArgument") -> _)...
1051 | },
1052 | {
1053 | _String | (Alternatives @@ Range[0, 9]) | {__String},
1054 | (("URI" | "DependsOnArgument") -> _)...,
1055 | (_String | (Alternatives @@ Range[0, 9]) | {__String})
1056 | },
1057 | {
1058 | __String
1059 | }
1060 | },
1061 | {
1062 | "codingNoteFontCom",
1063 | "ConvertersPath",
1064 | "ExternalDataCharacterEncoding",
1065 | "MenuListCellTags",
1066 | "MenuListConvertFormatTypes",
1067 | "MenuListDisplayAsFormatTypes",
1068 | "MenuListFonts",
1069 | "MenuListGlobalEvaluators",
1070 | "MenuListHelpWindows",
1071 | "MenuListNotebookEvaluators",
1072 | "MenuListNotebooksMenu",
1073 | "MenuListPackageWindows",
1074 | "MenuListPalettesMenu",
1075 | "MenuListPaletteWindows",
1076 | "MenuListPlayerWindows",
1077 | "MenuListPrintingStyleEnvironments",
1078 | "MenuListQuitEvaluators",
1079 | "MenuListScreenStyleEnvironments",
1080 | "MenuListStartEvaluators",
1081 | "MenuListStyleDefinitions",
1082 | "MenuListStyles",
1083 | "MenuListStylesheetWindows",
1084 | "MenuListTextWindows",
1085 | "MenuListWindows",
1086 | "PrintingStyleEnvironment",
1087 | "ScreenStyleEnvironment",
1088 | "Style"
1089 | }
1090 | };
1091 |
1092 |
1093 | (* ::Subsubsection::Closed:: *)
1094 | (*AddAutocompletions Base*)
1095 |
1096 |
1097 | PackageAddAutocompletions[pats : {(_String -> {$PackageAutoCompletionFormats..})..}] /;
1098 | TrueQ[$PackageAllowAutocompletions] :=
1099 | If[$Notebooks &&
1100 | Internal`CachedSystemInformation["FrontEnd", "VersionNumber"] > 10.0,
1101 | FrontEndExecute@FrontEnd`Value@
1102 | Map[
1103 | FEPrivate`AddSpecialArgCompletion[#]&,
1104 | pats
1105 | ],
1106 | $Failed
1107 | ];
1108 | PackageAddAutocompletions[pat : (_String -> {$PackageAutoCompletionFormats..})] /;
1109 | TrueQ[$PackageAllowAutocompletions] :=
1110 | PackageAddAutocompletions[{pat}];
1111 |
1112 |
1113 | (* ::Subsubsection::Closed:: *)
1114 | (*AddAutocompletions Helpers*)
1115 |
1116 |
1117 | $PackageAutocompletionAliases =
1118 | {
1119 | "None" | None | Normal -> 0,
1120 | "AbsoluteFileName" | AbsoluteFileName -> 2,
1121 | "FileName" | File | FileName -> 3,
1122 | "Color" | RGBColor | Hue | XYZColor -> 4,
1123 | "Package" | Package -> 7,
1124 | "Directory" | Directory -> 8,
1125 | "Interpreter" | Interpreter -> 9,
1126 | "Notebook" | Notebook -> "MenuListNotebooksMenu",
1127 | "StyleSheet" -> "MenuListStylesheetMenu",
1128 | "Palette" -> "MenuListPalettesMenu",
1129 | "Evaluator" | Evaluator -> "MenuListGlobalEvaluators",
1130 | "FontFamily" | FontFamily -> "MenuListFonts",
1131 | "CellTag" | CellTags -> "MenuListCellTags",
1132 | "FormatType" | FormatType -> "MenuListDisplayAsFormatTypes",
1133 | "ConvertFormatType" -> "MenuListConvertFormatTypes",
1134 | "DisplayAsFormatType" -> "MenuListDisplayAsFormatTypes",
1135 | "GlobalEvaluator" -> "MenuListGlobalEvaluators",
1136 | "HelpWindow" -> "MenuListHelpWindows",
1137 | "NotebookEvaluator" -> "MenuListNotebookEvaluators",
1138 | "PrintingStyleEnvironment" | PrintingStyleEnvironment ->
1139 | "PrintingStyleEnvironment",
1140 | "ScreenStyleEnvironment" | ScreenStyleEnvironment ->
1141 | ScreenStyleEnvironment,
1142 | "QuitEvaluator" -> "MenuListQuitEvaluators",
1143 | "StartEvaluator" -> "MenuListStartEvaluators",
1144 | "StyleDefinitions" | StyleDefinitions ->
1145 | "MenuListStyleDefinitions",
1146 | "CharacterEncoding" | CharacterEncoding |
1147 | ExternalDataCharacterEncoding ->
1148 | "ExternalDataCharacterEncoding",
1149 | "Style" | Style -> "Style",
1150 | "Window" -> "MenuListWindows"
1151 | };
1152 |
1153 |
1154 | (* ::Subsubsection:: *)
1155 | (*AddAutocompletions Convenience*)
1156 |
1157 |
1158 | $PackageAutocompletionTable = {
1159 | f : $PackageAutoCompletionFormats :> f,
1160 | Sequence @@ $PackageAutocompletionAliases,
1161 | s_String :> {s}
1162 | };
1163 |
1164 |
1165 | PackageAddAutocompletions[o : {__Rule}] /; (
1166 | TrueQ[$PackageAllowAutocompletions] && !TrueQ@$recursionProtect
1167 | ) :=
1168 | Block[{$recursionProtect = True},
1169 | Replace[
1170 | PackageAddAutocompletions@
1171 | Replace[o,
1172 | (s_ -> v_) :>
1173 | (Replace[s, _Symbol :> SymbolName[s]] ->
1174 | Replace[
1175 | Flatten[{v}, 1],
1176 | $PackageAutocompletionTable,
1177 | 1
1178 | ]),
1179 | 1
1180 | ],
1181 | _PackageAddAutocompletions -> $Failed
1182 | ]
1183 | ];
1184 | PackageAddAutocompletions[s : Except[_List], v_] /; TrueQ[$PackageAllowAutocompletions] :=
1185 | PackageAddAutocompletions[{s -> v}];
1186 | PackageAddAutocompletions[l_, v_] /; TrueQ[$PackageAllowAutocompletions] :=
1187 | PackageAddAutocompletions@
1188 | Flatten@{
1189 | Quiet@
1190 | Check[
1191 | Thread[l -> v],
1192 | Map[l -> #&, v]
1193 | ]
1194 | };
1195 |
1196 |
1197 | (*PackageAddAutocompletions[PackageAddAutocompletions,
1198 | {None,
1199 | Join[
1200 | Replace[Keys[$PackageAutocompletionAliases],
1201 | Verbatim[Alternatives][s_,___]:>s,
1202 | 1
1203 | ],
1204 | {FileName,AbsoluteFileName}/.$PackageAutocompletionAliases
1205 | ]
1206 | }
1207 | ]*)
1208 |
1209 |
1210 | (* ::Subsubsection::Closed:: *)
1211 | (* PackageSetAutocompletionData *)
1212 |
1213 |
1214 | PackageSetAutocompletionData[] :=
1215 | If[DirectoryQ@
1216 | FileNameJoin@{
1217 | $PackageDirectory,
1218 | "Resources",
1219 | "FunctionalFrequency"
1220 | },
1221 | CurrentValue[
1222 | $FrontEndSession,
1223 | {PrivatePaths, "AutoCompletionData"}
1224 | ] =
1225 | DeleteDuplicates@
1226 | Append[
1227 | CurrentValue[
1228 | $FrontEndSession,
1229 | {PrivatePaths, "AutoCompletionData"}
1230 | ],
1231 | FileNameJoin@{
1232 | $PackageDirectory,
1233 | "Resources",
1234 | "FunctionalFrequency"
1235 | }
1236 | ]
1237 | ];
1238 | (* ::Subsection:: *)
1239 | (*FrontEnd*)
1240 |
1241 |
1242 | (* ::Subsubsection::Closed:: *)
1243 | (*PackageFEInstallStylesheets *)
1244 |
1245 |
1246 | PackageFEInstallStylesheets[] :=
1247 | With[{
1248 | base =
1249 | FileNameJoin@{
1250 | $PackageDirectory,
1251 | "FrontEnd",
1252 | "StyleSheets",
1253 | $PackageName
1254 | },
1255 | target =
1256 | FileNameJoin@{
1257 | $UserBaseDirectory,
1258 | "SystemFiles",
1259 | "FrontEnd",
1260 | "StyleSheets",
1261 | $PackageName}
1262 | },
1263 | If[DirectoryQ@base,
1264 | Do[
1265 | Quiet@
1266 | CreateFile[
1267 | FileNameJoin@{
1268 | target,
1269 | FileNameDrop[f, FileNameDepth[base]]
1270 | },
1271 | CreateIntermediateDirectories -> True
1272 | ];
1273 | CopyFile[f,
1274 | FileNameJoin@{
1275 | target,
1276 | FileNameDrop[f, FileNameDepth[base]]
1277 | },
1278 | OverwriteTarget -> True],
1279 | {f, FileNames["*.nb", base, \[Infinity]]}
1280 | ]
1281 | ]
1282 | ];
1283 |
1284 |
1285 | (* ::Subsubsection::Closed:: *)
1286 | (*PackageFEInstallPalettes *)
1287 |
1288 |
1289 | PackageFEInstallPalettes[] :=
1290 | With[{
1291 | base =
1292 | FileNameJoin@{
1293 | $PackageDirectory,
1294 | "FrontEnd",
1295 | "Palettes",
1296 | $PackageName
1297 | },
1298 | target =
1299 | FileNameJoin@{
1300 | $UserBaseDirectory,
1301 | "SystemFiles",
1302 | "FrontEnd",
1303 | "Palettes",
1304 | $PackageName}
1305 | },
1306 | If[DirectoryQ@base,
1307 | Do[
1308 | Quiet@
1309 | CreateFile[
1310 | FileNameJoin@{
1311 | target,
1312 | FileNameDrop[f, FileNameDepth[base]]
1313 | },
1314 | CreateIntermediateDirectories -> True
1315 | ];
1316 | CopyFile[f,
1317 | FileNameJoin@{
1318 | target,
1319 | FileNameDrop[f, FileNameDepth[base]]
1320 | },
1321 | OverwriteTarget -> True],
1322 | {f, FileNames["*.nb", base, \[Infinity]]}
1323 | ]
1324 | ]
1325 | ];
1326 |
1327 |
1328 | (* ::Subsubsection::Closed:: *)
1329 | (*PackageFEHiddenBlock*)
1330 |
1331 |
1332 | $PackageFEHideExprSymbols = TrueQ[$PackageFEHideExprSymbols];
1333 | $PackageFEHideEvalExpr = TrueQ[$PackageFEHideEvalExpr];
1334 | PackageFEHiddenBlock[expr_,
1335 | hide : True | False | Automatic : Automatic,
1336 | eval : True | False | Automatic : Automatic
1337 | ] /; TrueQ[$AllowPackageRecoloring] :=
1338 | If[!$PackageDeclared && ListQ@$PackageFEHiddenSymbols,
1339 | With[{
1340 | s =
1341 | Cases[
1342 | HoldComplete[expr],
1343 | sym_Symbol?(
1344 | Function[Null,
1345 | MemberQ[$PackageContexts, Quiet[Context[#]]],
1346 | HoldAllComplete
1347 | ]
1348 | ) :>
1349 | HoldPattern[sym],
1350 | \[Infinity]
1351 | ]
1352 | },
1353 | $PackageFEHiddenSymbols =
1354 | {
1355 | $PackageFEHiddenSymbols,
1356 | s
1357 | }
1358 | ],
1359 | Block[{feBlockReturn},
1360 | Internal`SymbolList[False];
1361 | feBlockReturn = If[Replace[eval, Automatic :> $PackageFEHideEvalExpr], expr];
1362 | If[Replace[hide, Automatic :> $PackageFEHideExprSymbols],
1363 | With[{
1364 | s =
1365 | Cases[
1366 | HoldComplete[expr],
1367 | sym_Symbol?(
1368 | Function[Null,
1369 | MemberQ[$PackageContexts, Quiet[Context[#]]],
1370 | HoldAllComplete
1371 | ]
1372 | ) :>
1373 | HoldPattern[sym],
1374 | \[Infinity]
1375 | ]
1376 | },
1377 | Replace[Thread[s, HoldPattern],
1378 | Verbatim[HoldPattern][{sym__}] :>
1379 | PackageFERehideSymbols[sym]
1380 | ]
1381 | ]
1382 | ];
1383 | Internal`SymbolList[True];
1384 | feBlockReturn
1385 | ]
1386 | ];
1387 | PackageFEHiddenBlock[expr_,
1388 | hide : True | False | Automatic : Automatic,
1389 | eval : True | False | Automatic : Automatic
1390 | ] /; Not@TrueQ[$AllowPackageRecoloring] :=
1391 | If[eval, expr];
1392 | PackageFEHiddenBlock ~ SetAttributes ~ HoldFirst
1393 |
1394 |
1395 | (* ::Subsubsection::Closed:: *)
1396 | (*PackageFEUnhideSymbols*)
1397 |
1398 |
1399 | PackageFEUnhideSymbols[syms__Symbol,
1400 | cpath : {__String} | Automatic : Automatic,
1401 | mode : "Update" | "Set" : "Update"
1402 | ] /; TrueQ[$AllowPackageRecoloring] :=
1403 | With[{stuff =
1404 | Map[
1405 | Function[Null,
1406 | {Context@#, SymbolName@Unevaluated@#},
1407 | HoldAllComplete],
1408 | HoldComplete[syms]
1409 | ] // Apply[List]
1410 | },
1411 | KeyValueMap[
1412 | FrontEndExecute@
1413 | If[mode === "Update",
1414 | FrontEnd`UpdateKernelSymbolContexts,
1415 | FrontEnd`SetKernelSymbolContexts
1416 | ][
1417 | #,
1418 | Replace[cpath, Automatic -> $ContextPath],
1419 | {{#, {}, {}, #2, {}}}
1420 | ]&,
1421 | GroupBy[stuff, First -> Last]
1422 | ];
1423 | ];
1424 | PackageFEUnhideSymbols[names_String,
1425 | mode : "Update" | "Set" : "Update"] /; TrueQ[$AllowPackageRecoloring] :=
1426 | Replace[
1427 | Thread[ToExpression[Names@names, StandardForm, Hold], Hold],
1428 | Hold[{s__}] :> PackageFEUnhideSymbols[s, mode]
1429 | ];
1430 | PackageFEUnhideSymbols ~ SetAttributes ~ HoldAllComplete;
1431 |
1432 |
1433 | (* ::Subsubsection::Closed:: *)
1434 | (*PackageFERehideSymbols*)
1435 |
1436 |
1437 | PackageFERehideSymbols[syms__Symbol,
1438 | cpath : {__String} | Automatic : Automatic,
1439 | mode : "Update" | "Set" : "Update"] /; TrueQ[$AllowPackageRecoloring] :=
1440 | With[{stuff =
1441 | Map[
1442 | Function[Null,
1443 | {Context@#, SymbolName@Unevaluated@#},
1444 | HoldAllComplete],
1445 | HoldComplete[syms]
1446 | ] // Apply[List]
1447 | },
1448 | KeyValueMap[
1449 | FrontEndExecute@
1450 | If[mode === "Update",
1451 | FrontEnd`UpdateKernelSymbolContexts,
1452 | FrontEnd`SetKernelSymbolContexts
1453 | ][
1454 | #,
1455 | Replace[cpath,
1456 | Automatic -> $ContextPath
1457 | ],
1458 | {{#, {}, #2, {}, {}}}
1459 | ]&,
1460 | GroupBy[stuff, First -> Last]
1461 | ];
1462 | ];
1463 | PackageFERehideSymbols[names_String,
1464 | mode : "Update" | "Set" : "Update"] /; TrueQ[$AllowPackageRecoloring] :=
1465 | Replace[
1466 | Thread[ToExpression[Names@names, StandardForm, Hold], Hold],
1467 | Hold[{s__}] :> PackageFERehideSymbols[s, mode]
1468 | ];
1469 | PackageFERehideSymbols ~ SetAttributes ~ HoldAllComplete;
1470 |
1471 |
1472 | (* ::Subsubsection::Closed:: *)
1473 | (*PackageFEUnhidePackage*)
1474 |
1475 |
1476 | PackageFEUnhidePackage[
1477 | package_String?FileExistsQ,
1478 | a___
1479 | ] /; TrueQ[$AllowPackageRecoloring] :=
1480 | Replace[Thread[Lookup[$DeclaredPackages, package, {}], HoldPattern],
1481 | Verbatim[HoldPattern][{syms__}] :>
1482 | PackageFEUnhideSymbols[syms, a]
1483 | ];
1484 | PackageFEUnhidePackage[spec : _String | _List, a___] /; TrueQ[$AllowPackageRecoloring] :=
1485 | PackageFEUnhidePackage[PackageFilePath@Flatten@{"Packages", spec}, a];
1486 |
1487 |
1488 | (* ::Subsubsection::Closed:: *)
1489 | (*PackageFERehidePackage*)
1490 |
1491 |
1492 | PackageFERehidePackage[
1493 | package_String?FileExistsQ,
1494 | a___
1495 | ] /; TrueQ[$AllowPackageRecoloring] :=
1496 | Replace[Thread[Lookup[$DeclaredPackages, package, {}], HoldPattern],
1497 | Verbatim[HoldPattern][{syms__}] :>
1498 | PackageFERehideSymbols[syms, a]
1499 | ];
1500 | PackageFERehidePackage[spec : _String | _List, a___] /; TrueQ[$AllowPackageRecoloring] :=
1501 | PackageFERehidePackage[PackageFilePath@Flatten@{"Packages", spec}, a];
1502 |
1503 |
1504 | (* ::Subsection:: *)
1505 | (*Post-Processing*)
1506 |
1507 |
1508 | (* ::Subsubsection::Closed:: *)
1509 | (*PrepFileName*)
1510 |
1511 |
1512 | PackagePostProcessFileNamePrep[fn_] :=
1513 | Replace[
1514 | FileNameSplit@
1515 | FileNameDrop[fn,
1516 | FileNameDepth@
1517 | PackageFilePath["Packages"]
1518 | ], {
1519 | {f_} :>
1520 | f | fn | StringTrim[f, ".m" | ".wl"],
1521 | {p__, f_} :>
1522 | FileNameJoin@{p, f} | fn | {p, StringTrim[f, ".m" | ".wl"]}
1523 | }]
1524 |
1525 |
1526 | (* ::Subsubsection::Closed:: *)
1527 | (*PrepSpecs*)
1528 |
1529 |
1530 | PackagePostProcessPrepSpecs[] :=
1531 | (
1532 | Unprotect[
1533 | $PackagePreloadedPackages,
1534 | $PackageHiddenPackages,
1535 | $PackageHiddenContexts,
1536 | $PackageExposedContexts,
1537 | $PackageDecontextedPackages
1538 | ];
1539 | If[FileExistsQ@PackageFilePath["Config", "LoadInfo.m"],
1540 | Replace[
1541 | $PackageLoadSpecs,
1542 | specs : {__Rule} | _Association :>
1543 | CompoundExpression[
1544 | $PackagePreloadedPackages =
1545 | Replace[
1546 | Lookup[specs, "PreLoad"],
1547 | Except[{__String}] -> {}
1548 | ],
1549 | $PackageHiddenPackages =
1550 | Replace[
1551 | Lookup[specs, "FEHidden"],
1552 | Except[{__String}] -> {}
1553 | ],
1554 | $PackageDecontextedPackages =
1555 | Replace[
1556 | Lookup[specs, "PackageScope"],
1557 | Except[{__String}] -> {}
1558 | ],
1559 | $PackageExposedContexts =
1560 | Replace[
1561 | Lookup[specs, "ExposedContexts"],
1562 | Except[{__String}] -> {}
1563 | ]
1564 | ]
1565 | ]
1566 | ]
1567 | );
1568 |
1569 |
1570 | (* ::Subsubsection::Closed:: *)
1571 | (*ExposePackages*)
1572 |
1573 |
1574 | PackagePostProcessExposePackages[] /; TrueQ[$AllowPackageRecoloring] :=
1575 | (
1576 | PackageAppGet /@
1577 | $PackagePreloadedPackages;
1578 | With[{
1579 | syms =
1580 | If[
1581 | !MemberQ[$PackageHiddenPackages,
1582 | PackagePostProcessFileNamePrep[#]
1583 | ],
1584 | $DeclaredPackages[#],
1585 | {}
1586 | ]& /@ Keys@$DeclaredPackages // Flatten
1587 | },
1588 | Replace[
1589 | Thread[
1590 | If[ListQ@$PackageFEHiddenSymbols,
1591 | DeleteCases[syms,
1592 | Alternatives @@
1593 | (Verbatim[HoldPattern] /@ Flatten@$PackageFEHiddenSymbols)
1594 | ],
1595 | syms
1596 | ],
1597 | HoldPattern],
1598 | Verbatim[HoldPattern][{s__}] :>
1599 | PackageFEUnhideSymbols[s]
1600 | ]
1601 | ]
1602 | )
1603 |
1604 |
1605 |
1606 |
1607 | (* ::Subsubsection::Closed:: *)
1608 | (*Rehide Packages*)
1609 |
1610 |
1611 | PackagePostProcessRehidePackages[] /; TrueQ[$AllowPackageRecoloring] :=
1612 | If[
1613 | MemberQ[$PackageHiddenPackages,
1614 | PackagePostProcessFileNamePrep[#]
1615 | ],
1616 | PackageFERehidePackage@#
1617 | ]& /@ Keys@$DeclaredPackages
1618 |
1619 |
1620 | (* ::Subsubsection::Closed:: *)
1621 | (*Decontext*)
1622 |
1623 |
1624 | PackagePostProcessDecontextPackages[] /; TrueQ[$AllowPackageRecoloring] :=
1625 | (
1626 | If[
1627 | MemberQ[$PackageDecontextedPackages,
1628 | PackagePostProcessFileNamePrep[#]
1629 | ],
1630 | PackageFERehidePackage@#;
1631 | PackageDecontext@#
1632 | ]& /@ Keys@$DeclaredPackages;
1633 | If[ListQ@$PackageScopedSymbols,
1634 | KeyValueMap[
1635 | With[{newcont = #},
1636 | Replace[Join @@ #2,
1637 | HoldComplete[s__] :>
1638 | (
1639 | PackageFERehideSymbols[s];
1640 | Map[
1641 | Function[Null,
1642 | Quiet[
1643 | Check[
1644 | Set[Context[#], newcont],
1645 | Remove[#],
1646 | Context::cxdup
1647 | ],
1648 | Context::cxdup
1649 | ],
1650 | HoldAllComplete
1651 | ],
1652 | HoldComplete[s]
1653 | ] // ReleaseHold;
1654 | )
1655 | ]
1656 | ]&,
1657 | GroupBy[Flatten@$PackageScopedSymbols, First -> Last]
1658 | ];
1659 | ]
1660 | )
1661 |
1662 |
1663 |
1664 |
1665 | (* ::Subsubsection::Closed:: *)
1666 | (*ContextPathReassign*)
1667 |
1668 |
1669 | PackagePostProcessContextPathReassign[] :=
1670 | With[{cp = $ContextPath},
1671 | If[MemberQ[cp],
1672 | "BilibiliLink`",
1673 | $ContextPath =
1674 | Join[
1675 | Replace[
1676 | Flatten@{$PackageExposedContexts},
1677 | Except[_String?(StringEndsQ["`"])] -> Nothing,
1678 | 1
1679 | ],
1680 | $ContextPath
1681 | ];
1682 | If[TrueQ[$AllowPackageRecoloring],
1683 | FrontEnd`Private`GetUpdatedSymbolContexts[]
1684 | ];
1685 | ]
1686 | ]
1687 |
1688 |
1689 | (* ::Subsubsection:: *)
1690 | (*AttachMainAutocomplete*)
1691 |
1692 |
1693 | PackageAttachMainAutocomplete[] :=
1694 | PackageAddAutocompletions[BilibiliLink,
1695 | Table[
1696 | Replace[{} -> None]@
1697 | Cases[
1698 | DownValues[BilibiliLink],
1699 | Nest[
1700 | Insert[#, _, {1, 1, 1}]&,
1701 | (HoldPattern[Verbatim[HoldPattern]][
1702 | BilibiliLink[s_String, ___]
1703 | ] :> _),
1704 | n - 1
1705 | ] :> s,
1706 | Infinity
1707 | ],
1708 | {n, 5}
1709 | ]
1710 | ]
1711 |
1712 |
1713 | (* ::Subsection:: *)
1714 | (*End*)
1715 |
1716 |
1717 | End[];
1718 |
1719 |
1720 | (* ::Section:: *)
1721 | (* Load *)
1722 |
1723 |
1724 | If[`PackageScope`Private`$AllowPackageRecoloring,
1725 | Internal`SymbolList[False]
1726 | ];
1727 |
1728 |
1729 | (* ::Subsubsection:: *)
1730 | (*Basic Load*)
1731 |
1732 |
1733 | `PackageScope`Private`$loadAbort = False;
1734 | CheckAbort[
1735 | `PackageScope`Private`PackageAppLoad[];
1736 | `PackageScope`Private`$PackageFEHideExprSymbols = True;
1737 | `PackageScope`Private`$PackageFEHideEvalExpr = True;
1738 | `PackageScope`Private`$PackageScopeBlockEvalExpr = True;
1739 | `PackageScope`Private`$PackageDeclared = True;,
1740 | `PackageScope`Private`$loadAbort = True;
1741 | EndPackage[];
1742 | ];
1743 | Protect["`PackageScope`Private`*"];
1744 | Unprotect[`PackageScope`Private`$loadAbort];
1745 |
1746 |
1747 | (* ::Subsubsection:: *)
1748 | (*Post-Process*)
1749 |
1750 |
1751 | If[!`PackageScope`Private`$loadAbort,
1752 | `PackageScope`Private`PackagePostProcessPrepSpecs[];
1753 | `PackageScope`Private`PackagePostProcessExposePackages[];
1754 | `PackageScope`Private`PackagePostProcessRehidePackages[];
1755 | `PackageScope`Private`PackagePostProcessDecontextPackages[];
1756 | `PackageScope`Private`PackageAttachMainAutocomplete[];
1757 | ]
1758 |
1759 |
1760 | Unprotect[`PackageScope`Private`$PackageFEHiddenSymbols];
1761 | Clear[`PackageScope`Private`$PackageFEHiddenSymbols];
1762 | Unprotect[`PackageScope`Private`$PackageScopedSymbols];
1763 | Clear[`PackageScope`Private`$PackageScopedSymbols];
1764 |
1765 |
1766 | (* ::Subsubsection:: *)
1767 | (*Preempt Shadowing*)
1768 |
1769 |
1770 | (* Hide `PackageScope`Private` shadowing *)
1771 |
1772 |
1773 | Replace[
1774 | Hold[{`PackageScope`Private`m___}] :>
1775 | Off[`PackageScope`Private`m]
1776 | ]@
1777 | Thread[
1778 | ToExpression[
1779 | Map[# <> "$"&, Names["`PackageScope`Private`*"]
1780 | ],
1781 | StandardForm,
1782 | Function[Null,
1783 | Hold[MessageName[#, "shdw"]],
1784 | HoldAllComplete
1785 | ]
1786 | ],
1787 | Hold
1788 | ]
1789 |
1790 |
1791 | (* ::Subsubsection:: *)
1792 | (*EndPackage / Reset $ContextPath*)
1793 |
1794 |
1795 | EndPackage[];
1796 |
1797 |
1798 | If[
1799 | (Clear@BilibiliLink`PackageScope`Private`$loadAbort;!#)&@
1800 | BilibiliLink`PackageScope`Private`$loadAbort,
1801 | Unprotect[BilibiliLink`PackageScope`Private`$LoadCompleted];
1802 | BilibiliLink`PackageScope`Private`$LoadCompleted = True;
1803 | BilibiliLink`PackageScope`Private`PackagePostProcessContextPathReassign[]
1804 | ]
--------------------------------------------------------------------------------
/Config/BundleInfo.m:
--------------------------------------------------------------------------------
1 | (* Created with the Wolfram Language : www.wolfram.com *)
2 | {
3 | "RemovePaths" -> {"Private", "project", "GitHub", ".git"},
4 | "RemovePatterns" -> {"Packages/*.nb", "Packages/*/*.nb", "Packages/*/*/*.nb", ".DS_Store"}
5 | }
--------------------------------------------------------------------------------
/Config/DocInfo.m:
--------------------------------------------------------------------------------
1 | (* Created with the Wolfram Language : www.wolfram.com *)
2 | {
3 | "Usage" -> Automatic,
4 | "Functions" -> Automatic,
5 | "Details" -> Automatic,
6 | "Examples" -> Defer,
7 | "RelatedLinks" -> None,
8 | "GuideOptions" -> {},
9 | "TutorialOptions" -> {}
10 | }
--------------------------------------------------------------------------------
/Config/LoadInfo.m:
--------------------------------------------------------------------------------
1 | (* Created with the Wolfram Language : www.wolfram.com *)
2 | {"PreLoad" -> None, "FEHidden" -> {}, "PackageScope" -> None}
3 |
--------------------------------------------------------------------------------
/Kernel/Format.wl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai4waifu/BilibiliLink/d5ad6bf72d56d112fd71c7b5a752fb01bb3c0b8d/Kernel/Format.wl
--------------------------------------------------------------------------------
/Kernel/init.m:
--------------------------------------------------------------------------------
1 | If[$CharacterEncoding =!= "UTF-8",
2 | $CharacterEncoding = "UTF-8";
3 | Print[{
4 | Style["$CharacterEncoding has been changed to UTF-8 to avoid problems.", Red],
5 | Style["Because BilibiliLink only works under UTF-8"]
6 | } // TableForm];
7 | st = OpenAppend[FindFile["init.m"]];
8 | WriteString[st, "$CharacterEncoding=\"UTF-8\";"];
9 | Close[st];
10 | ];
11 | Get["BilibiliLink`BilibiliLink`"];
--------------------------------------------------------------------------------
/Kernel/scripts.m:
--------------------------------------------------------------------------------
1 | (* ::Package:: *)
2 |
3 | BScript`Pack[] := Module[
4 | {add, info, paclet},
5 | add[v_] := Block[
6 | {p, sp = StringSplit[v, "."]},
7 | p = ToString[ToExpression[Last@sp] + 1];
8 | StringRiffle[Append[Most@sp, p], "."]
9 | ];
10 | info = FindFile["BilibiliLink/PacletInfo.m"];
11 | paclet = Import[info] /. {("Version" -> v__) -> ("Version" -> Inactive[add][v])} // Activate;
12 | Export[info, StringReplace[ToString[paclet, InputForm],
13 | {
14 | "[" -> "[\n", "]" -> "\n]",
15 | "{" -> "{\n", "}" -> "\n}",
16 | "," -> ",\n"
17 | }
18 | ], "Text"];
19 | PacletInformation[PackPaclet["BilibiliLink"]]
20 | ];
21 |
22 |
23 | (* ::CodeText:: *)
24 | (*BScript`Pack[]*)
25 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Mozilla Public License Version 2.0
2 | ==================================
3 |
4 | 1. Definitions
5 | --------------
6 |
7 | 1.1. "Contributor"
8 | means each individual or legal entity that creates, contributes to
9 | the creation of, or owns Covered Software.
10 |
11 | 1.2. "Contributor Version"
12 | means the combination of the Contributions of others (if any) used
13 | by a Contributor and that particular Contributor's Contribution.
14 |
15 | 1.3. "Contribution"
16 | means Covered Software of a particular Contributor.
17 |
18 | 1.4. "Covered Software"
19 | means Source Code Form to which the initial Contributor has attached
20 | the notice in Exhibit A, the Executable Form of such Source Code
21 | Form, and Modifications of such Source Code Form, in each case
22 | including portions thereof.
23 |
24 | 1.5. "Incompatible With Secondary Licenses"
25 | means
26 |
27 | (a) that the initial Contributor has attached the notice described
28 | in Exhibit B to the Covered Software; or
29 |
30 | (b) that the Covered Software was made available under the terms of
31 | version 1.1 or earlier of the License, but not also under the
32 | terms of a Secondary License.
33 |
34 | 1.6. "Executable Form"
35 | means any form of the work other than Source Code Form.
36 |
37 | 1.7. "Larger Work"
38 | means a work that combines Covered Software with other material, in
39 | a separate file or files, that is not Covered Software.
40 |
41 | 1.8. "License"
42 | means this document.
43 |
44 | 1.9. "Licensable"
45 | means having the right to grant, to the maximum extent possible,
46 | whether at the time of the initial grant or subsequently, any and
47 | all of the rights conveyed by this License.
48 |
49 | 1.10. "Modifications"
50 | means any of the following:
51 |
52 | (a) any file in Source Code Form that results from an addition to,
53 | deletion from, or modification of the contents of Covered
54 | Software; or
55 |
56 | (b) any new file in Source Code Form that contains any Covered
57 | Software.
58 |
59 | 1.11. "Patent Claims" of a Contributor
60 | means any patent claim(s), including without limitation, method,
61 | process, and apparatus claims, in any patent Licensable by such
62 | Contributor that would be infringed, but for the grant of the
63 | License, by the making, using, selling, offering for sale, having
64 | made, import, or transfer of either its Contributions or its
65 | Contributor Version.
66 |
67 | 1.12. "Secondary License"
68 | means either the GNU General Public License, Version 2.0, the GNU
69 | Lesser General Public License, Version 2.1, the GNU Affero General
70 | Public License, Version 3.0, or any later versions of those
71 | licenses.
72 |
73 | 1.13. "Source Code Form"
74 | means the form of the work preferred for making modifications.
75 |
76 | 1.14. "You" (or "Your")
77 | means an individual or a legal entity exercising rights under this
78 | License. For legal entities, "You" includes any entity that
79 | controls, is controlled by, or is under common control with You. For
80 | purposes of this definition, "control" means (a) the power, direct
81 | or indirect, to cause the direction or management of such entity,
82 | whether by contract or otherwise, or (b) ownership of more than
83 | fifty percent (50%) of the outstanding shares or beneficial
84 | ownership of such entity.
85 |
86 | 2. License Grants and Conditions
87 | --------------------------------
88 |
89 | 2.1. Grants
90 |
91 | Each Contributor hereby grants You a world-wide, royalty-free,
92 | non-exclusive license:
93 |
94 | (a) under intellectual property rights (other than patent or trademark)
95 | Licensable by such Contributor to use, reproduce, make available,
96 | modify, display, perform, distribute, and otherwise exploit its
97 | Contributions, either on an unmodified basis, with Modifications, or
98 | as part of a Larger Work; and
99 |
100 | (b) under Patent Claims of such Contributor to make, use, sell, offer
101 | for sale, have made, import, and otherwise transfer either its
102 | Contributions or its Contributor Version.
103 |
104 | 2.2. Effective Date
105 |
106 | The licenses granted in Section 2.1 with respect to any Contribution
107 | become effective for each Contribution on the date the Contributor first
108 | distributes such Contribution.
109 |
110 | 2.3. Limitations on Grant Scope
111 |
112 | The licenses granted in this Section 2 are the only rights granted under
113 | this License. No additional rights or licenses will be implied from the
114 | distribution or licensing of Covered Software under this License.
115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a
116 | Contributor:
117 |
118 | (a) for any code that a Contributor has removed from Covered Software;
119 | or
120 |
121 | (b) for infringements caused by: (i) Your and any other third party's
122 | modifications of Covered Software, or (ii) the combination of its
123 | Contributions with other software (except as part of its Contributor
124 | Version); or
125 |
126 | (c) under Patent Claims infringed by Covered Software in the absence of
127 | its Contributions.
128 |
129 | This License does not grant any rights in the trademarks, service marks,
130 | or logos of any Contributor (except as may be necessary to comply with
131 | the notice requirements in Section 3.4).
132 |
133 | 2.4. Subsequent Licenses
134 |
135 | No Contributor makes additional grants as a result of Your choice to
136 | distribute the Covered Software under a subsequent version of this
137 | License (see Section 10.2) or under the terms of a Secondary License (if
138 | permitted under the terms of Section 3.3).
139 |
140 | 2.5. Representation
141 |
142 | Each Contributor represents that the Contributor believes its
143 | Contributions are its original creation(s) or it has sufficient rights
144 | to grant the rights to its Contributions conveyed by this License.
145 |
146 | 2.6. Fair Use
147 |
148 | This License is not intended to limit any rights You have under
149 | applicable copyright doctrines of fair use, fair dealing, or other
150 | equivalents.
151 |
152 | 2.7. Conditions
153 |
154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
155 | in Section 2.1.
156 |
157 | 3. Responsibilities
158 | -------------------
159 |
160 | 3.1. Distribution of Source Form
161 |
162 | All distribution of Covered Software in Source Code Form, including any
163 | Modifications that You create or to which You contribute, must be under
164 | the terms of this License. You must inform recipients that the Source
165 | Code Form of the Covered Software is governed by the terms of this
166 | License, and how they can obtain a copy of this License. You may not
167 | attempt to alter or restrict the recipients' rights in the Source Code
168 | Form.
169 |
170 | 3.2. Distribution of Executable Form
171 |
172 | If You distribute Covered Software in Executable Form then:
173 |
174 | (a) such Covered Software must also be made available in Source Code
175 | Form, as described in Section 3.1, and You must inform recipients of
176 | the Executable Form how they can obtain a copy of such Source Code
177 | Form by reasonable means in a timely manner, at a charge no more
178 | than the cost of distribution to the recipient; and
179 |
180 | (b) You may distribute such Executable Form under the terms of this
181 | License, or sublicense it under different terms, provided that the
182 | license for the Executable Form does not attempt to limit or alter
183 | the recipients' rights in the Source Code Form under this License.
184 |
185 | 3.3. Distribution of a Larger Work
186 |
187 | You may create and distribute a Larger Work under terms of Your choice,
188 | provided that You also comply with the requirements of this License for
189 | the Covered Software. If the Larger Work is a combination of Covered
190 | Software with a work governed by one or more Secondary Licenses, and the
191 | Covered Software is not Incompatible With Secondary Licenses, this
192 | License permits You to additionally distribute such Covered Software
193 | under the terms of such Secondary License(s), so that the recipient of
194 | the Larger Work may, at their option, further distribute the Covered
195 | Software under the terms of either this License or such Secondary
196 | License(s).
197 |
198 | 3.4. Notices
199 |
200 | You may not remove or alter the substance of any license notices
201 | (including copyright notices, patent notices, disclaimers of warranty,
202 | or limitations of liability) contained within the Source Code Form of
203 | the Covered Software, except that You may alter any license notices to
204 | the extent required to remedy known factual inaccuracies.
205 |
206 | 3.5. Application of Additional Terms
207 |
208 | You may choose to offer, and to charge a fee for, warranty, support,
209 | indemnity or liability obligations to one or more recipients of Covered
210 | Software. However, You may do so only on Your own behalf, and not on
211 | behalf of any Contributor. You must make it absolutely clear that any
212 | such warranty, support, indemnity, or liability obligation is offered by
213 | You alone, and You hereby agree to indemnify every Contributor for any
214 | liability incurred by such Contributor as a result of warranty, support,
215 | indemnity or liability terms You offer. You may include additional
216 | disclaimers of warranty and limitations of liability specific to any
217 | jurisdiction.
218 |
219 | 4. Inability to Comply Due to Statute or Regulation
220 | ---------------------------------------------------
221 |
222 | If it is impossible for You to comply with any of the terms of this
223 | License with respect to some or all of the Covered Software due to
224 | statute, judicial order, or regulation then You must: (a) comply with
225 | the terms of this License to the maximum extent possible; and (b)
226 | describe the limitations and the code they affect. Such description must
227 | be placed in a text file included with all distributions of the Covered
228 | Software under this License. Except to the extent prohibited by statute
229 | or regulation, such description must be sufficiently detailed for a
230 | recipient of ordinary skill to be able to understand it.
231 |
232 | 5. Termination
233 | --------------
234 |
235 | 5.1. The rights granted under this License will terminate automatically
236 | if You fail to comply with any of its terms. However, if You become
237 | compliant, then the rights granted under this License from a particular
238 | Contributor are reinstated (a) provisionally, unless and until such
239 | Contributor explicitly and finally terminates Your grants, and (b) on an
240 | ongoing basis, if such Contributor fails to notify You of the
241 | non-compliance by some reasonable means prior to 60 days after You have
242 | come back into compliance. Moreover, Your grants from a particular
243 | Contributor are reinstated on an ongoing basis if such Contributor
244 | notifies You of the non-compliance by some reasonable means, this is the
245 | first time You have received notice of non-compliance with this License
246 | from such Contributor, and You become compliant prior to 30 days after
247 | Your receipt of the notice.
248 |
249 | 5.2. If You initiate litigation against any entity by asserting a patent
250 | infringement claim (excluding declaratory judgment actions,
251 | counter-claims, and cross-claims) alleging that a Contributor Version
252 | directly or indirectly infringes any patent, then the rights granted to
253 | You by any and all Contributors for the Covered Software under Section
254 | 2.1 of this License shall terminate.
255 |
256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all
257 | end user license agreements (excluding distributors and resellers) which
258 | have been validly granted by You or Your distributors under this License
259 | prior to termination shall survive termination.
260 |
261 | ************************************************************************
262 | * *
263 | * 6. Disclaimer of Warranty *
264 | * ------------------------- *
265 | * *
266 | * Covered Software is provided under this License on an "as is" *
267 | * basis, without warranty of any kind, either expressed, implied, or *
268 | * statutory, including, without limitation, warranties that the *
269 | * Covered Software is free of defects, merchantable, fit for a *
270 | * particular purpose or non-infringing. The entire risk as to the *
271 | * quality and performance of the Covered Software is with You. *
272 | * Should any Covered Software prove defective in any respect, You *
273 | * (not any Contributor) assume the cost of any necessary servicing, *
274 | * repair, or correction. This disclaimer of warranty constitutes an *
275 | * essential part of this License. No use of any Covered Software is *
276 | * authorized under this License except under this disclaimer. *
277 | * *
278 | ************************************************************************
279 |
280 | ************************************************************************
281 | * *
282 | * 7. Limitation of Liability *
283 | * -------------------------- *
284 | * *
285 | * Under no circumstances and under no legal theory, whether tort *
286 | * (including negligence), contract, or otherwise, shall any *
287 | * Contributor, or anyone who distributes Covered Software as *
288 | * permitted above, be liable to You for any direct, indirect, *
289 | * special, incidental, or consequential damages of any character *
290 | * including, without limitation, damages for lost profits, loss of *
291 | * goodwill, work stoppage, computer failure or malfunction, or any *
292 | * and all other commercial damages or losses, even if such party *
293 | * shall have been informed of the possibility of such damages. This *
294 | * limitation of liability shall not apply to liability for death or *
295 | * personal injury resulting from such party's negligence to the *
296 | * extent applicable law prohibits such limitation. Some *
297 | * jurisdictions do not allow the exclusion or limitation of *
298 | * incidental or consequential damages, so this exclusion and *
299 | * limitation may not apply to You. *
300 | * *
301 | ************************************************************************
302 |
303 | 8. Litigation
304 | -------------
305 |
306 | Any litigation relating to this License may be brought only in the
307 | courts of a jurisdiction where the defendant maintains its principal
308 | place of business and such litigation shall be governed by laws of that
309 | jurisdiction, without reference to its conflict-of-law provisions.
310 | Nothing in this Section shall prevent a party's ability to bring
311 | cross-claims or counter-claims.
312 |
313 | 9. Miscellaneous
314 | ----------------
315 |
316 | This License represents the complete agreement concerning the subject
317 | matter hereof. If any provision of this License is held to be
318 | unenforceable, such provision shall be reformed only to the extent
319 | necessary to make it enforceable. Any law or regulation which provides
320 | that the language of a contract shall be construed against the drafter
321 | shall not be used to construe this License against a Contributor.
322 |
323 | 10. Versions of the License
324 | ---------------------------
325 |
326 | 10.1. New Versions
327 |
328 | Mozilla Foundation is the license steward. Except as provided in Section
329 | 10.3, no one other than the license steward has the right to modify or
330 | publish new versions of this License. Each version will be given a
331 | distinguishing version number.
332 |
333 | 10.2. Effect of New Versions
334 |
335 | You may distribute the Covered Software under the terms of the version
336 | of the License under which You originally received the Covered Software,
337 | or under the terms of any subsequent version published by the license
338 | steward.
339 |
340 | 10.3. Modified Versions
341 |
342 | If you create software not governed by this License, and you want to
343 | create a new license for such software, you may create and use a
344 | modified version of this License if you rename the license and remove
345 | any references to the name of the license steward (except to note that
346 | such modified license differs from this License).
347 |
348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary
349 | Licenses
350 |
351 | If You choose to distribute Source Code Form that is Incompatible With
352 | Secondary Licenses under the terms of this version of the License, the
353 | notice described in Exhibit B of this License must be attached.
354 |
355 | Exhibit A - Source Code Form License Notice
356 | -------------------------------------------
357 |
358 | This Source Code Form is subject to the terms of the Mozilla Public
359 | License, v. 2.0. If a copy of the MPL was not distributed with this
360 | file, You can obtain one at http://mozilla.org/MPL/2.0/.
361 |
362 | If it is not possible or desirable to put the notice in a particular
363 | file, then You may include the notice in a location (such as a LICENSE
364 | file in a relevant directory) where a recipient would be likely to look
365 | for such a notice.
366 |
367 | You may add additional accurate notices of copyright ownership.
368 |
369 | Exhibit B - "Incompatible With Secondary Licenses" Notice
370 | ---------------------------------------------------------
371 |
372 | This Source Code Form is "Incompatible With Secondary Licenses", as
373 | defined by the Mozilla Public License, v. 2.0.
--------------------------------------------------------------------------------
/Packages/!APIs.m:
--------------------------------------------------------------------------------
1 | $BilibiliLinkUA::usage = "";
2 | BilibiliLink`ㄑAPIs::usage = "";
3 | BilibiliLink`ㄑAPIs[___] := "";
4 | Begin["`APIs`"];
5 |
6 |
7 | $RawAPIs = <|
8 | "archive" -> <|
9 | "url" -> StringTemplate["https://api.bilibili.com/x/web-interface/archive/stat?aid=`aid`"],
10 | "detail" -> ""
11 | |>,
12 | "arch" -> <|
13 | "url" -> StringTemplate["https://api.bilibili.com/archive_stat/stat?aid=`aid`"],
14 | "detail" -> "效果和archive接口相同."
15 | |>,
16 | "cid" -> <|
17 | "url" -> StringTemplate["http://www.bilibilijj.com/Api/AvToCid/`aid`/0"],
18 | "detail" -> "哔哩哔哩唧唧的cid查询端口, 本机必须使用apikeys或cookies才能得到."
19 | |>,
20 | "photohot" -> <|
21 | "url" -> <|
22 | "illustration" -> StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Doc/list?category=illustration&type=hot&page_num=`page`&page_size=20"],
23 | "comic" -> StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Doc/list?category=comic&type=hot&page_num=`page`&page_size=20"],
24 | "draw" -> StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Doc/list?category=draw&type=hot&page_num=`page`&page_size=20"],
25 | "all" -> StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Doc/list?category=all&type=hot&page_num=`page`&page_size=20"],
26 | "cos" -> StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Photo/list?category=cos&type=hot&page_num=`page`&page_size=20"],
27 | "sifu" -> StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Photo/list?category=sifu&type=hot&page_num=`page`&page_size=20"]
28 | |>,
29 | "detail" -> "h.bilibili.com的热门作品. 可选参数 page, 从0到24."
30 | |>,
31 | "photorank" -> <|
32 | "url" -> <|
33 | 1 -> StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Doc/ranklist?biz=1&rank_type=`time`&page_size=50"],
34 | 2 -> StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Doc/ranklist?biz=2&category=cos&rank_type=`time`&page_size=50"],
35 | 3 -> StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Doc/ranklist?biz=2&category=sifu&rank_type=`time`&page_size=50"]
36 | |>,
37 | "detail" -> "h.bilibili.com的排行榜. 可选参数 time, 有day, week, month三种取值."
38 | |>,
39 | "webshow" -> <|
40 | "url" -> <|
41 | "id" -> StringTemplate["https://api.bilibili.com/x/web-show/res/locs?pf=0&id=`id`"]
42 | "ids" -> StringTemplate["https://api.bilibili.com/x/web-show/res/locs?pf=0&ids=`ids`"]
43 | |>,
44 | "detail" -> "不明,可选参数见$LocPF0."
45 | |>,
46 | "vs" -> <|
47 | "url" -> StringTemplate["http://api.bilibili.com/x/web-interface/newlist?rid=`rid`"],
48 | "detail" -> "VideoSection, B站视频分区, rid 为分区编号, 详见下表 $RidList."
49 | |>,
50 | "vspage" -> <|
51 | "url" -> StringTemplate["http://api.bilibili.com/x/web-interface/newlist?rid=`rid`&pn=`pn`&ps=20&type=0"],
52 | "detail" -> "VideoSectionPage, pn 为页数, ps 为单页显示条目数, 锁死 20, tpye 用途不明"
53 | |>,
54 | "ar" -> <|
55 | "url" -> StringTemplate["https://api.bilibili.com/x/article/rank/list?cid=`cid`"],
56 | "detail" -> "ArticleRank, 专栏文章全站排名, cid 为时段, 可选值有四个:1, 月榜, 2, 周榜, 3, 昨日, 4, 前天",
57 | "from" -> "https://www.bilibili.com/read/ranking"
58 | |>,
59 | "captcha" -> <|
60 | "url" -> "https://passport.bilibili.com/captcha",
61 | "detail" -> "返回验证码"
62 | |>
63 | |>;
64 |
65 | (*未整理的API
66 |
67 |
68 |
69 |
70 |
71 |
72 | https://api.bilibili.com/x/article/rank/list?cid=4
73 |
74 | // tag用
75 | URLExecute["https://api.bilibili.com/x/tag/ranking/archives?tag_id=6776132&rid=47&type=0&pn=1&ps=100","RawJson"]["data"]
76 | https://api.bilibili.com/x/web-interface/ranking/tag?rid=47&tag_id=6776132
77 |
78 |
79 | // 手机载入页面
80 | http://app.bilibili.com/x/splash?plat=0&width=1080&height=1920
81 | //IPHONE 和安卓一样
82 | http://app.bilibili.com/x/splash?channel=appstore&height=1334&plat=1&width=750
83 | //IPAD
84 | http://app.bilibili.com/x/splash?channel=appstore&height=1536&plat=1&width=2048
85 | *)
86 |
87 |
88 |
89 | (* ::Subsection::Closed:: *)
90 | (*Secret*)
91 | (*https://github.com/Vespa314/bilibili-api/blob/master/api.md*)
92 | $RidList = <|
93 | 0 -> <|
94 | "name" -> "根目录",
95 | "url" -> "http://www.bilibili.com",
96 | "parent" -> Missing
97 | |>,
98 | 1 -> <|
99 | "name" -> "动画",
100 | "url" -> "http://www.bilibili.com/video/douga.html",
101 | "parent" -> 0
102 | |>,
103 | 3 -> <|
104 | "name" -> "音乐",
105 | "url" -> "http://www.bilibili.com/video/music.html",
106 | "parent" -> 0
107 | |>,
108 | 4 -> <|
109 | "name" -> "游戏",
110 | "url" -> "http://www.bilibili.com/video/game.html",
111 | "parent" -> 0
112 | |>,
113 | 5 -> <|
114 | "name" -> "娱乐",
115 | "url" -> "http://www.bilibili.com/video/ent.html",
116 | "parent" -> 0
117 | |>,
118 | 9 -> <|
119 | "name" -> "意见留言簿",
120 | "url" -> "http://www.bilibili.complus/guestbook.php",
121 | "parent" -> 0
122 | |>,
123 | 11 -> <|
124 | "name" -> "电视剧",
125 | "url" -> "http://www.bilibili.com/video/teleplay.html",
126 | "parent" -> 0
127 | |>,
128 | 12 -> <|
129 | "name" -> "公告",
130 | "url" -> "http://www.bilibili.com/list.php?tid=",
131 | "parent" -> 0
132 | |>,
133 | 13 -> <|
134 | "name" -> "番剧",
135 | "url" -> "http://www.bilibili.com/video/bangumi.html",
136 | "parent" -> 0
137 | |>,
138 | 15 -> <|
139 | "name" -> "连载剧集",
140 | "url" -> "http://www.bilibili.com/video/soap-three-1.html",
141 | "parent" -> 11
142 | |>,
143 | 16 -> <|
144 | "name" -> "flash游戏",
145 | "url" -> "http://www.bilibili.com/video/game-flash-1.html",
146 | "parent" -> 116
147 | |>,
148 | 17 -> <|
149 | "name" -> "单机联机",
150 | "url" -> "http://www.bilibili.com/video/game-video-1.html",
151 | "parent" -> 116
152 | |>,
153 | 18 -> <|
154 | "name" -> "游戏攻略\[CenterDot]解说",
155 | "url" -> "http://www.bilibili.com/video/game-ctary-1.html",
156 | "parent" -> 116
157 | |>,
158 | 19 -> <|
159 | "name" -> "Mugen",
160 | "url" -> "http://www.bilibili.com/video/game-mugen-1.html",
161 | "parent" -> 116
162 | |>,
163 | 20 -> <|
164 | "name" -> "ACG相关舞蹈",
165 | "url" -> "http://www.bilibili.com/video/dance-1.html",
166 | "parent" -> 129
167 | |>,
168 | 21 -> <|
169 | "name" -> "生活",
170 | "url" -> "http://www.bilibili.com/video/ent-life-1.html",
171 | "parent" -> 5
172 | |>,
173 | 22 -> <|
174 | "name" -> "三次元鬼畜",
175 | "url" -> "http://www.bilibili.com/video/ent-Kichiku-1.html",
176 | "parent" -> 119
177 | |>,
178 | 23 -> <|
179 | "name" -> "电影",
180 | "url" -> "http://www.bilibili.com/video/movie.html",
181 | "parent" -> 0
182 | |>,
183 | 24 -> <|
184 | "name" -> "MAD\[CenterDot]AMV",
185 | "url" -> "http://www.bilibili.com/video/douga-mad-1.html",
186 | "parent" -> 1
187 | |>,
188 | 25 -> <|
189 | "name" -> "MMD\[CenterDot]3D",
190 | "url" -> "http://www.bilibili.com/video/douga-mmd-1.html",
191 | "parent" -> 1
192 | |>,
193 | 26 -> <|
194 | "name" -> "二次元鬼畜",
195 | "url" -> "http://www.bilibili.com/video/douga-kichiku-1.html",
196 | "parent" -> 119
197 | |>,
198 | 27 -> <|
199 | "name" -> "综合",
200 | "url" -> "http://www.bilibili.com/video/douga-else-1.html",
201 | "parent" -> 1
202 | |>,
203 | 28 -> <|
204 | "name" -> "同人音乐",
205 | "url" -> "http://www.bilibili.com/video/music-video-1.html",
206 | "parent" -> 117
207 | |>,
208 | 29 -> <|
209 | "name" -> "三次元音乐",
210 | "url" -> "http://www.bilibili.com/video/music-coordinate-1.html",
211 | "parent" -> 117
212 | |>,
213 | 30 -> <|
214 | "name" -> "VOCALOID\[CenterDot]UTAU",
215 | "url" -> "http://www.bilibili.com/video/music-vocaloid-1.html",
216 | "parent" -> 117
217 | |>,
218 | 31 -> <|
219 | "name" -> "翻唱",
220 | "url" -> "http://www.bilibili.com/video/music-Cover-1.html",
221 | "parent" -> 117
222 | |>,
223 | 32 -> <|
224 | "name" -> "完结动画",
225 | "url" -> "http://www.bilibili.com/video/part-twoelement-1.html",
226 | "parent" -> 13
227 | |>,
228 | 33 -> <|
229 | "name" -> "连载动画",
230 | "url" -> "http://www.bilibili.com/video/bangumi-two-1.html",
231 | "parent" -> 13
232 | |>,
233 | 34 -> <|
234 | "name" -> "完结剧集",
235 | "url" -> "http://www.bilibili.com/video/tv-drama-1.html",
236 | "parent" -> 11
237 | |>,
238 | 36 -> <|
239 | "name" -> "科技",
240 | "url" -> "http://www.bilibili.com/video/technology.html",
241 | "parent" -> 0
242 | |>,
243 | 37 -> <|
244 | "name" -> "纪录片",
245 | "url" -> "http://www.bilibili.com/video/tech-popular-science-1.html",
246 | "parent" -> 36
247 | |>,
248 | 39 -> <|
249 | "name" -> "演讲\[Bullet]公开课",
250 | "url" -> "http://www.bilibili.com/video/speech-course-1.html",
251 | "parent" -> 36
252 | |>,
253 | 40 -> <|
254 | "name" -> "技术宅",
255 | "url" -> "http://www.bilibili.com/video/tech-otaku-1.html",
256 | "parent" -> 122
257 | |>,
258 | 41 -> <|
259 | "name" -> "暂置区",
260 | "url" -> "http://www.bilibili.com/video/index.html",
261 | "parent" -> 12
262 | |>,
263 | 43 -> <|
264 | "name" -> "舞蹈MMD",
265 | "url" -> "http://www.bilibili.com/video/mmd-dance-1.html",
266 | "parent" -> 25
267 | |>,
268 | 44 -> <|
269 | "name" -> "剧情MMD",
270 | "url" -> "http://www.bilibili.com/video/mmd-story-1.html",
271 | "parent" -> 25
272 | |>,
273 | 45 -> <|
274 | "name" -> "原创模型",
275 | "url" -> "http://www.bilibili.com/video/mmd-original-1.html",
276 | "parent" -> 25
277 | |>,
278 | 46 -> <|
279 | "name" -> "其他视频",
280 | "url" -> "http://www.bilibili.com/video/index.html",
281 | "parent" -> 25
282 | |>,
283 | 47 -> <|
284 | "name" -> "动画短片",
285 | "url" -> "http://www.bilibili.com/video/douga-voice-1.html",
286 | "parent" -> 1
287 | |>,
288 | 48 -> <|
289 | "name" -> "原创动画",
290 | "url" -> "http://www.bilibili.com/video/douga-voice-original-1.html",
291 | "parent" -> 47
292 | |>,
293 | 49 -> <|
294 | "name" -> "ACG配音",
295 | "url" -> "http://www.bilibili.com/video/douga-voice-translate-1.html",
296 | "parent" -> 27
297 | |>,
298 | 50 -> <|
299 | "name" -> "手书",
300 | "url" -> "http://www.bilibili.com/video/douga-else-handwriting-1.html",
301 | "parent" -> 27
302 | |>,
303 | 51 -> <|
304 | "name" -> "资讯",
305 | "url" -> "http://www.bilibili.com/video/douga-else-information-1.html",
306 | "parent" -> 13
307 | |>,
308 | 52 -> <|
309 | "name" -> "动漫杂谈",
310 | "url" -> "http://www.bilibili.com/video/douga-else-tattle-1.html",
311 | "parent" -> 27
312 | |>,
313 | 53 -> <|
314 | "name" -> "其他动漫",
315 | "url" -> "http://www.bilibili.com/video/douga-else-other-1.html",
316 | "parent" -> 27
317 | |>,
318 | 54 -> <|
319 | "name" -> "OP/ED/OST",
320 | "url" -> "http://www.bilibili.com/video/music-oped-1.html",
321 | "parent" -> 117
322 | |>,
323 | 55 -> <|
324 | "name" -> "其他音乐",
325 | "url" -> "http://www.bilibili.com/video/music-video-other-1.html",
326 | "parent" -> 28
327 | |>,
328 | 56 -> <|
329 | "name" -> "VOCALOID",
330 | "url" -> "http://www.bilibili.com/video/music-vocaloid-vocaloid-1.html",
331 | "parent" -> 30
332 | |>,
333 | 57 -> <|
334 | "name" -> "UTAU",
335 | "url" -> "http://www.bilibili.com/video/music-vocaloid-utau-1.html",
336 | "parent" -> 30
337 | |>,
338 | 58 -> <|
339 | "name" -> "VOCALOID中文曲",
340 | "url" -> "http://www.bilibili.com/video/music-vocaloid-chinese-1.html",
341 | "parent" -> 30
342 | |>,
343 | 59 -> <|
344 | "name" -> "演奏",
345 | "url" -> "http://www.bilibili.com/video/music-perform-1.html",
346 | "parent" -> 117
347 | |>,
348 | 60 -> <|
349 | "name" -> "电子竞技",
350 | "url" -> "http://www.bilibili.com/video/game-fight-1.html",
351 | "parent" -> 116
352 | |>,
353 | 61 -> <|
354 | "name" -> "预告资讯",
355 | "url" -> "http://www.bilibili.com/video/game-presentation-1.html",
356 | "parent" -> 17
357 | |>,
358 | 63 -> <|
359 | "name" -> "实况解说",
360 | "url" -> "http://www.bilibili.com/video/game-video-other-1.html",
361 | "parent" -> 17
362 | |>,
363 | 64 -> <|
364 | "name" -> "游戏杂谈",
365 | "url" -> "http://www.bilibili.com/video/game-ctary-standalone-1.html",
366 | "parent" -> 17
367 | |>,
368 | 65 -> <|
369 | "name" -> "网络游戏",
370 | "url" -> "http://www.bilibili.com/video/game-ctary-network-1.html",
371 | "parent" -> 116
372 | |>,
373 | 66 -> <|
374 | "name" -> "游戏集锦",
375 | "url" -> "http://www.bilibili.com/video/game-ctary-handheld-1.html",
376 | "parent" -> 17
377 | |>,
378 | 67 -> <|
379 | "name" -> "其他游戏",
380 | "url" -> "http://www.bilibili.com/video/game-ctary-other-1.html",
381 | "parent" -> 17
382 | |>,
383 | 68 -> <|
384 | "name" -> "电竞赛事",
385 | "url" -> "http://www.bilibili.com/video/game-fight-matches-1.html",
386 | "parent" -> 60
387 | |>,
388 | 69 -> <|
389 | "name" -> "实况解说",
390 | "url" -> "http://www.bilibili.com/video/game-fight-explain-1.html",
391 | "parent" -> 60
392 | |>,
393 | 70 -> <|
394 | "name" -> "游戏集锦",
395 | "url" -> "http://www.bilibili.com/video/game-fight-other-1.html",
396 | "parent" -> 60
397 | |>,
398 | 71 -> <|
399 | "name" -> "综艺",
400 | "url" -> "http://www.bilibili.com/video/ent-variety-1.html",
401 | "parent" -> 5
402 | |>,
403 | 72 -> <|
404 | "name" -> "运动",
405 | "url" -> "http://www.bilibili.com/video/ent-sports-1.html",
406 | "parent" -> 21
407 | |>,
408 | 73 -> <|
409 | "name" -> "影视剪影",
410 | "url" -> "http://www.bilibili.com/video/ent-silhouette-1.html",
411 | "parent" -> 128
412 | |>,
413 | 74 -> <|
414 | "name" -> "日常",
415 | "url" -> "http://www.bilibili.com/video/ent-life-other-1.html",
416 | "parent" -> 21
417 | |>,
418 | 75 -> <|
419 | "name" -> "动物圈",
420 | "url" -> "http://www.bilibili.com/video/ent-animal-1.html",
421 | "parent" -> 5
422 | |>,
423 | 76 -> <|
424 | "name" -> "美食圈",
425 | "url" -> "http://www.bilibili.com/video/ent-food-1.html",
426 | "parent" -> 5
427 | |>,
428 | 77 -> <|
429 | "name" -> "喵星人",
430 | "url" -> "http://www.bilibili.com/video/ent-animal-cat-1.html",
431 | "parent" -> 75
432 | |>,
433 | 78 -> <|
434 | "name" -> "汪星人",
435 | "url" -> "http://www.bilibili.com/video/ent-animal-dog-1.html",
436 | "parent" -> 75
437 | |>,
438 | 79 -> <|
439 | "name" -> "其他动物",
440 | "url" -> "http://www.bilibili.com/video/ent-animal-other-1.html",
441 | "parent" -> 75
442 | |>,
443 | 80 -> <|
444 | "name" -> "美食视频",
445 | "url" -> "http://www.bilibili.com/video/ent-food-video-1.html",
446 | "parent" -> 76
447 | |>,
448 | 81 -> <|
449 | "name" -> "料理制作",
450 | "url" -> "http://www.bilibili.com/video/ent-food-course-1.html",
451 | "parent" -> 76
452 | |>,
453 | 82 -> <|
454 | "name" -> "电影相关",
455 | "url" -> "http://www.bilibili.com/video/movie-presentation-1.html",
456 | "parent" -> 23
457 | |>,
458 | 83 -> <|
459 | "name" -> "其他国家",
460 | "url" -> "http://www.bilibili.com/video/movie-movie-1.html",
461 | "parent" -> 23
462 | |>,
463 | 85 -> <|
464 | "name" -> "短片",
465 | "url" -> "http://www.bilibili.com/video/tv-micromovie-1.html",
466 | "parent" -> 23
467 | |>,
468 | 86 -> <|
469 | "name" -> "特摄\[CenterDot]布袋",
470 | "url" -> "http://www.bilibili.com/video/tv-sfx-1.html",
471 | "parent" -> 11
472 | |>,
473 | 87 -> <|
474 | "name" -> "国产",
475 | "url" -> "http://www.bilibili.com/video/tv-drama-cn-1.html",
476 | "parent" -> 34
477 | |>,
478 | 88 -> <|
479 | "name" -> "日剧",
480 | "url" -> "http://www.bilibili.com/video/tv-drama-jp-1.html",
481 | "parent" -> 34
482 | |>,
483 | 89 -> <|
484 | "name" -> "美剧",
485 | "url" -> "http://www.bilibili.com/video/tv-drama-us-1.html",
486 | "parent" -> 34
487 | |>,
488 | 90 -> <|
489 | "name" -> "其他TV",
490 | "url" -> "http://www.bilibili.com/video/tv-drama-other-1.html",
491 | "parent" -> 34
492 | |>,
493 | 91 -> <|
494 | "name" -> "特摄",
495 | "url" -> "http://www.bilibili.com/video/tv-sfx-sfx-1.html",
496 | "parent" -> 86
497 | |>,
498 | 92 -> <|
499 | "name" -> "布袋戏",
500 | "url" -> "http://www.bilibili.com/video/tv-sfx-pili-1.html",
501 | "parent" -> 86
502 | |>,
503 | 94 -> <|
504 | "name" -> "剧场版",
505 | "url" -> "http://www.bilibili.com/video/bangumi-ova-1.html",
506 | "parent" -> 32
507 | |>,
508 | 95 -> <|
509 | "name" -> "数码",
510 | "url" -> "http://www.bilibili.com/video/tech-future-digital-1.html",
511 | "parent" -> 36
512 | |>,
513 | 96 -> <|
514 | "name" -> "军事",
515 | "url" -> "http://www.bilibili.com/video/tech-future-military-1.html",
516 | "parent" -> 36
517 | |>,
518 | 97 -> <|
519 | "name" -> "手机评测",
520 | "url" -> "http://www.bilibili.com/video/tech-future-mobile-1.html",
521 | "parent" -> 95
522 | |>,
523 | 98 -> <|
524 | "name" -> "机械",
525 | "url" -> "http://www.bilibili.com/video/tech-future-other-1.html",
526 | "parent" -> 36
527 | |>,
528 | 99 -> <|
529 | "name" -> "BBC纪录片",
530 | "url" -> "http://www.bilibili.com/video/tech-geo-bbc-1.html",
531 | "parent" -> 37
532 | |>,
533 | 100 -> <|
534 | "name" -> "探索频道",
535 | "url" -> "http://www.bilibili.com/video/tech-geo-discovery-1.html",
536 | "parent" -> 37
537 | |>,
538 | 101 -> <|
539 | "name" -> "国家地理",
540 | "url" -> "http://www.bilibili.com/video/tech-geo-national-1.html",
541 | "parent" -> 37
542 | |>,
543 | 102 -> <|
544 | "name" -> "NHK",
545 | "url" -> "http://www.bilibili.com/video/tech-geo-nhk-1.html",
546 | "parent" -> 37
547 | |>,
548 | 103 -> <|
549 | "name" -> "演讲",
550 | "url" -> "http://www.bilibili.com/video/speech-1.html",
551 | "parent" -> 39
552 | |>,
553 | 104 -> <|
554 | "name" -> "公开课",
555 | "url" -> "http://www.bilibili.com/video/course-1.html",
556 | "parent" -> 39
557 | |>,
558 | 105 -> <|
559 | "name" -> "演示",
560 | "url" -> "http://www.bilibili.com/video/tech-geo-course-1.html",
561 | "parent" -> 122
562 | |>,
563 | 107 -> <|
564 | "name" -> "科技人文",
565 | "url" -> "http://www.bilibili.com/video/tech-humanity-1.html",
566 | "parent" -> 124
567 | |>,
568 | 108 -> <|
569 | "name" -> "趣味短片",
570 | "url" -> "http://www.bilibili.com/video/tech-funvideo-1.html",
571 | "parent" -> 124
572 | |>,
573 | 110 -> <|
574 | "name" -> "国产",
575 | "url" -> "http://www.bilibili.com/video/soap-three-cn-1.html",
576 | "parent" -> 15
577 | |>,
578 | 111 -> <|
579 | "name" -> "日剧",
580 | "url" -> "http://www.bilibili.com/video/soap-three-jp-1.html",
581 | "parent" -> 15
582 | |>,
583 | 112 -> <|
584 | "name" -> "美剧",
585 | "url" -> "http://www.bilibili.com/video/soap-three-us-1.html",
586 | "parent" -> 15
587 | |>,
588 | 113 -> <|
589 | "name" -> "其他电视剧",
590 | "url" -> "http://www.bilibili.com/video/soap-three-oth-1.html",
591 | "parent" -> 15
592 | |>,
593 | 114 -> <|
594 | "name" -> "国内综艺",
595 | "url" -> "http://www.bilibili.com/video/index.html",
596 | "parent" -> 71
597 | |>,
598 | 115 -> <|
599 | "name" -> "国外综艺",
600 | "url" -> "http://www.bilibili.com/video/index.html",
601 | "parent" -> 71
602 | |>,
603 | 116 -> <|
604 | "name" -> "游戏",
605 | "url" -> "http://www.bilibili.com/video/index.html",
606 | "parent" -> 12
607 | |>,
608 | 117 -> <|
609 | "name" -> "音乐",
610 | "url" -> "http://www.bilibili.com/video/index.html",
611 | "parent" -> 12
612 | |>,
613 | 118 -> <|
614 | "name" -> "其他",
615 | "url" -> "http://www.bilibili.com/video/index.html",
616 | "parent" -> 12
617 | |>,
618 | 119 -> <|
619 | "name" -> "鬼畜",
620 | "url" -> "http://www.bilibili.com/video/kichiku.html",
621 | "parent" -> 0
622 | |>,
623 | 120 -> <|
624 | "name" -> "剧场版",
625 | "url" -> "http://www.bilibili.com/video/newbangumi-ova-1.html",
626 | "parent" -> 33
627 | |>,
628 | 121 -> <|
629 | "name" -> "GMV",
630 | "url" -> "http://www.bilibili.com/video/gmv-1.html",
631 | "parent" -> 116
632 | |>,
633 | 122 -> <|
634 | "name" -> "野生技术协会",
635 | "url" -> "http://www.bilibili.com/video/tech-wild-1.html",
636 | "parent" -> 36
637 | |>,
638 | 123 -> <|
639 | "name" -> "手办模型",
640 | "url" -> "http://www.bilibili.com/video/figure-1.html",
641 | "parent" -> 122
642 | |>,
643 | 124 -> <|
644 | "name" -> "趣味科普人文",
645 | "url" -> "http://www.bilibili.com/video/tech-fun-1.html",
646 | "parent" -> 36
647 | |>,
648 | 125 -> <|
649 | "name" -> "其他",
650 | "url" -> "http://www.bilibili.com/video/tech-geo-other-1.html",
651 | "parent" -> 37
652 | |>,
653 | 126 -> <|
654 | "name" -> "人力VOCALOID",
655 | "url" -> "http://www.bilibili.com/video/kichiku-manual_vocaloid-1.html",
656 | "parent" -> 119
657 | |>,
658 | 127 -> <|
659 | "name" -> "教程演示",
660 | "url" -> "http://www.bilibili.com/video/kichiku-course-1.html",
661 | "parent" -> 119
662 | |>,
663 | 128 -> <|
664 | "name" -> "电视剧相关",
665 | "url" -> "http://www.bilibili.com/video/tv-presentation-1.html",
666 | "parent" -> 11
667 | |>,
668 | 129 -> <|
669 | "name" -> "舞蹈",
670 | "url" -> "http://www.bilibili.com/video/dance.html",
671 | "parent" -> 0
672 | |>,
673 | 130 -> <|
674 | "name" -> "音乐选集",
675 | "url" -> "http://www.bilibili.com/video/music-collection-1.html",
676 | "parent" -> 117
677 | |>,
678 | 131 -> <|
679 | "name" -> "Korea相关",
680 | "url" -> "http://www.bilibili.com/video/ent-korea-1.html",
681 | "parent" -> 5
682 | |>,
683 | 132 -> <|
684 | "name" -> "Korea音乐舞蹈",
685 | "url" -> "http://www.bilibili.com/video/ent-korea-music-dance-1.html",
686 | "parent" -> 131
687 | |>,
688 | 133 -> <|
689 | "name" -> "Korea综艺",
690 | "url" -> "http://www.bilibili.com/video/ent-korea-variety-1.html",
691 | "parent" -> 131
692 | |>,
693 | 134 -> <|
694 | "name" -> "其他",
695 | "url" -> "http://www.bilibili.com/video/ent-korea-other-1.html",
696 | "parent" -> 131
697 | |>,
698 | 135 -> <|
699 | "name" -> "活动",
700 | "url" -> "http://www.bilibili.com/video/video/activities.html",
701 | "parent" -> 0
702 | |>,
703 | 136 -> <|
704 | "name" -> "音游",
705 | "url" -> "http://www.bilibili.com/video/music-game-1.html",
706 | "parent" -> 116
707 | |>,
708 | 137 -> <|
709 | "name" -> "娱乐圈",
710 | "url" -> "http://www.bilibili.com/video/ent-circle-1.html",
711 | "parent" -> 5
712 | |>,
713 | 138 -> <|
714 | "name" -> "搞笑",
715 | "url" -> "http://www.bilibili.com/video/ent_funny_1.html",
716 | "parent" -> 5
717 | |>,
718 | 139 -> <|
719 | "name" -> "实况解说",
720 | "url" -> "http://www.bilibili.com/video/list__1.html",
721 | "parent" -> 65
722 | |>,
723 | 140 -> <|
724 | "name" -> "游戏杂谈",
725 | "url" -> "http://www.bilibili.com/video/list__1.html",
726 | "parent" -> 65
727 | |>,
728 | 141 -> <|
729 | "name" -> "游戏集锦",
730 | "url" -> "http://www.bilibili.com/video/list__1.html",
731 | "parent" -> 65
732 | |>,
733 | 142 -> <|
734 | "name" -> "漫展",
735 | "url" -> "http://www.bilibili.com/video/list__1.html",
736 | "parent" -> 21
737 | |>,
738 | 143 -> <|
739 | "name" -> "COSPLAY",
740 | "url" -> "http://www.bilibili.com/video/list__1.html",
741 | "parent" -> 21
742 | |>,
743 | 144 -> <|
744 | "name" -> "综艺剪辑",
745 | "url" -> "http://www.bilibili.com/video/list__1.html",
746 | "parent" -> 71
747 | |>,
748 | 145 -> <|
749 | "name" -> "欧美电影",
750 | "url" -> "http://www.bilibili.com/video/movie_west_1.html",
751 | "parent" -> 23
752 | |>,
753 | 146 -> <|
754 | "name" -> "日本电影",
755 | "url" -> "http://www.bilibili.com/video/movie_japan_1.html",
756 | "parent" -> 23
757 | |>,
758 | 147 -> <|
759 | "name" -> "国产电影",
760 | "url" -> "http://www.bilibili.com/video/movie_chinese_1.html",
761 | "parent" -> 23
762 | |>,
763 | 148 -> <|
764 | "name" -> "TV动画",
765 | "url" -> "http://www.bilibili.com/video/list__1.html",
766 | "parent" -> 33
767 | |>,
768 | 149 -> <|
769 | "name" -> "OVA\[CenterDot]OAD",
770 | "url" -> "http://www.bilibili.com/video/list__1.html",
771 | "parent" -> 33
772 | |>,
773 | 150 -> <|
774 | "name" -> "TV动画",
775 | "url" -> "http://www.bilibili.com/video/list__1.html",
776 | "parent" -> 32
777 | |>,
778 | 151 -> <|
779 | "name" -> "OVA\[CenterDot]OAD",
780 | "url" -> "http://www.bilibili.com/video/list__1.html",
781 | "parent" -> 32
782 | |>,
783 | 152 -> <|
784 | "name" -> "官方延伸",
785 | "url" -> "http://www.bilibili.com/video/bagumi_offical_1.html",
786 | "parent" -> 13
787 | |>,
788 | 153 -> <|
789 | "name" -> "国产动画",
790 | "url" -> "http://www.bilibili.com/video/bangumi_chinese_1.html",
791 | "parent" -> 13
792 | |>,
793 | 154 -> <|
794 | "name" -> "三次元舞蹈",
795 | "url" -> "http://www.bilibili.com/video/three-dimension-dance-1.html",
796 | "parent" -> 129
797 | |>
798 | |>;
799 |
800 | (* 编号全靠口胡, 服气
801 | URLExecute["https://api.bilibili.com/x/web-show/res/locs?pf=0&ids="<>StringJoin@StringRiffle[ToString /@ Range[1, 10000], ","], "RawJSON"]
802 | StringRiffle[Keys[%["data"]], ","] // Sort*)
803 | $LocPF0 = "21,23,29,31,34,40,42,44,52,58,64,70,76,82,88,94,
804 | 100,106,112,118,124,126,128,130,132,134,136,138,142,
805 | 148,151,152,153,160,162,243,245,247,249,251,253,255,
806 | 257,259,261,263,265,267,269,271,273,275,277,279,281,
807 | 283,285,287,289,291,293,295,395,403,405,406,412,413,
808 | 414,415,417,418,419,1466,1550,1554,1556,1558,1560,1562,
809 | 1564,1566,1568,1570,1572,1574,1576,1578,1580,1582,1584,
810 | 1586,1588,1590,1592,1594,1596,1598,1600,1602,1604,1606,
811 | 1608,1610,1612,1614,1616,1618,1620,1622,1624,1626,1628,
812 | 1630,1632,1634,1636,1660,1666,1670,1674,1680,1682,1919,
813 | 1920,1921,1922,1923,1966,2034,2047,2048,2057,2058,2061,
814 | 2062,2065,2066,2067,2078,2079,2207,2210,2211,2212,2213,
815 | 2214,2257,2260,2261,2262,2263,2264,2307,2308,2309,2319,
816 | 2341,2343,2345,2403,2452,2453,2462,2463,2472,2473,2482,
817 | 2483,2492,2493,2503";
818 |
819 | (* ::Subsection::Closed:: *)
820 | (*Secret*)
821 | $Secrets::usage = "官方key注册通道已经关闭\r
822 | 虽然可以用黑科技注入, 但是已经搞不到高权限的key了\r
823 | 所以只能用现有的开源方案来搞了, 这些key来自\r
824 | https://github.com/search?q=bilibili+appkey&type=Code";
825 | $Secrets = {
826 | <|
827 | "AppKey" -> "84956560bc028eb7",
828 | "Source" -> "soimort/you-get",
829 | "LastTest" -> "No Test"
830 | |>,
831 | <|
832 | "AppKey" -> "f3bb208b3d081dc8",
833 | "Secret" -> "1c15888dc316e05a15fdd0a02ed6584f"
834 | "Source" -> "MoePlayer/DPlayer-API",
835 | "LastTest" -> "Success when 20180513"
836 | |>
837 |
838 | };
839 |
840 |
841 |
842 | $APIs = <|
843 | "PhotoHot" -> Function[Table[$RawAPIs["photohot", "url", #][<|"page" -> i|>], {i, 0, 24}]],
844 | "PhotoRank" -> Function[Through[Values[$RawAPIs["photorank", "url"]][<|"time" -> #|>]]],
845 | "RidList" -> $RidList,
846 | "VideoSection" -> Function[$RawAPIs["vs"]["rid" -> #]]
847 | |>;
848 |
849 | $BilibiliLinkUA = {
850 | "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
851 | "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
852 | "Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
853 | "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
854 | "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
855 | "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
856 | "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
857 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
858 | "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
859 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
860 | "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
861 | "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5",
862 | "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6",
863 | "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
864 | "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20",
865 | "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",
866 | "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11",
867 | "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER",
868 | "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; LBBROWSER)",
869 | "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E; LBBROWSER)",
870 | "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 LBBROWSER",
871 | "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)",
872 | "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; QQBrowser/7.0.3698.400)",
873 | "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)",
874 | "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; 360SE)",
875 | "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)",
876 | "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)",
877 | "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1",
878 | "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1",
879 | "Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; zh-cn) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5",
880 | "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0b13pre) Gecko/20110307 Firefox/4.0b13pre",
881 | "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:16.0) Gecko/20100101 Firefox/16.0",
882 | "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11",
883 | "Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10"
884 | };
885 |
886 |
887 |
888 | SetAttributes[
889 | {$RawAPIs, $RidList, $APIs},
890 | {Protected, ReadProtected}
891 | ];
892 | End[];
893 |
--------------------------------------------------------------------------------
/Packages/!Directories.m:
--------------------------------------------------------------------------------
1 | $BilibiliLinkDirectory::usage = "BilibiliLink 的安装路径.";
2 | $BilibiliLinkIcons::usage = "BilibiliLink 的图标映射.";
3 | $BilibiliLinkData::usage = "BilibiliLink 的数据存放位置.";
4 | BilibiliLink`ㄑDirectories::usage = "";
5 | BilibiliLink`ㄑDirectories[___] := "";
6 | Begin["`Directories`"];
7 |
8 |
9 | $BilibiliLinkDirectory = DirectoryName[FindFile["BilibiliLink`Kernel`"], 2];
10 | $BilibiliLinkData = FileNameJoin[{$UserBaseDirectory, "ApplicationData", "BilibiliLink"}];
11 |
12 |
13 |
14 | $BLID::usage = "BilibiliLinkIconsDirectory,BilibiliLink 图片图标的存放路径.";
15 | $BLID = FileNameJoin[{$BilibiliLinkDirectory, "Resources", "ico"}];
16 | $BilibiliLinkIcons[name_] := $BilibiliLinkIcons[name] = Switch[name,
17 | "BilibiliAlbumObject",
18 | Image[Import[FileNameJoin[{$BLID, "BilibiliAlbumObject.jpg"}], "jpg"], ImageSize -> {Automatic, 140}],
19 | "BilibiliVideoSectionObject",
20 | Image[Import[FileNameJoin[{$BLID, "BilibiliVideoSectionObject.png"}], "png"], ImageSize -> {Automatic, 53}],
21 | "BilibiliDownloadObject",
22 | Image[Import[FileNameJoin[{$BLID, "BilibiliDownloadObject.png"}], "png"], ImageSize -> {Automatic, 64}]
23 | ];
24 |
25 |
26 | SetAttributes[
27 | {$BLID},
28 | {Protected, ReadProtected}
29 | ];
30 | End[];
31 |
--------------------------------------------------------------------------------
/Packages/BilibiliCore.m:
--------------------------------------------------------------------------------
1 | AbortableMap::usage = "";
2 | BilibiliLink`ㄑFunctions::usage = "";
3 | BilibiliLink`ㄑFunctions[___] := "";
4 | Begin["`Functions`"];
5 | timeLeft[start_, frac_] := With[{past = AbsoluteTime[] - start}, If[frac == 0 || past < 1, "-", Floor[past / frac - past]]];
6 | AbortableMap[func_, list_, ker_ : $KernelCount] := DynamicModule[
7 | {len, bag, size, lastresults, starttime, n, results, t},
8 | len = Length[list]; size = 0; starttime = AbsoluteTime[];
9 | results = {}; SetSharedVariable[results, size];
10 | Monitor[
11 | t = Table[ParallelSubmit[{i},
12 | With[
13 | {r = func[list[[i]]]},
14 | size += ByteCount[r];
15 | AppendTo[results, {i, r}]
16 | ]
17 | ], {i, Range[len]}];
18 | CheckAbort[WaitAll[t], AbortKernels[]];
19 | SortBy[results, First],
20 | Dynamic@Refresh[Panel @ Column[{
21 | ProgressIndicator[Length[results] / len, ImageSize -> 350],
22 | Row[{Button["Abort", Abort[]],
23 | Grid[{{"Tasks", "Memory (kB)", "Time left (s)"},
24 | {StringForm["``/``", Length[results], len],
25 | ToString @ NumberForm[size / 2.^10, {3, 2}],
26 | ToString @ timeLeft[starttime, Length[results] / len]}
27 | }, Spacings -> {1, 1}, ItemSize -> {10, 1}, Dividers -> Center
28 | ]}, Spacer[5]]
29 | }], UpdateInterval -> 1, TrackedSymbols -> {}
30 | ]
31 | ]
32 | ];
33 | WriteCSV[file_String, matrix_] := With[
34 | {
35 | str = OpenWrite[file, PageWidth -> Infinity],
36 | len = Length[First@matrix]
37 | },
38 | Scan[Write[str,
39 | Sequence @@ (Flatten[
40 | Table[{FortranForm[#[[i]]], OutputForm[","]}, {i, len - 1}]
41 | ]) ~ Join ~ {FortranForm[#[[len]]]}]&, matrix
42 | ];
43 | Close[str];
44 | ];
45 | SetAttributes[
46 | {},
47 | {Protected, ReadProtected}
48 | ];
49 | End[]
50 |
--------------------------------------------------------------------------------
/Packages/BilibiliDDOS.m:
--------------------------------------------------------------------------------
1 | VipEmoji::usage = "xxx";
2 | IndexIcon::usage = "xxx";
3 | ErrorPage::usage = "xxx";
4 | HeaderBanner::usage = "xxx";
5 | HeaderLogo::usage = "xxx";
6 | BilibiliLink`ㄑDDOS::usage = "";
7 | BilibiliLink`ㄑDDOS[___] := "";
8 | Begin["`DDOS`"];
9 | VipEmojiReshape[line_] := Block[
10 | {drop = KeyDrop[line["emojis"], {"state", "remark"}]},
11 | Append[
12 | <|"ID" -> #["id"], "URL" -> #["url"], "Name" -> StringTake[#["name"], 2 ;; -2]|>& /@ drop,
13 | <|"ID" -> line["pid"], "URL" -> line["purl"], "Name" -> line["pname"]|>
14 | ]];
15 | Options[VipEmoji] = {Path -> FileNameJoin[{$BilibiliLinkData, "Image", "Emoji"}]};
16 | VipEmoji[___, OptionsPattern[]] := Block[
17 | {get = URLExecute["http://api.bilibili.com/x/v2/reply/emojis", "RawJSON"]["data"]},
18 | BilibiliDownloadObject[<|
19 | "Date" -> Now,
20 | "Category" -> "Bilibili Vip Emoji",
21 | "Data" -> SortBy[Flatten[VipEmojiReshape /@ get], "ID"],
22 | "Path" -> OptionValue[Path],
23 | "Size" -> 5021696.
24 | |>
25 | ]];
26 | VipEmoji["Raw"] := URLExecute["http://api.bilibili.com/x/v2/reply/emojis", "RawJSON"]["data"];
27 |
28 |
29 |
30 | IndexIconReshape[line_] := <|
31 | "ID" -> line["id"],
32 | "Name" -> line["title"],
33 | "URL" -> line["icon"]
34 | |>;
35 | Options[IndexIcon] = {Path -> FileNameJoin[{$BilibiliLinkData, "Image", "Icon"}]};
36 | IndexIcon[___, OptionsPattern[]] := Block[
37 | {get = URLExecute["https://www.bilibili.com/index/index-icon.json", "RawJSON"]["fix"]},
38 | BilibiliDownloadObject[<|
39 | "Date" -> Now,
40 | "Category" -> "Bilibili Index Icon",
41 | "Data" -> SortBy[Flatten[IndexIconReshape /@ get], "ID"],
42 | "Path" -> OptionValue[Path],
43 | "Size" -> 8015872.
44 | |>
45 | ]];
46 | IndexIcon["Raw"] := URLExecute["https://www.bilibili.com/index/index-icon.json", "RawJSON"]["fix"];
47 | tsLine[doc_] := {
48 | "#### Title: " <> doc["id"] <> "_" <> doc["title"],
49 | "##### Date: " <> DateString[FromUnixTime[ToExpression@doc["sttime"]]],
50 | "##### Link: " <> StringDelete[URLDecode@URLDecode@First@doc["links"], " "],
51 | "![" <> First@doc["links"] <> "](https:" <> doc["icon"] <> ")",
52 | "---"
53 | };
54 | IndexIcon["Markdown", OptionsPattern[]] := Block[
55 | {get = IndexIcon["Raw"], file = OptionValue[Path], name},
56 | name = FileNameJoin[{file, "IndexIcon.md"}];
57 | If[!FileExistsQ[file], CreateFile[file]];
58 | If[FileExistsQ[name], DeleteFile[name]];
59 | Export[name, StringJoin@Riffle[Flatten[tsLine /@ SortBy[get, ToExpression[#["id"]]&]], "\r"], "Text"]
60 | ];
61 |
62 |
63 | $ErrorPageExtension = {
64 | "https://static.hdslb.com/error/400.png",
65 | "https://static.hdslb.com/error/403.png",
66 | "https://static.hdslb.com/error/404.png",
67 | "https://static.hdslb.com/error/444.png",
68 | "https://static.hdslb.com/error/500.png",
69 | "https://static.hdslb.com/error/502.png",
70 | "https://static.hdslb.com/error/503.png",
71 | "https://static.hdslb.com/error/504.png",
72 | "https://activity.hdslb.com/zzjs/cartoon/errorPage-manga-1.png",
73 | "https://activity.hdslb.com/zzjs/cartoon/errorPage-manga-2.png",
74 | "https://activity.hdslb.com/zzjs/cartoon/errorPage-manga-3.png",
75 | "https://activity.hdslb.com/zzjs/cartoon/errorPage-manga-4.png",
76 | "https://activity.hdslb.com/zzjs/cartoon/errorPage-manga-5.png",
77 | "https://activity.hdslb.com/zzjs/cartoon/errorPage-manga-6.png",
78 | "https://activity.hdslb.com/zzjs/cartoon/errorPage-manga-7.png",
79 | "https://static.hdslb.com/images/error/no_video_login.png",
80 | "https://static.hdslb.com/images/error/wait_for_review.png",
81 | "https://static.hdslb.com/images/error/wait_for_release.png",
82 | "https://static.hdslb.com/images/error/no_video.png",
83 | "https://static.hdslb.com/images/error/video_conflict.png"
84 | };
85 | ErrorPageExtensionReshape[url_, {id_}] := <|
86 | "ID" -> id,
87 | "Name" -> StringSplit[url, {"/", "."}][[-2]],
88 | "URL" -> url
89 | |>;
90 | ErrorPageReshape[line_] := <|
91 | "ID" -> line["id"],
92 | "Name" -> StringJoin["error_cover_", line["id"]],
93 | "URL" -> line["data", "img"]
94 | |>;
95 | Options[ErrorPage] = {Path -> FileNameJoin[{$BilibiliLinkData, "Image", "Icon"}]};
96 | ErrorPage[___, OptionsPattern[]] := Block[
97 | {get = URLExecute["www.bilibili.com/activity/web/view/data/31", "RawJSON"]["data", "list"], data},
98 | data = Join[ErrorPageReshape /@ get, MapIndexed[ErrorPageExtensionReshape, $ErrorPageExtension]];
99 | BilibiliDownloadObject[<|
100 | "Date" -> Now,
101 | "Category" -> "Bilibili Error Page",
102 | "Data" -> SortBy[data, "ID"],
103 | "Path" -> OptionValue[Path],
104 | "Size" -> 58363904.
105 | |>]
106 | ];
107 |
108 |
109 | HeaderReshape[asc_] := Module[
110 | {name, banner, icon, c = asc["c"]},
111 | If[c === {}, Return[Nothing]];
112 | name = If[KeyExistsQ[asc["c"], "title"], c["title"], c["name"]];
113 | icon = If[
114 | KeyExistsQ[asc["c"], "logo"],
115 | Last@StringSplit[c["logo"], "/"],
116 | Last@StringSplit[c["litpic"], "/"]
117 | ];
118 | banner = If[
119 | KeyExistsQ[asc["c"], "pic"],
120 | Last@StringSplit[c["pic"], "/"],
121 | Last@StringSplit[c["background"], "/"]
122 | ];
123 | <|
124 | "Title" -> c["name"],
125 | "Date" -> First@StringSplit[asc["n"], {"_", "-"}],
126 | "Banner" -> "https://i0.hdslb.com/headers/" <> banner,
127 | "Logo" -> "https://i0.hdslb.com/headers/" <> icon,
128 | "Link" -> c["url"]
129 | |>
130 | ];
131 | GetHeader[] := GetHeader[] = Block[
132 | {get, json, list},
133 | get = URLFetch["https://www.biliplus.com/task/banner_fetch/"];
134 | json = First@StringCases[get, "var items=" ~~ json__ ~~ "}}];" :> json <> "}}]"];
135 | list = ImportString[ToString[json, CharacterEncoding -> "UTF8"], "RawJSON"];
136 | HeaderReshape /@ list
137 | ];
138 |
139 | HeaderBannerReshape[line_, {index_}] := <|"ID" -> index, "Name" -> StringSplit[line["Banner"], {"/", "."}][[-2]], "URL" -> line["Banner"]|>;
140 | Options[HeaderBanner] = {Path -> FileNameJoin[{$BilibiliLinkData, "Image", "Banner"}]};
141 | HeaderBanner[___, OptionsPattern[]] := Block[
142 | {get = GetHeader[], data},
143 | data = MapIndexed[HeaderBannerReshape, get];
144 | BilibiliDownloadObject[<|
145 | "Date" -> Now,
146 | "Category" -> "Bilibili Header Banner",
147 | "Data" -> SortBy[data, "ID"],
148 | "Path" -> OptionValue[Path],
149 | "Size" -> 118206806.
150 | |>]
151 | ];
152 | HeaderLogoReshape[line_, {index_}] := <|"ID" -> index, "Name" -> StringSplit[line["Logo"], {"/", "."}][[-2]], "URL" -> line["Logo"]|>;
153 | Options[HeaderLogo] = {Path -> FileNameJoin[{$BilibiliLinkData, "Image", "Logo"}]};
154 | HeaderLogo[___, OptionsPattern[]] := Block[
155 | {get = GetHeader[], data},
156 | data = MapIndexed[HeaderLogoReshape, get];
157 | BilibiliDownloadObject[<|
158 | "Date" -> Now,
159 | "Category" -> "Bilibili Header Logo",
160 | "Data" -> SortBy[data, "ID"],
161 | "Path" -> OptionValue[Path],
162 | "Size" -> 17955498.
163 | |>]
164 | ];
165 |
166 | SetAttributes[
167 | {},
168 | {Protected, ReadProtected}
169 | ];
170 | End[]
171 |
--------------------------------------------------------------------------------
/Packages/BilibiliDataServer.m:
--------------------------------------------------------------------------------
1 | $BilibiliServer::usage = "远程数据服务器";
2 | BilibiliLink`ㄑRemote::usage = "";
3 | BilibiliLink`ㄑRemote[___] := "";
4 | Needs["MongoLink`"];
5 | Begin["`Remote`"];
6 | $BilibiliServer = "https://m.vers.site";
7 | $DatabaseServer = "mongodb://biliman:readonly@45.32.68.44:37017/bilispider";
8 | DatabaseClient=MongoLink`MongoConnect[$DatabaseServer];
9 | TracedMemberDB=MongoLink`MongoGetCollection[DatabaseClient,"bilispider","trace_member_info"];
10 | TracedVideoDB=MongoLink`MongoGetCollection[DatabaseClient,"bilispider","trace_video_stat"];
11 |
12 |
13 |
14 |
15 |
16 | GetTraceRemote[id_]:=Block[
17 | {cursor,data},
18 | cursor=MongoLink`MongoCollectionFind[
19 | TracedVideoDB,
20 | <|"aid"->id|>,
21 | <|"_id"->False,"aid"->False|>
22 | ];
23 | data=MongoLink`MongoCursorToArray[cursor]
24 | ];
25 |
26 |
27 |
28 | SetAttributes[
29 | {},
30 | {Protected, ReadProtected}
31 | ];
32 | End[]
33 |
--------------------------------------------------------------------------------
/Packages/BilibiliPhoto.m:
--------------------------------------------------------------------------------
1 | PhotosIndex::usage = "";
2 | PhotosRange::usage = "";
3 | PhotosHot::usage = "";
4 | PhotosNew::usage = "";
5 | PhotosRank::usage = "";
6 | BilibiliLink`ㄑPhoto::usage = "";
7 | BilibiliLink`ㄑPhoto[___] := "";
8 | Begin["`Photo`"];
9 | $PhotoKeyMap = <|
10 | 1 -> <|"Name" -> "插画", "Alias" -> "Illustration", "Key" -> "illustration", "Url" -> "https://h.bilibili.com/eden/draw_area#/illustration"|>,
11 | 2 -> <|"Name" -> "漫画", "Alias" -> "Comic", "Key" -> "comic", "Url" -> "https://h.bilibili.com/eden/draw_area#/comic"|>,
12 | 3 -> <|"Name" -> "其他画作", "Alias" -> "OtherDraw", "Key" -> "draw", "Url" -> "https://h.bilibili.com/eden/draw_area#/other"|>,
13 | 4 -> <|"Name" -> "全部画作", "Alias" -> "DrawAll", "Key" -> "alld", "Url" -> "https://h.bilibili.com/eden/draw_area#/all"|>,
14 | 5 -> <|"Name" -> "Cosplay", "Alias" -> "Cosplay", "Key" -> "cos", "Url" -> "https://h.bilibili.com/eden/picture_area#/cos"|>,
15 | 6 -> <|"Name" -> "其他摄影", "Alias" -> "OtherPhoto", "Key" -> "sifu", "Url" -> "https://h.bilibili.com/eden/picture_area#/sifu"|>,
16 | 7 -> <|"Name" -> "全部摄影", "Alias" -> "PhotoAll", "Key" -> "allp", "Url" -> "https://h.bilibili.com/eden/picture_area#/all"|>,
17 | 8 -> <|"Name" -> "日榜/新人榜", "Alias" -> "DayLeader", "Key" -> "day", "Url" -> "https://h.bilibili.com/common/rank#/photo"|>,
18 | 9 -> <|"Name" -> "周榜", "Alias" -> "WeekLeader", "Key" -> "week", "Url" -> "https://h.bilibili.com/common/rank#/photo"|>,
19 | 10 -> <|"Name" -> "月榜", "Alias" -> "MonthLeader", "Key" -> "month", "Url" -> "https://h.bilibili.com/common/rank#/photo"|>
20 | |>;
21 | $PhotosAPI = <|
22 | "Home" -> "https://api.vc.bilibili.com/link_draw/v2/Doc/home",
23 | "Range" -> StringTemplate["https://api.vc.bilibili.com/link_draw/v1/doc/detail?doc_id=`id`"],
24 | "Detail" -> StringTemplate["https://api.vc.bilibili.com/link_draw/v1/doc/detail?doc_id=`id`"],
25 | "Author" -> StringTemplate["https://api.vc.bilibili.com/link_draw/v1/doc/doc_list?uid=`id`&page_num=`page`&page_size=100"],
26 | "AuthorCount" -> StringTemplate["https://api.vc.bilibili.com/link_draw/v1/doc/upload_count?uid=`id`"],
27 | "AuthorDetail" -> StringTemplate["https://api.vc.bilibili.com/user_ex/v1/user/detail?user[]=info&user[]=level&room[]=live_status&room[]=room_link&feed[]=fans_count&feed[]=feed_count&feed[]=is_followed&uid=`id`"],
28 | "New" -> Function[Switch[#,
29 | "illustration", StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Doc/list?category=illustration&type=new&page_num=`p`&page_size=20"],
30 | "comic", StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Doc/list?category=comic&type=new&page_num=`p`&page_size=20"],
31 | "draw", StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Doc/list?category=draw&type=new&page_num=`p`&page_size=20"],
32 | "alld", StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Doc/list?category=all&type=new&page_num=`p`&page_size=20"],
33 | "cos", StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Photo/list?category=cos&type=new&page_num=`p`&page_size=20"],
34 | "sifu", StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Photo/list?category=sifu&type=new&page_num=`p`&page_size=20"],
35 | "allp", StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Photo/list?category=all&type=new&page_num=`p`&page_size=20"]
36 | ]],
37 | "Hot" -> Function[Switch[#,
38 | "illustration", StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Doc/list?category=illustration&type=hot&page_num=`p`&page_size=20"],
39 | "comic", StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Doc/list?category=comic&type=hot&page_num=`p`&page_size=20"],
40 | "draw", StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Doc/list?category=draw&type=hot&page_num=`p`&page_size=20"],
41 | "alld", StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Doc/list?category=all&type=hot&page_num=`p`&page_size=20"],
42 | "cos", StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Photo/list?category=cos&type=hot&page_num=`p`&page_size=20"],
43 | "sifu", StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Photo/list?category=sifu&type=hot&page_num=`p`&page_size=20"],
44 | "allp", StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Photo/list?category=all&type=hot&page_num=`p`&page_size=20"]
45 | ]],
46 | "Recommend" -> Function[{
47 | StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Doc/index?type=recommend&page_num=`p`&page_size=20"][#],
48 | StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Photo/index?type=recommend&page_num=`p`&page_size=20"][#]
49 | }],
50 | "Rank" -> Function[{
51 | StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Doc/ranklist?biz=1&rank_type=`time`&page_size=50"][#],
52 | StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Doc/ranklist?biz=2&category=cos&rank_type=`time`&page_size=50"][#],
53 | StringTemplate["https://api.vc.bilibili.com/link_draw/v2/Doc/ranklist?biz=2&category=sifu&rank_type=`time`&page_size=50"][#]
54 | }]
55 | |>;
56 |
57 |
58 |
59 | PhotosRangeReshape::usage = "PhotosRange的数据清洗.";
60 | PhotosRangeReshape[doc_Association] := <|
61 | "uid" -> doc["user", "uid"],
62 | "author" -> doc["user", "name"],
63 | "did" -> doc["item", "doc_id"],
64 | "title" -> If[doc["item", "title"] != "",
65 | doc["item", "title"],
66 | "无名_" <> ToString[doc["item", "doc_id"]]
67 | ],
68 | "time" -> DateObject[doc["item", "upload_time"]],
69 | "imgs" -> ("img_src" /. doc["item", "pictures"]),
70 | "size" -> If[KeyExistsQ[First@doc["item", "pictures"], "img_size"],
71 | Total["img_size" /. doc["item", "pictures"]],
72 | Missing
73 | ]
74 | |>;
75 | Options[PhotosRange] = {RawData -> False};
76 | PhotosRange[n_Integer, ops : OptionsPattern[]] := PhotosRange[Range[n], ops];
77 | PhotosRange[a_Integer, b_Integer, ops : OptionsPattern[]] := PhotosRange[Range[a, b], ops];
78 | PhotosRange[input_List, OptionsPattern[]] := Module[
79 | {$now = Now, urls, raw, data, count, size},
80 | urls = Table[$PhotosAPI["Range"][<|"id" -> i|>], {i, input}];
81 | raw = #["data"]& /@ Select[ParallelMap[URLExecute[#, "RawJSON"]&, urls], #["code"] == 0&];
82 | If[OptionValue[RawData], Return[raw]];
83 | data = PhotosRangeReshape /@ raw;
84 | If[data == {},
85 | count = 0;size = 0,
86 | count = Length@Flatten["imgs" /. data];
87 | size = Total@DeleteCases["size" /. data, Missing]
88 | ];
89 | BilibiliAlbumObject[<|
90 | "Data" -> data,
91 | "Category" -> "PhotosRange",
92 | "Repo" -> ToString[Length@input] <> " of ???",
93 | "Count" -> count,
94 | "Size" -> size,
95 | "Time" -> Now - $now,
96 | "Date" -> $now
97 | |>]
98 | ];
99 |
100 |
101 | PhotosIndex[] := Module[
102 | {$now = Now, get, bg, size, imgs},
103 | get = URLExecute[$PhotosAPI["Home"], "RawJSON"]["data"];
104 | bg = <|"Name" -> ToString[Now // UnixTime] <> "_0", "URL" -> get["bg_img"]|>;
105 | size = Total@DeleteCases["img_size" /. get["items"], "img_size"];
106 | imgs = Prepend["img_src" /. get["items"], bg];
107 | BilibiliAlbumObject[<|
108 | "Data" -> {<|
109 | "uid" -> 12076317,
110 | "author" -> "BilibiliHomePage",
111 | "did" -> 0,
112 | "title" -> "HomePage " <> DateString[$now],
113 | "time" -> $now,
114 | "imgs" -> imgs,
115 | "size" -> size
116 | |>},
117 | "Category" -> "PhotosHomePage",
118 | "Repo" -> "0 of 0",
119 | "Count" -> Length@imgs,
120 | "Size" -> size,
121 | "Time" -> Now - $now,
122 | "Date" -> $now
123 | |>]
124 | ];
125 |
126 |
127 | PhotosHotReshape::usage = "内部函数, 用于数据清洗";
128 | PhotosHotReshape[doc_Association] := <|
129 | "uid" -> doc["user", "uid"],
130 | "author" -> doc["user", "name"],
131 | "did" -> doc["item", "doc_id"],
132 | "title" -> If[doc["item", "title"] != "",
133 | doc["item", "title"],
134 | "无名_" <> ToString[doc["item", "doc_id"]]
135 | ],
136 | "time" -> FromUnixTime[doc["item", "upload_time"]],
137 | "imgs" -> ("img_src" /. doc["item", "pictures"]),
138 | "size" -> If[
139 | KeyExistsQ[First@doc["item", "pictures"], "img_size"],
140 | Total["img_size" /. doc["item", "pictures"]],
141 | Missing
142 | ]
143 | |>;
144 | Options[PhotosHot] = {UpTo -> 100, RawData -> False};
145 | PhotosHot[typenum_, OptionsPattern[]] := Module[
146 | {$now = Now, api, map, raw, data},
147 | api = $PhotosAPI["Hot"][$PhotoKeyMap[typenum]["Key"]];
148 | map = Table[api[<|"p" -> i|>], {i, 0, Quotient[Min[OptionValue[UpTo] - 1, 500], 20]}];
149 | raw = Flatten[URLExecute[#, "RawJSON"]["data", "items"]& /@ map];
150 | If[OptionValue[RawData], Return[raw]];
151 | data = PhotosHotReshape /@ raw;
152 | BilibiliAlbumObject[<|
153 | "Data" -> data,
154 | "Category" -> "PhotosHot" <> $PhotoKeyMap[typenum]["Alias"],
155 | "Repo" -> ToString[OptionValue[UpTo]] <> " of 500",
156 | "Count" -> Length@Flatten["imgs" /. data],
157 | "Size" -> Total@DeleteCases["size" /. data, Missing],
158 | "Time" -> Now - $now,
159 | "Date" -> $now
160 | |>]
161 | ];
162 |
163 |
164 | PhotosNewFindMax::usage = "找到某一图片分类的总数.";
165 | SetAttributes[PhotosNewFindMax, Listable];
166 | Options[PhotosNewFindMax] = {Max -> RandomInteger[{20000, 21000}], Count -> True};
167 | PhotosNewFindMax[type_String, OptionsPattern[]] := Module[
168 | {max, min, try, api},
169 | {min, max} = {1, OptionValue[Max]};
170 | api = $PhotosAPI["New"][type];
171 | try = URLExecute[api[<|"p" -> #|>], "RawJSON"]["data"]&;
172 | While[max - min > 1, If[try[Floor[(min + max) / 2]]["total_count"] > 0, min = Floor[(min + max) / 2], max = Floor[(min + max) / 2]]];
173 | If[OptionValue[Count], Return[Length[try[min]["items"]] + 20(min - 1)], min]
174 | ];
175 | PhotosNewReshape::usage = "内部函数, 用于数据清洗";
176 | PhotosNewReshape[doc_Association] := <|
177 | "uid" -> doc["user", "uid"],
178 | "author" -> doc["user", "name"],
179 | "did" -> doc["item", "doc_id"],
180 | "title" -> If[doc["item", "title"] != "",
181 | doc["item", "title"],
182 | "无名_" <> ToString[doc["item", "doc_id"]]
183 | ],
184 | "time" -> FromUnixTime[doc["item", "upload_time"]],
185 | "imgs" -> ("img_src" /. doc["item", "pictures"]),
186 | "size" -> If[
187 | KeyExistsQ[First@doc["item", "pictures"], "img_size"],
188 | Total["img_size" /. doc["item", "pictures"]],
189 | Missing]
190 | |>;
191 |
192 |
193 | Options[PhotosNew] = {UpTo -> 100, RawData -> False, Count -> False, All -> False};
194 | PhotosNew[typenum_, OptionsPattern[]] := Module[
195 | {$now = Now, api, all, map, raw, data},
196 | api = $PhotosAPI["New"][$PhotoKeyMap[typenum]["Key"]];
197 | If[OptionValue[Count],
198 | all = ToString[PhotosNewFindMax[$PhotoKeyMap[typenum]["Key"]]],
199 | all = "???"
200 | ];
201 | If[OptionValue[All],
202 | all = ToString[PhotosNewFindMax[$PhotoKeyMap[typenum]["Key"]]];
203 | map = Table[api[<|"p" -> i|>], {i, 0, Quotient[ToExpression[all] - 1, 20]}],
204 | map = Table[api[<|"p" -> i|>], {i, 0, Quotient[OptionValue[UpTo] - 1, 20]}]
205 | ];
206 | raw = Flatten[URLExecute[#, "RawJSON"]["data", "items"]& /@ map];
207 | If[OptionValue[RawData], Return[raw]];
208 | data = PhotosNewReshape /@ raw;
209 | BilibiliAlbumObject[<|
210 | "Data" -> data,
211 | "Category" -> "PhotosNew" <> $PhotoKeyMap[typenum]["Alias"],
212 | "Repo" -> ToString[OptionValue[UpTo]] <> " of " <> all,
213 | "Count" -> Length@Flatten["imgs" /. data],
214 | "Size" -> Total@DeleteCases["size" /. data, Missing],
215 | "Time" -> Now - $now,
216 | "Date" -> $now
217 | |>]
218 | ];
219 |
220 | PhotosAuthorReshape::usage = "内部函数, 用于数据清洗";
221 | PhotosAuthorReshape[doc_Association] := <|
222 | "uid" -> doc["poster_uid"],
223 | "author" -> doc["description"],
224 | "did" -> doc["doc_id"],
225 | "title" -> If[doc["item", "title"] != "",
226 | doc["item", "title"],
227 | "无名_" <> ToString[doc["item", "doc_id"]]
228 | ],
229 | "time" -> FromUnixTime[doc["ctime"]],
230 | "imgs" -> ("img_src" /. doc["pictures"]),
231 | "size" -> If[
232 | KeyExistsQ[First@doc["pictures"], "img_size"],
233 | Total["img_size" /. doc["pictures"]],
234 | Missing
235 | ]
236 | |>;
237 | PhotosAuthor[id_] := Module[
238 | {$now = Now, count, api, raw, data},
239 | count = URLExecute[$PhotosAPI["AuthorCount"][<|"id" -> id|>], "RawJSON"]["data"];
240 | api = URLExecute[$PhotosAPI["Author"][<|"id" -> id, "page" -> #|>], "RawJSON"]["data", "items"]&;
241 | raw = Flatten@Table[api[i], {i, 0, Quotient[count["all_count"] - 1, 100]}];
242 | data = PhotosAuthorReshape /@ raw;
243 | BilibiliAlbumObject[<|
244 | "Data" -> data,
245 | "Category" -> "PhotosAuthor " <> ToString[id],
246 | "Repo" -> ToString[raw // Length] <> " of " <> ToString[count["all_count"]],
247 | "Count" -> Length@Flatten["imgs" /. data],
248 | "Size" -> Total@DeleteCases["size" /. data, Missing],
249 | "Time" -> Now - $now,
250 | "Date" -> $now
251 | |>]
252 | ];
253 |
254 |
255 | PhotosRankReshape::usage = "内部函数, 用于数据清洗";
256 | PhotosRankReshape[doc_Association] := <|
257 | "uid" -> doc["user", "uid"],
258 | "author" -> doc["user", "name"],
259 | "did" -> doc["item", "doc_id"],
260 | "title" -> If[doc["item", "title"] != "",
261 | doc["item", "title"],
262 | "无名_" <> ToString[doc["item", "doc_id"]]
263 | ],
264 | "time" -> FromUnixTime[doc["item", "upload_time"]],
265 | "imgs" -> ("img_src" /. doc["item", "pictures"]),
266 | "size" -> If[KeyExistsQ[First@doc["item", "pictures"], "img_size"],
267 | Total["img_size" /. doc["item", "pictures"]],
268 | Missing
269 | ]
270 | |>;
271 |
272 | Options[PhotosRank] = {RawData -> False};
273 | PhotosRank[typenum_, OptionsPattern[]] := Module[
274 | {$now = Now, api, raw, data},
275 | api = $PhotosAPI["Rank"][<|"time" -> $PhotoKeyMap[typenum]["Key"]|>];
276 | raw = Flatten[URLExecute[#, "RawJSON"]["data", "items"]& /@ api];
277 | If[OptionValue[RawData], Return[raw]];
278 | data = PhotosRankReshape /@ raw;
279 | BilibiliAlbumObject[<|
280 | "Data" -> data,
281 | "Category" -> "PhotosRank" <> $PhotoKeyMap[typenum]["Alias"],
282 | "Repo" -> "150 of 150",
283 | "Count" -> Length@Flatten["imgs" /. data],
284 | "Size" -> Total@DeleteCases["size" /. data, Missing],
285 | "Time" -> Now - $now,
286 | "Date" -> $now
287 | |>]
288 | ];
289 |
290 | SetAttributes[
291 | {},
292 | {Protected, ReadProtected}
293 | ];
294 | End[]
295 |
--------------------------------------------------------------------------------
/Packages/BilibiliUI.m:
--------------------------------------------------------------------------------
1 | PhotosHelp::usage = "xxx";
2 | BilibiliLink`ㄑUI::usage = "";
3 | BilibiliLink`ㄑUI[___] := "";
4 | Begin["`UI`"];
5 |
6 |
7 |
8 | BLine[length_] := Panel["", Appearance -> Image[
9 | RawArray["UnsignedInteger8", {
10 | {{0, 0, 0, 0}, {0, 0, 0, 255}, {0, 0, 0, 0}},
11 | {{0, 0, 0, 0}, {255, 255, 255, 255}, {0, 0, 0, 255}},
12 | {{0, 0, 0, 255}, {250, 250, 250, 255}, {0, 0, 0, 255}},
13 | {{0, 0, 0, 255}, {249, 249, 249, 255}, {0, 0, 0, 255}},
14 | {{0, 0, 0, 255}, {249, 249, 249, 255}, {0, 0, 0, 255}},
15 | {{0, 0, 0, 255}, {249, 249, 249, 255}, {0, 0, 0, 255}},
16 | {{0, 0, 0, 255}, {248, 248, 248, 255}, {0, 0, 0, 255}},
17 | {{0, 0, 0, 255}, {248, 248, 248, 255}, {0, 0, 0, 255}},
18 | {{0, 0, 0, 255}, {247, 247, 247, 255}, {0, 0, 0, 255}},
19 | {{0, 0, 0, 255}, {246, 246, 246, 255}, {0, 0, 0, 255}},
20 | {{0, 0, 0, 255}, {246, 246, 246, 255}, {0, 0, 0, 255}},
21 | {{0, 0, 0, 255}, {245, 245, 245, 255}, {0, 0, 0, 255}},
22 | {{0, 0, 0, 255}, {245, 245, 245, 255}, {0, 0, 0, 255}},
23 | {{0, 0, 0, 255}, {244, 244, 244, 255}, {0, 0, 0, 255}},
24 | {{0, 0, 0, 255}, {243, 243, 243, 255}, {0, 0, 0, 255}},
25 | {{0, 0, 0, 255}, {243, 243, 243, 255}, {0, 0, 0, 255}},
26 | {{0, 0, 0, 255}, {242, 242, 242, 255}, {0, 0, 0, 255}},
27 | {{0, 0, 0, 255}, {241, 241, 241, 255}, {0, 0, 0, 255}},
28 | {{0, 0, 0, 255}, {241, 241, 241, 255}, {0, 0, 0, 255}},
29 | {{0, 0, 0, 255}, {240, 240, 240, 255}, {0, 0, 0, 255}},
30 | {{0, 0, 0, 255}, {239, 239, 239, 255}, {0, 0, 0, 255}},
31 | {{0, 0, 0, 255}, {239, 239, 239, 255}, {0, 0, 0, 255}},
32 | {{0, 0, 0, 255}, {238, 238, 238, 255}, {0, 0, 0, 255}},
33 | {{0, 0, 0, 255}, {237, 237, 237, 255}, {0, 0, 0, 255}},
34 | {{0, 0, 0, 255}, {237, 237, 237, 255}, {0, 0, 0, 255}},
35 | {{0, 0, 0, 255}, {236, 236, 236, 255}, {0, 0, 0, 255}},
36 | {{0, 0, 0, 255}, {236, 236, 236, 255}, {0, 0, 0, 255}},
37 | {{0, 0, 0, 255}, {235, 235, 235, 255}, {0, 0, 0, 255}},
38 | {{0, 0, 0, 255}, {234, 234, 234, 255}, {0, 0, 0, 255}},
39 | {{0, 0, 0, 255}, {234, 234, 234, 255}, {0, 0, 0, 255}},
40 | {{0, 0, 0, 255}, {233, 233, 233, 255}, {0, 0, 0, 255}},
41 | {{0, 0, 0, 255}, {233, 233, 233, 255}, {0, 0, 0, 255}},
42 | {{0, 0, 0, 255}, {233, 233, 233, 255}, {0, 0, 0, 255}},
43 | {{0, 0, 0, 255}, {232, 232, 232, 255}, {0, 0, 0, 255}},
44 | {{0, 0, 0, 0}, {179, 179, 179, 255}, {0, 0, 0, 0}},
45 | {{0, 0, 0, 0}, {0, 0, 0, 255}, {0, 0, 0, 0}}
46 | }], "Byte", ColorSpace -> "RGB", Interleaving -> True
47 | ], ImageMargins -> 5, ImageSize -> {length, 1}
48 | ];
49 |
50 | SetAttributes[Temp1, HoldAll];
51 | Temp1[text_String, fun_] := {{
52 | TextCell[text, "Text"],
53 | Row[{
54 | Button["Copy", CopyToClipboard[Defer@fun]],
55 | Button["Run", CellPrint[ExpressionCell[fun, "Output"]]]
56 | }]
57 | },
58 | {InputField[Defer[fun]], SpanFromLeft},
59 | {BLine[300], SpanFromLeft}
60 | };
61 |
62 | pHot = Grid[Most@Join[
63 | Temp1["1.热门插画", PhotosHot[1]],
64 | Temp1["2.热门漫画", PhotosHot[2]],
65 | Temp1["3.其他画作", PhotosHot[3]],
66 | Temp1["4.全部画作", PhotosHot[4]],
67 | Temp1["5.Cosplay", PhotosHot[5]],
68 | Temp1["6.其他摄影", PhotosHot[6]],
69 | Temp1["7.全部摄影", PhotosHot[7]]
70 | ], Alignment -> {{Left, Right}}, Selectable -> False
71 | ];
72 | pNew = Grid[Most@Join[
73 | Temp1["1.热门插画", PhotosNew[1]],
74 | Temp1["2.热门漫画", PhotosNew[2]],
75 | Temp1["3.其他画作", PhotosNew[3]],
76 | Temp1["4.全部画作", PhotosNew[4]],
77 | Temp1["5.Cosplay", PhotosNew[5]],
78 | Temp1["6.其他摄影", PhotosNew[6]],
79 | Temp1["7.全部摄影", PhotosNew[7]]
80 | ], Alignment -> {{Left, Right}}, Selectable -> False
81 | ];
82 | pRec = "未完成";
83 | pSearch = "未完成";
84 | pRank = Grid[Join[
85 | Temp1["1.日榜/新人榜", PhotosRank[8]],
86 | Temp1["2.周榜", PhotosRank[9]],
87 | Temp1["3.月榜", PhotosRank[10]]
88 | ], Alignment -> {{Left, Right}}, Selectable -> False
89 | ];
90 | PhotosHelp[___] := Module[
91 | {
92 | tb = Text /@ {"最新", "热门", "推荐", "排行", "搜索"},
93 | st = {pNew, pHot, pRec, pRank, pSearch}
94 | },
95 | TabView[Thread[tb -> st], ControlPlacement -> Left, Alignment -> Left, AutoAction -> True]
96 | ];
97 |
98 |
99 |
100 | SetAttributes[
101 | {},
102 | {Protected, ReadProtected}
103 | ];
104 | End[]
105 |
--------------------------------------------------------------------------------
/Packages/BilibiliVideoSection.m:
--------------------------------------------------------------------------------
1 | (* ::Package:: *)
2 | (* ::Title:: *)
3 | (*Example(样板包)*)
4 | (* ::Subchapter:: *)
5 | (*程序包介绍*)
6 | (* ::Text:: *)
7 | (*Mathematica Package*)
8 | (*Created by Mathematica Plugin for IntelliJ IDEA*)
9 | (*Establish from GalAster's template*)
10 | (**)
11 | (* ::Text:: *)
12 | (*Author:我是作者*)
13 | (*Creation Date:我是创建日期*)
14 | (*Copyright: Mozilla Public License Version 2.0*)
15 | (* ::Program:: *)
16 | (*1.软件产品再发布时包含一份原始许可声明和版权声明。*)
17 | (*2.提供快速的专利授权。*)
18 | (*3.不得使用其原始商标。*)
19 | (*4.如果修改了源代码,包含一份代码修改说明。*)
20 | (**)
21 | (* ::Section:: *)
22 | (*函数说明*)
23 | VideoSectionQ::usage = "";
24 | VideoSection::usage = "";
25 | VideoIDsRange::usage = "遍历所有ID";
26 | VideoIDsList::usage = "遍历指定ID";
27 | VideoIDsPack::usage = "打包缓存";
28 | VideoIDsInsertDB::usage = "插入数据库";
29 | TagInfo::usage = "TagInfo[id] 获取tag详细信息";
30 | (* ::Section:: *)
31 | (*程序包正体*)
32 | (* ::Subsection::Closed:: *)
33 | (*主设置*)
34 | BilibiliLink`ㄑVideo::usage = "";
35 | BilibiliLink`ㄑVideo[___] := "";
36 | Begin["`Video`"];
37 | (* ::Subsection:: *)
38 | (*功能块 2*)
39 | timeLeft[start_, frac_] := With[{past = AbsoluteTime[] - start}, If[frac == 0 || past < 1, "-", Floor[past / frac - past]]];
40 | (* ::Subsection:: *)
41 | (*功能块 2*)
42 | VideoSectionQ = MemberQ[$APIs["RidList"] // Keys // Rest, #]&;
43 | VideoSection[id_Integer] := Module[
44 | {get = URLExecute[$APIs["VideoSection"][id], "RawJson"]},
45 | If[!VideoSectionQ[id], Echo[Text@"编号不存在!", "Warning: "];Return@$Failed];
46 | BilibiliVideoSectionObject[<|
47 | "Me" -> $APIs["RidList"][id],
48 | "Parent" -> $APIs["RidList"][$APIs["RidList"][id, "parent"]],
49 | "Count" -> get["data", "page", "count"],
50 | "Date" -> Now
51 | |>]
52 | ];
53 |
54 |
55 |
56 | (* ::Subsection:: *)
57 | (*功能块 2*)
58 | Options[DownloadIDsRange] = {
59 | "Path" -> FileNameJoin[{$BilibiliLinkData, "VideoDataRaw"}],
60 | "Overwrite" -> False,
61 | "Format" -> "WXF",
62 | "LimitTime" -> 10
63 | };
64 | DownloadIDsRange[ps_, OptionsPattern[]] := Block[
65 | {file, do, data, fail},
66 | file = FileNameJoin[{OptionValue["Path"],
67 | StringRiffle[{100(First@ps - 1) + 1, 100Last[ps]}, "-"] <> "." <> OptionValue["Format"]}
68 | ];
69 | If[
70 | OptionValue["Overwrite"],
71 | If[FileExistsQ@file, DeleteFile[file]],
72 | If[FileExistsQ@file, Return[Nothing]]
73 | ];
74 | do = URLExecute[HTTPRequest["https://api.bilibili.com/x/article/archives?ids=" <>
75 | StringRiffle[Range[100(# - 1) + 1, 100#], ","], TimeConstraint -> OptionValue["LimitTime"]
76 | ], "RawJson"]["data"]&;
77 | {data, fail} = Quiet@Reap@Flatten[List @@@ Map[Check[do[#], Sow[#]]&, ps]];
78 | Export[file, Flatten[data], PerformanceGoal -> "Size"];
79 | Return[fail]
80 | ];
81 | VideoMaxID[] := Module[
82 | {get, case},
83 | get = URLExecute["http://www.jijidown.com/new/video", {"HTML", "XMLObject"}];
84 | case = Cases[get, XMLElement["img", {__, "src" -> u_, __}, __] :> u, Infinity];
85 | Max@StringCases[case, "av=" ~~ id__ ~~ "&url" :> ToExpression[id]]
86 | ];
87 | Options[VideoIDsRange] = {
88 | "Path" -> Automatic,
89 | "LimitTime" -> 4,
90 | "Overwrite" -> False,
91 | "Format" -> "WXF",
92 | "BlockSize" -> 10000,
93 | "Min" -> 1
94 | };
95 | VideoIDsRange[max_Integer : 0, OptionsPattern[]] := Module[
96 | {m, path, do, r, funs, fail, log},
97 | m = If[max == 0, VideoMaxID[], max];
98 | path = If[OptionValue["Path"] === Automatic,
99 | FileNameJoin[{$BilibiliLinkData, "VideoData",
100 | DateString[{"Year", "Month", "Day", "Hour", "Minute", "Second"}]
101 | }],
102 | OptionValue["Path"]
103 | ];
104 | If[!FileExistsQ@path, CreateDirectory[path]];
105 | do = Inactive[DownloadIDsRange][#,
106 | "Path" -> path,
107 | "Overwrite" -> OptionValue["Overwrite"],
108 | "Format" -> OptionValue["Format"],
109 | "LimitTime" -> OptionValue["LimitTime"]
110 | ]&;
111 | r = Range[Ceiling[OptionValue["Min"] / 100], Ceiling[m / 100]];
112 | funs = do /@ Partition[r, UpTo[Ceiling[OptionValue["BlockSize"] / 100]]];
113 | fail = AbortableMap[Activate, funs];
114 | log = FileNameJoin[{path, DateString[{"Year", "Month", "Day", "-", "Hour", "Minute", "Second"}] <> ".log.m"}];
115 | Export[log, <|
116 | "Date" -> Now,
117 | "FailedIDs" -> Flatten[fail[[-2, All, 2]]],
118 | "RetryFunction" -> "BilibiliLink`Video`DownloadIDsRange[...]"
119 | |>]
120 | ];
121 | DistributeDefinitions[VideoIDsRange];
122 | (* ::Subsection:: *)
123 | (*功能块 2*)
124 | Options[DownloadIDsList] = {
125 | "Path" -> FileNameJoin[{$BilibiliLinkData, "VideoDataRaw"}],
126 | "Overwrite" -> False,
127 | "Format" -> "WXF",
128 | "LimitTime" -> 10
129 | };
130 | DownloadIDsList[ls_, OptionsPattern[]] := Block[
131 | {file, group, do, data, fail},
132 | file = FileNameJoin[{OptionValue["Path"], Hash[ls, "MD5", "HexString"] <> "." <> OptionValue["Format"]}];
133 | If[
134 | OptionValue["Overwrite"],
135 | If[FileExistsQ@file, DeleteFile[file]],
136 | If[FileExistsQ@file, Return[Nothing]]
137 | ];
138 | group = Partition[ls, UpTo[100]];
139 | do = URLExecute[HTTPRequest["https://api.bilibili.com/x/article/archives?ids=" <>
140 | StringRiffle[#, ","], TimeConstraint -> OptionValue["LimitTime"]
141 | ], "RawJson"]["data"]&;
142 | {data, fail} = Quiet@Reap@Flatten[List @@@ Map[Check[do[#], Sow[#]]&, group]];
143 | Export[file, Flatten[data], PerformanceGoal -> "Size"];
144 | Return[fail]
145 | ];
146 | Options[VideoIDsList] = {
147 | "Path" -> Automatic,
148 | "LimitTime" -> 4,
149 | "Overwrite" -> False,
150 | "Format" -> "WXF",
151 | "BlockSize" -> 10000
152 | };
153 | VideoIDsList[ls_, OptionsPattern[]] := Block[
154 | {path, do, fail, funs, log},
155 | path = If[OptionValue["Path"] === Automatic,
156 | FileNameJoin[{$BilibiliLinkData, "VideoData",
157 | DateString[{"Year", "Month", "Day", "Hour", "Minute", "Second"}]}
158 | ],
159 | OptionValue["Path"]
160 | ];
161 | If[!FileExistsQ@path, CreateDirectory[path]];
162 | do = Inactive[DownloadIDsList][#,
163 | "Path" -> path,
164 | "Overwrite" -> OptionValue["Overwrite"],
165 | "Format" -> OptionValue["Format"],
166 | "LimitTime" -> OptionValue["LimitTime"]
167 | ]&;
168 | funs = do /@ Partition[ls, UpTo[Ceiling[OptionValue["BlockSize"] / 100]]];
169 | fail = AbortableMap[Activate, funs];
170 | log = FileNameJoin[{path, DateString[{"Year", "Month", "Day", "-", "Hour", "Minute", "Second"}] <> ".log.m"}];
171 | Export[log, <|
172 | "Date" -> Now;
173 | "FailedIDs" -> Flatten[fail]
174 | |>]
175 | ];
176 | DistributeDefinitions[VideoIDsList];
177 |
178 |
179 |
180 | (* ::Subsection:: *)
181 | (*功能块 2*)
182 | VideoIdsFormat[asc_] := <|
183 | "VideoID" -> asc["aid"],
184 | "Title" -> asc["title"],
185 | "Date" -> FromUnixTime[asc["pubdate"]],
186 | "Length" -> asc["duration"],
187 | "Pages" -> asc["videos"],
188 | "Region" -> asc["tid"],
189 | "CID" -> asc["cid"],
190 | "OwnerID" -> asc["owner", "mid"],
191 | "OwnerName" -> asc["owner", "name"],
192 | "View" -> asc["stat", "view"],
193 | "Favorite" -> asc["stat", "favorite"],
194 | "Coin" -> asc["stat", "coin"],
195 | "Share" -> asc["stat", "share"],
196 | "Like" -> asc["stat", "like"],
197 | "Dislike" -> asc["stat", "dislike"],
198 | "Comment" -> asc["stat", "reply"],
199 | "HighestRank" -> asc["stat", "his_rank"]
200 | |>;
201 | (* ::Subsection:: *)
202 | (*功能块 2*)
203 | Options[VideoIDsPack] = {
204 | "Pack" -> 1000,
205 | "Path" -> FileNameJoin[{$BilibiliLinkData, "VideoDataRaw"}],
206 | "Format" -> "WXF"
207 | };
208 | VideoIDsPack[fs_List, {num_ : 0}, OptionsPattern[]] := Block[
209 | {data, file, fmt},
210 | file = FileNameJoin[{OptionValue["Path"], "Block_" <> ToString[num] <> ".WXF"}];
211 | If[FileExistsQ@file, Return[Nothing]];
212 | data = Select[Flatten[Import /@ fs], AssociationQ];
213 | fmt = SortBy[VideoIdsFormat /@ data, #["VideoID"]&] /. {Missing[__] :> ""};
214 | Export[file, Dataset@fmt, PerformanceGoal -> "Size"];
215 | Length@fmt
216 | ];
217 | VideoIDsPack[dir_String, ops : OptionsPattern[]] := Block[
218 | {all},
219 | If[!DirectoryQ[OptionValue["Path"]], VideoIDsPack[{dir}]];
220 | If[!FileExistsQ[OptionValue["Path"]], CreateDirectory[OptionValue["Path"]]];
221 | all = SortBy[FileNames[{"*.WXF", "*.Json"}, dir], ToExpression[StringSplit[#, {"\\", "-"}][[-2]]]&];
222 | MapIndexed[AbsoluteTiming@VideoIDsPack[#, ops]&, Partition[all, UpTo[OptionValue["Pack"]]]]
223 | ];
224 |
225 |
226 | (* ::Subsection:: *)
227 | (*功能块 2*)
228 | VideoIDsInsertPack[fs_, co_] := Block[
229 | {in = Select[Flatten[Import /@ fs], AssociationQ]},
230 | MongoLink`MongoCollectionInsert[co, Map[VideoIdsFormat, in] /. Missing[__] :> ""];
231 | Length[in]
232 | ] // AbsoluteTiming;
233 | Options[VideoIDsInsertDB] = {"BatchSize" -> 1};
234 | VideoIDsInsertDB[dir_String, db_, OptionsPattern[]] := Block[
235 | {client, all, pt, tasks, ans, i = 0, j = 0, now = Now},
236 | all = SortBy[FileNames[{"*.WXF", "*.Json"}, dir], ToExpression[StringSplit[#, {"\\", "-"}][[-2]]]&];
237 | pt = Partition[all, UpTo[OptionValue["BatchSize"]]];
238 | ans = With[
239 | {table = MongoLink`MongoGetCollection[db, StringJoin["VideoData_",
240 | DateString[{"Year", "Month", "Day", "Hour", "Minute", "Second"}]
241 | ]]},
242 | Monitor[Map[
243 | Reap[Check[i++;VideoIDsInsertPack[#, table], j++; Sow[#]]
244 | ]& , pt],
245 | Grid[{
246 | {Text[Style["Transforming :", Darker@Blue]], ProgressIndicator[i, {0, Length[pt]}]},
247 | {
248 | Text[Style["Error Cases : ", Darker@Red]],
249 | StringJoin[ToString /@ {j, " --- Time Left: ", timeLeft[AbsoluteTime[now], (i + j ) / Length[pt]]}]
250 | }
251 | },
252 | Alignment -> Left,
253 | Dividers -> Center
254 | ]
255 | ]
256 | ];
257 | Echo[Quantity[Total[ans[[All, 1, 2]]] / Total[ans[[All, 1, 1]]], "Kilobytes" / "Seconds"], "Speed: "];
258 | <|"Failed" -> Flatten[ans[[All, -1]]]|>
259 | ];
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 | TagInfoFormat[asc_] := <|
277 | "ID" -> asc["tag_id"],
278 | "Name" -> asc["tag_name"],
279 | "Detail" -> asc["content"],
280 | "Date" -> FromUnixTime[asc["ctime"]],
281 | "Count" -> asc["count", "use"],
282 | "Watch" -> asc["count", "atten"]
283 | |>;
284 | (*
285 | 屏蔽字段
286 | - tag 图标 "Icon"->asc["cover"]
287 | - type, 意义不明
288 | *)
289 | TagInfo[id_] := TagInfoFormat[URLExecute["https://api.bilibili.com/x/tag/info?tag_id=" <> ToString[id], "RawJSON"]["data"]];
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 | (* ::Subsection::Closed:: *)
303 | (*附加设置*)
304 | SetAttributes[{TagInfo}, Listable];
305 | SetAttributes[
306 | { },
307 | {Protected, ReadProtected}
308 | ];
309 | End[]
310 |
--------------------------------------------------------------------------------
/Packages/Crawlers/ArchiveCrawlers.nb:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:3c479a2cd6e4355ae8458f395fbc9a065ecd72d457284b9d91b422586c494276
3 | size 48448
4 |
--------------------------------------------------------------------------------
/Packages/Crawlers/TagCrawlers.nb:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:8a18f5b8e3898318e6182e41724c7aed68913805a3e2a08613f9a051af35fe4d
3 | size 32735
4 |
--------------------------------------------------------------------------------
/Packages/ObjectAlbum.m:
--------------------------------------------------------------------------------
1 | BilibiliAlbumObject::usage = "内部函数, 图片地址对象.";
2 | BilibiliLink`ㄑAlbum::usage = "";
3 | BilibiliLink`ㄑAlbum[___] := "";
4 | Begin["`Object`"];
5 | (*BilibiliAlbumObject*)
6 | BilibiliAlbumObjectQ::usage = "BilibiliAlbumObject 合法性检测";
7 | BilibiliAlbumObjectQ[asc_?AssociationQ] := AllTrue[{"Count", "Date"}, KeyExistsQ[asc, #]&];
8 | BilibiliAlbumObjectQ[_] := False;
9 |
10 | Format[BilibiliAlbumObjectQ[___], OutputForm] := "BilibiliDownloadObject[>_<]";
11 | Format[BilibiliAlbumObjectQ[___], InputForm] := "BilibiliDownloadObject[>_<]";
12 | BilibiliAlbumObject /: MakeBoxes[obj : BilibiliAlbumObject[asc_?BilibiliAlbumObjectQ], form : (StandardForm | TraditionalForm)] := Module[
13 | {above, below},
14 | above = {
15 | {BoxForm`SummaryItem[{"Type: ", "PicturesPack"}]},
16 | {BoxForm`SummaryItem[{"Category: ", asc["Category"]}]},
17 | {BoxForm`SummaryItem[{"Date: ", DateString[asc["Date"]]}]},
18 | {BoxForm`SummaryItem[{"Repo: ", asc["Repo"]}]},
19 | {BoxForm`SummaryItem[{"Count: ", asc["Count"]}]},
20 | {BoxForm`SummaryItem[{"Size: ", AlbumSizeConvert[asc["Size"]]}]},
21 | {BoxForm`SummaryItem[{"Time: ", asc["Time"]}]}
22 | };
23 | below = {};
24 | BoxForm`ArrangeSummaryBox[
25 | "BilibiliLink", obj,
26 | $BilibiliLinkIcons["BilibiliAlbumObject"],
27 | above, below, form,
28 | "Interpretable" -> Automatic
29 | ]
30 | ];
31 | (*Aid Functions*)
32 | AlbumSizeConvert[x_Integer] := N@Piecewise[{
33 | {Quantity[x, "Kilobytes"], x < 1024 / 2},
34 | {Quantity[x / 1024, "Megabytes"], 1024^2 / 2 > x >= 1024 / 2},
35 | {Quantity[x / 1024^2, "Gigabytes"], x >= 1024^2 / 2}
36 | }];
37 | Options[ImageSizeConvert] = {Format -> "webp"};
38 | ImageSizeConvert[size_, OptionsPattern[]] := Switch[
39 | size,
40 | Tiny, "@125w_125h_1e." <> OptionValue[Format],
41 | Small, "@250w_250h_1e." <> OptionValue[Format],
42 | Normal, "@500w_500h_1e." <> OptionValue[Format],
43 | Large, "@1000w_1000h_1e." <> OptionValue[Format],
44 | RawData, "",
45 | _, size
46 | ];
47 | MapMonitored[f_, args_List] := Module[
48 | {x = 0},
49 | Monitor[
50 | MapIndexed[(x = #2[[1]];f[#1])&, args],
51 | ProgressIndicator[x / Length[args]]
52 | ]
53 | ];
54 |
55 |
56 |
57 |
58 | (*Interface*)
59 | BilibiliAlbumObject[ass_][func_String] := Switch[
60 | func,
61 | "d", BilibiliAlbumObject[ass]["Data"],
62 | "Data", Lookup[ass, "Data"],
63 | "i", BilibiliAlbumObject[ass]["Image"],
64 | "Image", Flatten["imgs" /. Lookup[ass, "Data"]],
65 | "m", BilibiliAlbumObject[ass]["Markdown"],
66 | "Markdown", PicturesPackMarkdownExport[ass],
67 | "do", AlbumDownload[ass]["Download"],
68 | "Download", AlbumDownload[ass],
69 | _, BilibiliAlbumObjectHelp[]
70 | ];
71 | BilibiliAlbumObject[ass_][func_String, {para__}] := Switch[
72 | func,
73 | "Download", AlbumDownload[ass, para],
74 | _, BilibiliAlbumObjectHelp[]
75 | ];
76 | BilibiliAlbumObject[ass_][___] := BilibiliAlbumObjectHelp[];
77 |
78 |
79 | (*Method*)
80 | PicturesPackMarkdownExport[ass_] := Block[
81 | {text = PicturesPack2MD[Lookup[ass, "Data"]], name, file},
82 | name = DateString[Lookup[ass, "Date"], {"Year", "-", "Month", "-", "Day", "-"}] <> ToString[Hash@text] <> ".md";
83 | file = FileNameJoin[{$BilibiliLinkData, "Markdown", name}];
84 | If[FileExistsQ[file], Return[file], CreateFile[file]];
85 | Export[file, text, "Text"]
86 | ];
87 | PicturesPack2MD::usage = "将Album对象中的数据导出为Markdown格式.";
88 | PicturesPack2MD[docs_List] := StringJoin[PicturesPack2MD /@ docs];
89 | PicturesPack2MD[doc_Association] := StringJoin@Riffle[Join[
90 | {
91 | "### 作者: " <> doc["author"],
92 | "### 主页: " <> "https://space.bilibili.com/" <> ToString[doc["uid"]] <> "/#/album",
93 | "### 标题: " <> doc["title"],
94 | "### 日期: " <> DateString@doc["time"],
95 | "### 链接: " <> "https://h.bilibili.com/" <> ToString[doc["did"]]
96 | },
97 | ""& /@ doc["imgs"],
98 | {"\r---\r\r"}
99 | ], "\r"];
100 |
101 | Options[AlbumCollage] = {
102 | Max -> 25,
103 | ItemSize -> Small,
104 | ImageSize -> Automatic,
105 | AspectRatio -> GoldenRatio
106 | };
107 | AlbumCollage[ass_, OptionsPattern[]] := Module[
108 | {imgs, get, fliter, $now = Now, ar = OptionValue[AspectRatio]},
109 | imgs = RandomSample[Flatten["imgs" /. ass["Data"]], UpTo[OptionValue[Max]]];
110 | get = MapMonitored[URLExecute[# <> ImageSizeConvert[OptionValue[ItemSize]]]&, imgs];
111 | fliter = Select[get, 1 / ar < ImageAspectRatio[#] < ar&];
112 | Echo[Now - $now, "Time Used:"];
113 | ImageCollage[fliter, Background -> Transparent, Method -> "Rows", ImageSize -> OptionValue[ImageSize]]
114 | ];
115 | Options[AlbumDownload] = {
116 | ImageSize -> RawData,
117 | Format -> "webp",
118 | Path -> FileNameJoin[{$BilibiliLinkData, "Image", ass["Category"]}]
119 | };
120 | AlbumDownload[ass_, OptionsPattern[]] := Module[
121 | {data},
122 | data = Function[doc,
123 | <|"Name" -> Last@StringSplit[#, "/"], "URL" -> #|>& /@
124 | (# <> ImageSizeConvert[OptionValue[ImageSize], Format -> OptionValue[Format]]& /@ doc["imgs"])
125 | ][Flatten[reshape /@ ass["Data"]]];
126 | BilibiliDownloadObject[<|
127 | "Date" -> ass["Date"],
128 | "Category" -> ass["Category"],
129 | "Data" -> data,
130 | "Path" -> OptionValue[Path],
131 | "Size" -> ass["Size"]
132 | |>]
133 | ];
134 |
135 |
136 |
137 | SetAttributes[
138 | {},
139 | {Protected, ReadProtected}
140 | ];
141 | End[]
142 |
--------------------------------------------------------------------------------
/Packages/ObjectDownload.m:
--------------------------------------------------------------------------------
1 | BilibiliDownload::usage = "";
2 | BilibiliDownloadObject::usage = ToString[Column[{
3 | Row[{"初始化下载对象, ",Style["obj = BilibiliLink[...,Type->DownloadObject]",Blue]}],
4 | Row[{Style["\t快速下载: ",Bold],"obj@\"do\""}],
5 | Row[{Style["\t转换为md格式: ",Bold],"obj@\"m\""}],
6 | Row[{Style["\t提取原始数据: ",Bold],"obj@\"d\""}],
7 | Row[{Style["完整指令: ",Red,Bold],"简令: 指令 - 函数"}],
8 | "\td: Data",
9 | "\tm: MarkDown",
10 | "\tdo: Download - BilibiliDownload"
11 | }],StandardForm];
12 | BilibiliLink`ㄑDownload::usage = "";
13 | BilibiliLink`ㄑDownload[___] := "";
14 | Begin["`Object`"];
15 | BilibiliDownloadObjectQ::usage = "BilibiliDownloadObject 合法性检测";
16 | BilibiliDownloadObjectQ[asc_?AssociationQ] := AllTrue[{"Path", "Data"}, KeyExistsQ[asc, #]&];
17 | BilibiliDownloadObjectQ[_] := False;
18 | Format[BilibiliDownloadObject[___], OutputForm] := "BilibiliDownloadObject[<>]";
19 | Format[BilibiliDownloadObject[___], InputForm] := "BilibiliDownloadObject[<>]";
20 | BilibiliDownloadObject /: MakeBoxes[obj : BilibiliDownloadObject[asc_?BilibiliDownloadObjectQ], form : (StandardForm | TraditionalForm)] := Module[
21 | {above, below},
22 | above = {
23 | {BoxForm`SummaryItem[{"Type: ", "DownloadObject"}]},
24 | {BoxForm`SummaryItem[{"Category: ", asc["Category"]}]},
25 | {BoxForm`SummaryItem[{"Count: ", Length@asc["Data"]}]},
26 | {BoxForm`SummaryItem[{"Size: ", DownloadSizeConvert[asc["Size"]]}]}
27 | };
28 | below = {
29 | {BoxForm`SummaryItem[{"Date: ", DateString[asc["Date"]]}]},
30 | {BoxForm`SummaryItem[{"Path: ", File[asc["Path"]]}]}
31 | };
32 | BoxForm`ArrangeSummaryBox[
33 | "BilibiliLink", obj,
34 | $BilibiliLinkIcons["BilibiliDownloadObject"],
35 | above, below, form,
36 | "Interpretable" -> Automatic
37 | ]
38 | ];
39 |
40 | (*Aid Functions*)
41 | DownloadSizeConvert[x_] := N@Piecewise[{
42 | {Quantity[x / 1024^0, "Bytes"], x < 1024 / 2},
43 | {Quantity[x / 1024^1, "Kilobytes"], 1024^2 / 2 > x >= 1024^1 / 2},
44 | {Quantity[x / 1024^2, "Megabytes"], 1024^3 / 2 > x >= 1024^2 / 2},
45 | {Quantity[x / 1024^3, "Gigabytes"], x >= 1024^3 / 2}
46 | }];
47 |
48 |
49 | BilibiliDownloadObject[ass_][func_String] := Switch[
50 | func,
51 | "do", BilibiliDownload[ass],
52 | "Download", BilibiliDownload[ass],
53 | "d", Dataset[ass["Data"]],
54 | "Data", Dataset[ass["Data"]],
55 | _, Information[BilibiliDownloadObject]
56 | ];
57 | BilibiliDownloadObject[ass_][func_String, {para__}] := Switch[
58 | func,
59 | "Download", BilibiliDownload[ass, para],
60 | _, Information[BilibiliDownloadObject]
61 | ];
62 | BilibiliDownloadObject[ass_][___] := BilibiliDownloadHelp[];
63 |
64 | BilibiliDownload[BilibiliDownloadObject[ass_]] := BilibiliDownload[ass];
65 |
66 |
67 | Options[BilibiliDownloadLine] = {Path -> $TemporaryDirectory, Method -> URLDownloadSubmit};
68 | BilibiliDownloadLine[line_, OptionsPattern[]] := Block[
69 | {path = OptionValue[Path], file},
70 | file = FileNameJoin[{path, line["Name"] <> "." <> Last@StringSplit[line["URL"], "."]}];
71 | If[FileExistsQ@file, Return[]];
72 | OptionValue[Method][line["URL"], file]
73 | ];
74 | Options[BilibiliDownload] = {
75 | Path -> Automatic,
76 | Method -> URLDownloadSubmit,
77 | Return -> True
78 | };
79 | BilibiliDownload[ass_, OptionsPattern[]] := Block[
80 | {data = ass["Data"], path},
81 | path = If[OptionValue[Path] == Automatic, ass["Path"], OptionValue[Path]];
82 | If[!FileExistsQ[path], CreateDirectory[path]];
83 | BilibiliDownloadLine[#, Path -> path, Method -> OptionValue[Method]]& /@ data;
84 | If[OptionValue[Return], Return[ass["Path"]]];
85 | ];
86 |
87 |
88 | SetAttributes[
89 | {},
90 | {Protected, ReadProtected}
91 | ];
92 | End[]
93 |
--------------------------------------------------------------------------------
/Packages/ObjectVideoSection.m:
--------------------------------------------------------------------------------
1 | BilibiliVideoSectionObject::usage = "";
2 | BilibiliLink`ㄑVideoSectionObject::usage = "";
3 | BilibiliLink`ㄑVideoSectionObject[___] := "";
4 | Begin["`Object`"];
5 | BilibiliVideoSectionObjectQ::usage = "BilibiliVideoSectionObject 合法性检测";
6 | BilibiliVideoSectionObjectQ[asc_?AssociationQ] := AllTrue[{"Me", "Parent", "Count", "Date"}, KeyExistsQ[asc, #]&];
7 | BilibiliVideoSectionObjectQ[_] = False;
8 | Format[BilibiliVideoSectionObject[___], OutputForm] := "BilibiliVideoSectionObject[<>]";
9 | Format[BilibiliVideoSectionObject[___], InputForm] := "BilibiliVideoSectionObject[<>]";
10 | BilibiliVideoSectionObject /: MakeBoxes[obj : BilibiliVideoSectionObject[asc_?BilibiliVideoSectionObjectQ], form : (StandardForm | TraditionalForm)] := Module[
11 | {above, below},
12 | above = {
13 | {BoxForm`SummaryItem[{"Type: ", "VideoSection"}]},
14 | {BoxForm`SummaryItem[{"Section: ", asc["Me"]["name"]}]},
15 | {BoxForm`SummaryItem[{"Link: ", Hyperlink[StringSplit[#["url"], {"/", "."}][[-2]], #["url"]]&[asc["Me"]]}]}
16 | };
17 | below = {
18 | {BoxForm`SummaryItem[{"Count: ", asc["Count"]}]},
19 | {BoxForm`SummaryItem[{"Parent: ", Hyperlink[#["name"], #["url"]]&[asc["Parent"]]}]},
20 | {BoxForm`SummaryItem[{"Date: ", DateString[asc["Date"]]}]}
21 | };
22 | BoxForm`ArrangeSummaryBox[
23 | "BilibiliLink",
24 | obj,
25 | $BilibiliLinkIcons["BilibiliVideoSectionObject"],
26 | above,
27 | below,
28 | form,
29 | "Interpretable" -> Automatic]
30 | ];
31 | SetAttributes[
32 | {BilibiliVideoSectionObject},
33 | {Protected, ReadProtected}
34 | ];
35 | End[];
36 |
--------------------------------------------------------------------------------
/Packages/__Dev/!BilibiliColumns.m:
--------------------------------------------------------------------------------
1 | BilibiliArticle::usage = "将HTML转化为Markdown格式.";
2 | (* ::Section:: *)
3 | (*程序包正体*)
4 | Begin["`Columns`"];
5 | (* ::Subsection::Closed:: *)
6 | (*主体代码*)
7 | (* ::Subsubsection:: *)
8 | (*下载并转化专栏*)
9 | Options[BilibiliArticle] = {Debug -> False};
10 | BilibiliArticle[cv_, OptionsPattern[]] := Block[
11 | {
12 | xml, pre, body,
13 | raw = Import["https://www.bilibili.com/read/cv" <> ToString@cv, {"HTML", "XMLObject"}]
14 | },
15 | xml = Flatten@Cases[raw, XMLElement["div", {"class" -> "article-holder"}, t___] :> t, Infinity, 1];
16 | pre = xml /. {
17 | XMLElement["h1", {}, {h__}] :> StringJoin["\n# ", h, "\n"],
18 | XMLElement["h2", {}, {h__}] :> StringJoin["\n## ", h, "\n"],
19 | XMLElement["h3", {}, {h__}] :> StringJoin["\n### ", h, "\n"],
20 | XMLElement["h4", {}, {h__}] :> StringJoin["\n#### ", h, "\n"],
21 | XMLElement["h5", {}, {h__}] :> StringJoin["\n##### ", h, "\n"],
22 | XMLElement["h6", {}, {h__}] :> StringJoin["\n###### ", h, "\n"],
23 | XMLElement["strong", {}, {b_}] :> StringJoin["**", b, "**"], (*粗体标识*)
24 | XMLElement["div", ___, {text___}] :> text,
25 | XMLElement["figure", err___] :> Nothing, (*错误解析, 直接删除*)
26 | XMLElement["figcaption", err___] :> Nothing, (*错误解析, 直接删除*)
27 | XMLElement["img", {"data-src" -> img_, __}, {}] :> StringJoin[""],
28 | XMLElement["img", {"class" -> _, "data-src" -> img_}, {}] :> StringJoin[""],
29 | XMLElement["img", {"class" -> "video-card nomal", "data-src" -> img_, __, "aid" -> aid_, __}, {}] :> StringTemplate[
30 | "[](www.bilibili.com/blackboard/player.html?aid=`aid`)"
31 | ][<|"img" -> img, "aid" -> aid|>],
32 | XMLElement["hr", ___] :> "\n---\n"
33 | };
34 | body = pre /. {
35 | XMLElement["p", {}, {para___}] :> StringJoin["\n", para, "\n"], (*段落标识*)
36 | XMLElement["blockquote", {}, q_] :> StringJoin@Riffle[q, "> ", {1, -1, 3}],
37 | XMLElement["ul", {}, {ul__}] :> StringJoin["\n", ul, "\n"],
38 | XMLElement["li", {}, {li__}] :> StringJoin["> ", li, "\n"]
39 | };
40 | If[OptionValue[Debug], Return[body], StringJoin[ToString /@ body]]
41 | ];
42 | (*(*读入预处理*)
43 | text=URLExecute["https://www.bilibili.com/read/cv423670","Text",CharacterEncoding->"UTF8"];
44 | raw=ImportString[StringReplace[text,Thread[{"span","br"}->"div"]],{"HTML","XMLObject"}];
45 | *)
46 | (*(*span替换*)
47 | $ColorMapArticle=<|
48 | "color-blue-01"\[Rule]"#56c1fe","color-lblue-01"\[Rule]"#73fdea","color-green-01"\[Rule]"#89fa4e","color-yellow-01"\[Rule]"#fff359","color-pink-01"\[Rule]"#ff968d","color-purple-01"\[Rule]"#ff8cc6","color-blue-02"\[Rule]"#02a2ff","color-lblue-02"\[Rule]"#18e7cf","color-green-02"\[Rule]"#60d837","color-yellow-02"\[Rule]"#fbe231","color-pink-02"\[Rule]"#ff654e","color-purple-02"\[Rule]"#ef5fa8","color-blue-03"\[Rule]"#0176ba","color-lblue-03"\[Rule]"#068f86","color-green-03"\[Rule]"#1db100","color-yellow-03"\[Rule]"#f8ba00","color-pink-03"\[Rule]"#ee230d","color-purple-03"\[Rule]"#cb297a","color-blue-04"\[Rule]"#004e80","color-lblue-04"\[Rule]"#017c76","color-green-04"\[Rule]"#017001","color-yellow-04"\[Rule]"#ff9201","color-pink-04"\[Rule]"#b41700","color-purple-04"\[Rule]"#99195e","color-gray-01"\[Rule]"#d6d5d5","color-gray-02"\[Rule]"#929292","color-gray-03"\[Rule]"#5f5f5f","color-default"\[Rule]"#222"
49 | |>;
50 | XMLElement["span",{"class"\[Rule]class_},{text_}]\[RuleDelayed]StringTemplate[
51 | "`text`"][Association[
52 | "color"\[Rule]First[StringSplit["color-pink-03 font-size-20"," "]/.\[VeryThinSpace]$ColorMapArticle]],"text"\[Rule]text
53 | ]
54 | *)
55 |
56 | (* ::Subsection::Closed:: *)
57 | (*附加设置*)
58 | SetAttributes[
59 | {},
60 | {Protected, ReadProtected}
61 | ];
62 | End[]
--------------------------------------------------------------------------------
/Packages/__Dev/Album.m:
--------------------------------------------------------------------------------
1 | PhotosLeaderboard::usage = "h.bilibili.com 图片作品排行榜.";
2 |
3 |
4 | BilibiliAlbumIndex::usage = "";
5 | BilibiliAlbumIndex[] := Module[
6 | {$now = Now, get, bg, imgs, data},
7 | get = URLExecute[$PhotosAPI["Home"], "RawJSON"]["data"];
8 | bg = <|"Name" -> ToString[Now // UnixTime] <> "_0", "URL" -> get["bg_img"]|>;
9 | imgs = MapIndexed[<|"Name" -> StringJoin[ToString /@ {UnixTime@Now, _, First@#2}], "URL" -> #1|>&, "img_src" /. get["items"]];
10 | data = <|
11 | "DataType" -> "AlbumIndexPage",
12 | "ImageList" -> Prepend[imgs, bg]
13 | |>;
14 | BilibiliAlbumObject[<|
15 | "Data" -> data,
16 | "Category" -> "Album Index Page",
17 | "Repo" -> Length[get["items"]] + 1,
18 | "Count" -> Length[get["items"]] + 1,
19 | "Size" -> Total@Select["img_size" /. get["items"], IntegerQ],
20 | "Time" -> Now - $now,
21 | "Date" -> $now
22 | |>]
23 | ];
24 |
25 |
26 |
27 |
28 |
29 | (* ::Subsection::Closed:: *)
30 | (*PhotosLeaderboard*)
31 | PictureDataRebuild::usage = "内部函数, 用于数据清洗";
32 | PictureDataRebuild[doc_Association] := <|
33 | "uid" -> doc["user", "uid"],
34 | "author" -> doc["user", "name"],
35 | "did" -> doc["item", "doc_id"],
36 | "title" -> doc["item", "title"],
37 | "time" -> FromUnixTime[doc["item", "upload_time"]],
38 | "imgs" -> ("img_src" /. doc["item", "pictures"]),
39 | "size" -> If[KeyExistsQ[First@doc["item", "pictures"], "img_size"],
40 | Quantity[Total["img_size" /. doc["item", "pictures"]] / 1024.0, "Megabytes"],
41 | Missing
42 | ]
43 | |>;
44 | $PhotoMap = <|"Cosplay" -> "cos", "其他服饰" -> "sifu", "插画" -> "illustration", "漫画" -> "comic", "其他画作" -> "draw", "全部画作" -> "all"|>;
45 | PhotosLeaderboard[cat_] := Module[
46 | {$now = Now, map, raw, data},
47 | map = Switch[cat,
48 | "Cosplay", $APIs["PhotoHot"]["cos"],
49 | "其他服饰", $APIs["PhotoHot"]["sifu"],
50 | "插画作品", $APIs["PhotoHot"]["illustration"],
51 | "漫画作品", $APIs["PhotoHot"]["comic"],
52 | "其他画作", $APIs["PhotoHot"]["draw"],
53 | "全部画作", $APIs["PhotoHot"]["all"],
54 | "日榜", $APIs["PhotoRank"]["day"],
55 | "周榜", $APIs["PhotoRank"]["week"],
56 | "月榜", $APIs["PhotoRank"]["month"],
57 | _, Echo[Text@"可选参数:Cosplay,其他服饰,插画作品,漫画作品,其他画作,全部画作,日榜,周榜,月榜"];Return[$Failed]
58 | ];
59 | raw = URLExecute[HTTPRequest[#, TimeConstraint -> 10], "RawJSON"]["data", "items"]& /@ map;
60 | data = PictureDataRebuild /@ Flatten[raw];
61 | BilibiliPicturePackObject[<|
62 | "Data" -> data,
63 | "Category" -> Text@cat,
64 | "Repo" -> Length@data,
65 | "Count" -> Length@Flatten["imgs" /. data],
66 | "Size" -> Total@DeleteCases["size" /. data, Missing],
67 | "Time" -> Now - $now,
68 | "Date" -> $now
69 | |>]
70 | ];
71 |
72 | AlbumDownload[raw_] := Switch[
73 | raw["Data", "DataType"],
74 | "AlbumIndexPage", AlbumIndexPageDownload[raw]
75 |
76 |
77 |
78 | ];
79 |
80 |
81 | Options[AlbumIndexPageDownload] = {ImageSize -> Full, Defer -> False};
82 | AlbumIndexPageDownload[ass_, OptionsPattern[]] := Block[
83 | {size = OptionValue[ImageSize], obj, resize},
84 | resize = <|"Name" -> #["Name"] <> ToString[size], "URL" -> #["URL"] <> ImageSizeConvert[size]|>&;
85 | obj = BilibiliDownloadObject[<|
86 | "Date" -> ass["Date"],
87 | "Category" -> ass["Data", "DataType"],
88 | "Data" -> (resize /@ ass["Data", "ImageList"]),
89 | "Path" -> FileNameJoin[{$BilibiliLinkData, "Image", "Album", "Index"}],
90 | "Size" -> Quantity[ass["Size"] / 1024., "Megabytes"]
91 | |>];
92 | If[OptionValue[Defer], Return[obj], obj["Download"]]
93 | ];
94 |
--------------------------------------------------------------------------------
/Packages/__Dev/BilibiliSearch.m:
--------------------------------------------------------------------------------
1 | tttttt = 1;
2 | Begin["`Search`"];
3 | tttttt = 1;
4 | End[];
--------------------------------------------------------------------------------
/Packages/__Dev/Proxy.m:
--------------------------------------------------------------------------------
1 | (* Mathematica Package *)
2 | (* Created by Mathematica Plugin for IntelliJ IDEA *)
3 |
4 | (* :Title: Proxy *)
5 | (* :Context: Proxy` *)
6 | (* :Author: Aster *)
7 | (* :Date: 2018-07-22 *)
8 |
9 | (* :Package Version: 0.1 *)
10 | (* :Mathematica Version: *)
11 | (* :Copyright: (c) 2018 Aster *)
12 | (* :Keywords: *)
13 | (* :Discussion: *)
14 |
15 | BeginPackage["Proxy`"]
16 | (* Exported symbols added here with SymbolName::usage *)
17 |
18 |
19 | TagURL[id_] := HTTPRequest[
20 | "http://api.bilibili.com/tags/info_description?id=" <> ToString[id],
21 | TimeConstraint -> 5
22 | ];
23 |
24 |
25 | Begin["`Private`"]
26 | TagFormat[asc_] := <|
27 | "ID" -> asc["tag_id"],
28 | "Name" -> asc["tag_name"],
29 | "Detail" -> asc["content"],
30 | "Date" -> FromUnixTime[asc["ctime"]],
31 | "Count" -> asc["count", "use"],
32 | "Watch" -> asc["count", "atten"]
33 | |>;
34 |
35 | TagDown[i_, try_] := Block[
36 | {get},
37 | If[try <= 0, AppendTo[i, failure]];
38 | get = URLExecute[HTTPRequest["http://api.bilibili.com/x/tag/info?tag_id=" <> ToString[i], TimeConstraint -> 5], "RawJSON"];
39 | If[
40 | Or[FailureQ@get, get["code"] != 0],
41 | AppendTo[$Tasks, Inactive[TagDown][i, try - 1]];
42 | retry++;Return[Nothing]
43 | ];
44 | finish++;
45 | TagFormat[get["data"]]
46 | ];
47 |
48 |
49 | GetMemberRequest[mid_] := HTTPRequest[
50 | "https://space.bilibili.com/ajax/member/GetInfo",
51 | <|
52 | "Method" -> "POST",
53 | "Headers" -> {
54 | "content-type" -> "application/x-www-form-urlencoded;charset=UTF-8",
55 | "user-agent" -> "Mozilla/5.0 (X11;Linux i686) AppleWebKit/534.24 (KHTML,like Gecko) Chrome/11.0.696.68 Safari/534.24",
56 | "Referer" -> "https://space.bilibili.com/" <> ToString[mid]
57 | },
58 | "Body" -> "mid=" <> ToString[mid] <> "&csrf="
59 | |>,
60 | TimeConstraint -> 10
61 | ];
62 | GetReg[id_] := Quiet@Block[
63 | {get = URLExecute[GetMemberRequest[id], "RawJSON"]},
64 | DateString[FromUnixTime[get["data", "regtime"]], {"Year", "Month", "Day"}] -> id
65 | ]
66 |
67 | End[] (* `Private` *)
68 |
69 | EndPackage[]
70 |
--------------------------------------------------------------------------------
/PacletInfo.m:
--------------------------------------------------------------------------------
1 | Paclet[
2 | Name -> "BilibiliLink",
3 | Version -> "0.4.0",
4 | BuildNumber -> "20180715",
5 | WolframVersion -> "11.3+",
6 | Creator -> "GalAster",
7 | Description -> "",
8 | Category -> "",
9 | Loading -> Manual,
10 | Extensions -> {
11 | {
12 | "Kernel",
13 | Root -> ".",
14 | Context -> {
15 | "BilibiliLink`"
16 | }
17 | }
18 | }
19 | ]
20 |
--------------------------------------------------------------------------------
/Readme.md:
--------------------------------------------------------------------------------
1 | # BilibiliLink — 乾杯 - ( ゜ᴗ ゜)つロ
2 |
3 | [](https://travis-ci.org/Moe-Net/BilibiliLink)
4 | [](https://www.wolfram.com/mathematica/)
5 | [](https://github.com/Moe-Net/BilibiliLink/releases)
6 | [](https://github.com/Moe-Net/BilibiliLink.git)
7 |
8 | 
9 |
10 | BilibiliLink 提供了一系列获取B站数据的方法, 计划中的内容有, 文章下载, 文章评论下载, 画师画作下载, 评论下载, cosplay下载, 视频跟踪等等.
11 |
12 | 有什么想要的功能也可以在 github issue 中提出哦!
13 |
14 | 但并非所有页面上的东西都能获得, 有些看着是文字, 其实是图片, 那就没法抓取了.
15 |
16 | [详细文档](https://bilibililink.netlify.com/)
17 |
18 | ## Install
19 | 
20 |
21 | 第一条命令安装, 第二条命令更新, 第三条命令卸载
22 | ```mma
23 | PacletInstall["BilibilliLink","Site"->"http://m.vers.site/"]
24 | PacletUpdate["BilibilliLink","Site"->"http://m.vers.site/"]
25 | PacletUninstall["BilibilliLink"]
26 | ```
27 |
28 | 对于开发者建议使用 [手动安装](https://github.com/Moe-Net/BilibiliLink/wiki/For-Developers).
29 |
30 | ## Show Time
31 | 
32 |
33 | ```mma
34 | << "BilibiliLink`
35 | PhotosLeaderboard["help"]
36 | link = PhotosLeaderboard["日榜"]
37 | link["Markdown"]
38 | ```
39 |
40 | ## Todo List
41 | 
42 |
43 | - 反正很多就是了
44 |
45 | ## Ideas
46 | 
47 | 1. 任何创意欢迎 git pull request, 或联系知乎[酱紫君](https://www.zhihu.com/people/GalAster).
48 | 2. 任何的意见和建议, 提交 github issue 或者加QQ群1014125反馈.
49 |
50 | |知乎主页|QQ群聊|
51 | |:-:|:-:|
52 | |[
](https://www.zhihu.com/people/GalAster)|[
](https://jq.qq.com/?_wv=1027&k=5BqFya1)
53 |
54 | - Copyrights of all pictures belong to **©bilibili.com**
55 | - License of this project under **@Mozilla Public License Version 2.0**
56 |
--------------------------------------------------------------------------------
/Resources/ico/BilibiliAlbumObject.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai4waifu/BilibiliLink/d5ad6bf72d56d112fd71c7b5a752fb01bb3c0b8d/Resources/ico/BilibiliAlbumObject.jpg
--------------------------------------------------------------------------------
/Resources/ico/BilibiliDownloadObject.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai4waifu/BilibiliLink/d5ad6bf72d56d112fd71c7b5a752fb01bb3c0b8d/Resources/ico/BilibiliDownloadObject.png
--------------------------------------------------------------------------------
/Resources/ico/BilibiliVideoSectionObject.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ai4waifu/BilibiliLink/d5ad6bf72d56d112fd71c7b5a752fb01bb3c0b8d/Resources/ico/BilibiliVideoSectionObject.png
--------------------------------------------------------------------------------
/Resources/ico/Readme.md:
--------------------------------------------------------------------------------
1 | ## 创始四图
2 | 
3 |
4 | Bilibili.us第一年用的四张壁纸, 我认为是本人考古的最高成就.
5 |
6 | ```mma
7 | {
8 | "http://i0.hdslb.com/Wallpaper/bilibili_chun.jpg",
9 | "http://i0.hdslb.com/Wallpaper/summer2_2011_1920.jpg",
10 | "http://i0.hdslb.com/Wallpaper/2011-autumn.jpg",
11 | "http://i0.hdslb.com/Wallpaper/2011-dong.png"
12 | }//URLExecute//ImageCollage
13 | ```
14 | ---
15 |
16 | ## Logos
17 | **hash:** [58c71871161412e2ad656485c9a89ecc](https://i0.hdslb.com/headers/58c71871161412e2ad656485c9a89ecc.png)
18 | 
19 |
20 | **hash:** [dd4053d635b32234e84ce58fb59206f3](https://i0.hdslb.com/headers/dd4053d635b32234e84ce58fb59206f3.png)
21 | 
22 |
23 | **hash:** [bdddec22494b50d792487028c17ece76](https://i0.hdslb.com/headers/bdddec22494b50d792487028c17ece76.png)
24 | 
25 |
26 | **hash:** [0944e505703d74c2fee96fe2bdc48d4d](https://i0.hdslb.com/headers/0944e505703d74c2fee96fe2bdc48d4d.png)
27 | 
28 |
29 | **hash:** [5b2a8933b2ed2a46d2e12ff9f4e4bc0b2cec45bf](https://i0.hdslb.com/bfs/archive/5b2a8933b2ed2a46d2e12ff9f4e4bc0b2cec45bf.png)
30 | 
31 |
32 | **hash:** [e07cbe482a00fef231688ece24ab459e8ff44b3f](https://i0.hdslb.com/bfs/archive/e07cbe482a00fef231688ece24ab459e8ff44b3f.png)
33 | 
34 |
35 | **hash:** [2fc95e205a40652ddc04ca7ed8ead57324fc68cd](https://i0.hdslb.com/bfs/archive/2fc95e205a40652ddc04ca7ed8ead57324fc68cd.png)
36 | 
37 |
38 | **hash:** [2fc95e205a40652ddc04ca7ed8ead57324fc68cd](https://i0.hdslb.com/bfs/archive/44a6c7979dfd332542c549513acabf907af06d2b.png)
39 | 
40 |
41 | ---
42 |
43 |
44 | 一些记载:
45 |
46 | 这个吧真是非常有趣
47 | http://dq.tieba.com/f?kw=bilibili%E7%9B%90&ie=utf-8
48 |
49 | 时光机:
50 | https://archive.li/drawyoo.hdslb.com
51 | https://archive.li/i0.hdslb.com
52 |
53 | 版头与Logo:
54 | https://www.biliplus.com/task/banner_fetch/
--------------------------------------------------------------------------------
/docs/.vuepress/config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | dest: 'docs/.build',
3 | locales: {
4 | '/': {
5 | lang: 'zh-CN',
6 | title: 'BBLink',
7 | description: 'Bilibili Connection Established!'
8 | }
9 | },
10 | serviceWorker: true,
11 | themeConfig: {
12 | repo: 'Moe-Net/BilibiliLink',
13 | editLinks: true,
14 | docsDir: 'docs',
15 | markdown: {
16 | lineNumbers: true
17 | },
18 | sidebar: [
19 | {
20 | title: '简介',
21 | children: [
22 | '/Start/',
23 | '/Start/Design.md',
24 | '/Start/Guide.md'
25 | ]
26 | },
27 | {
28 | title: '画友站',
29 | children: [
30 | '/Photo/',
31 | '/Photo/Object.md'
32 | ]
33 | },
34 | {
35 | title: '视频站',
36 | children: [
37 | '/Video/',
38 | '/Video/Object.md'
39 | ]
40 | },
41 | {
42 | title: '小功能',
43 | children: [
44 | '/Toys/'
45 | ]
46 | },
47 | {
48 | title: '全站爬虫',
49 | children: [
50 | '/Crawler/',
51 | '/Crawler/Video.md',
52 | '/Crawler/Tag.md'
53 |
54 | ]
55 | }
56 | ]
57 | }
58 | };
59 |
--------------------------------------------------------------------------------
/docs/.vuepress/override.styl:
--------------------------------------------------------------------------------
1 | $accentColor = #3eaf7c
2 | $textColor = #2c3e50
3 | $borderColor = #eaecef
4 | $codeBgColor = #282c34
5 | // 代码库重置
6 | .content pre{ margin: 0!important;}
7 |
--------------------------------------------------------------------------------
/docs/Crawler/Readme.md:
--------------------------------------------------------------------------------
1 | ## 全站爬虫简介
2 |
3 | 虽然 BBLink 本身并不是为了爬虫设计的, 而个人实际上也没有爬虫需要的大量硬盘、 内存、 时间、 代理资源.
4 |
5 | 但如果用户想获得大量的数据来研究的话, BBLink 也做得到.
6 |
7 | BBLink 可以从远程FTP服务器下载一些爬虫限制很死的信息, 同时可以自主抓取那些不是那么严格反爬的信息.
8 |
9 | ## 全站爬虫分类
10 |
11 |
12 | - AV 号遍历
13 | - UID 遍历
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/docs/Crawler/Tag.md:
--------------------------------------------------------------------------------
1 | # Tag 抓取日志
2 |
3 | 2018年7月9日执行了一次反查爬虫
4 | 已发现的最大 tid 为 7758024
5 | 其中有效 tid 有 3752764 个
6 | 预计遗漏 15% - 20%
7 |
--------------------------------------------------------------------------------
/docs/Crawler/Video.md:
--------------------------------------------------------------------------------
1 | # Video 抓取日志
2 |
3 | 全站视频爬虫依据 AV 号遍历所有视频.
4 |
5 | 当然你也可以不指定, 不指定会直接塞进 `$UserBaseDirectory`, 提醒你一下这个文件夹一般是在C盘的...
6 |
7 | 截止2018年上半年, B站视频ID总计有2600W, 其中有效ID号大约1800W.
8 |
9 | 
10 |
11 | CPU的内核数记为 X , 开启的内核越多速度越快, 但是相应每个内核的效率就越低
12 |
13 | 一般使用 4X 的内核, 6X 仍然能有少量提升, 但是内存占用就很高了, 8X 的话基本就得不偿失了.
14 |
15 | 一般来说要爬取一个小时左右, 速度大约是每秒 5400 条记录.
16 |
17 |
18 |
19 | 
20 |
21 | ## Database
22 |
23 |
24 | 当然这还没完, 只是下载了所有页面而已, 一般来说你得读进内存才能操作.
25 |
26 | 读取的话直接 `Import[path]` 即可, 但是问题在于全部读取需要约 20G 内存. 我想大多数人是没这么大内存了, 所以需要导入数据库.
27 |
28 |
29 |
30 | 把额外的内核全关了, 因为 mongodb 的端口就那点带宽, 线程开了好几个也是堵着.
31 |
32 | 
33 |
34 |
--------------------------------------------------------------------------------
/docs/Photo/Object.md:
--------------------------------------------------------------------------------
1 | # Object
2 |
3 | ## PhotosHelp
4 |
5 |
6 |
7 | ## PhotosObject
8 |
9 | 现在名为 `BilibiliAlbumObject`
10 |
--------------------------------------------------------------------------------
/docs/Photo/Readme.md:
--------------------------------------------------------------------------------
1 | # Functions
2 |
3 |
4 | ## PhotosRange
5 | 参数: list, 从一个pid列表中获取数据.
6 |
7 | 返回: AlbumObject对象
8 |
9 | 简写: 单个整数n表示`Range[1,n]`, 两个整数n则表示`Range[a,b]`
10 |
11 | ### 选项:
12 | - RawData->False
13 | - 是否不转化为AlbumObject而返回接受到的原始数据
14 | ---
15 | ## PhotosIndex
16 | 1. 参数: 无
17 | 获得画友首页的推荐拼图
18 | 2. 返回: AlbumObject对象
19 |
20 | **无选项**
21 |
22 | ## PhotosNew
23 | - 参数: `Integer`
24 |
25 | - 返回: `BilibiliAlbumObject`
26 |
27 | - 选项
28 | - UpTo: `100`
29 | - Count: `False`
30 | - All: `False`
31 | 严重bug, 勿用
32 | - RawData `False`
33 | Debug , 不转换生成 Object, 直接返回原始读入.
34 |
35 | ## PhotosHot
36 |
37 |
38 | ## PhotosRank
39 |
40 | ## PhotosRecommend
41 |
42 | ## PhotosTag
43 |
44 | ## PhotosAuthor
45 |
46 | ## PhotosSearch
47 |
48 | ## PhotosTrace
49 |
50 | ## PhotosDetail
51 |
52 |
53 |
54 |
55 | 具体实现参考 https://github.com/Moe-Net/BilibiliLink/issues/7
56 |
57 |
58 | ### Bug
59 |
60 | 
61 |
62 | 已知错误
--------------------------------------------------------------------------------
/docs/Readme.md:
--------------------------------------------------------------------------------
1 | ---
2 | home: true
3 | actionText: Get Started →
4 | actionLink: /Start/
5 | footer: MPL2.0 Licensed | Copyright © 2018-2018 GalAster
6 | ---
7 |
8 | ### 一键安装
9 |
10 | ```haskell
11 | PacletInstall["BilibilliLink","Site"->"http://math.owo.site/"]
12 | ```
13 |
14 | 当然更新和卸载也是一键搞定
15 |
16 | ```haskell
17 | PacletUpdate["BilibilliLink","Site"->"http://math.owo.site/"]
18 | PacletUninstall["BilibilliLink"]
19 | ```
20 |
21 | ::: warning 兼容性要求
22 | [](https://github.com/Moe-Net/BilibiliLink/releases)
23 | [](https://www.wolfram.com/mathematica/)
24 | [](https://www.wolfram.com/mathematica/)
25 | :::
26 |
--------------------------------------------------------------------------------
/docs/Start/Design.md:
--------------------------------------------------------------------------------
1 | # 设计模式
2 |
3 | ## Install
4 |
5 | 如果你是开发者, 那么按照如下方式安装, 同时卸载用户版, 以免造成干扰.
6 |
7 | 接着打开如下或任意 `$Path` 目录
8 | ```haskell
9 | PacletUninstall["BilibilliLink"]
10 | SystemOpen[FileNameJoin@{$UserBaseDirectory, "Applications"}]
11 | ```
12 | 接着使用git下载以下, 或任意fork项目即可
13 | ```bash
14 | git clone git@github.com:Moe-Net/BilibiliLink.git --depth 1
15 | ```
16 |
17 | 使用 `git pull` 同步, 使用`rm -rf BilibiliLink`命令删除即可卸载.
18 |
19 | ### Encoding
20 |
21 | 在开始一切之前, 请务必检查编码, 运行如下代码自动纠正编码.
22 |
23 | ```haskell
24 | If[$CharacterEncoding=!="UTF-8",
25 | $CharacterEncoding="UTF-8";
26 | Print[{
27 | Style["$CharacterEncoding has changed to UTF-8 to avoid problems.",Red],
28 | Style["Because BilibiliLink only works under UTF-8"]
29 | }//TableForm];
30 | st=OpenAppend[FindFile["init.m"]];
31 | WriteString[st,"$CharacterEncoding=\"UTF-8\";"];
32 | Close[st];
33 | ];
34 | ```
35 |
36 |
37 | ---
38 | ## Dev
39 |
40 | BBLink的核心部分就是`Package`目录, 所有**直接**在该目录下的 `*.m` 文件会被惰性加载, 也就是说 `__Feature__` 文件夹下的任何程序包都不会被默认加载, 所以一般测试功能, 过期功能都可以放里面
41 | 所有 `*.m` 文件都应该满足如下形式:
42 | ```haskell
43 | TestFunction1::usage="测试函数, 最终函数名BillibiliLink`TestFunction1.";
44 | Begin["`Test`"];
45 | TestFunction1:="Test";
46 | TestFunction2::usage="测试函数, 最终函数名BillibiliLink`Test`TestFunction2.";
47 | TestFunction2:="Test";
48 | End[]
49 | ```
50 | 也就是说所有在Begin前的声明会加载进整个包的上下文, 且能在不同的 `*.m` 文件中被共享, 在整个项目里被读取.
51 | 而Begin之后函数名则是局部的, 需要使用相对引用才能读取.
52 | 使用同名上下文惰性加载后会被识别为同一程序包, 请务必避免同名上下文里写同名函数.
53 | ***
54 |
55 | ## Test
56 |
57 | BBLink对于单个单位使用函数(Function)操作, 对于多个单位使用对象(Object)操作. 例如对于单个视频, 有一系列的函数接收vid并返回相应的返回值, 而对于多个视频则采用BilibiliVideoSectionObject对象来封装.
58 |
59 | 面对对象的部分通常名字相当长, 但是不用担心, 一般不需要手动操作那个部分, BBLink 提供了一些UI来简化操作.
60 |
61 | 首先我们加载BBLink查看所有全局函数
62 | ```haskell
63 | << "BilibiliLink`"
64 | ?? BilibiliLink`*
65 | (*?? BilibiliLink`*`**)
66 | ```
67 |
68 | 
69 |
70 | 然后查看Help函数, 最终会有一个BilibiliHelp 函数给出一个完整的UI封装, 现在将就用这个
71 |
72 | 
73 |
74 | 点击Copy, 然后传给`obj`, 运行后`obj`就相当于是一个函数, 能够接受参数
75 | 小写开头的字符串是短码, 短码不接受额外选项.
76 | 大写开头的是长码, 那就能和正常函数一样使用了.
77 |
78 | 
79 |
80 | 我们可以看到UI是Object的整合, Object是Function的整合, 所以其实熟练以后完全可以只用Function.
81 |
--------------------------------------------------------------------------------
/docs/Start/Guide.md:
--------------------------------------------------------------------------------
1 | # 文档编写指南
2 |
3 | 本文档使用 vuepress 编写
4 |
5 | 注意使用CRLF
6 |
--------------------------------------------------------------------------------
/docs/Start/Readme.md:
--------------------------------------------------------------------------------
1 | # 功能展示
2 |
3 | ## 图片下载
4 |
5 |
6 |
7 | ## 页面抓取
8 |
9 |
10 |
11 | ## 数据分析
12 |
--------------------------------------------------------------------------------
/docs/Toys/Readme.md:
--------------------------------------------------------------------------------
1 | # 其他图片类功能
2 |
3 | ## Logo
4 |
5 | #### `HeaderLogo[]`
6 |
7 | 文件名为哈希
8 |
9 | 
10 |
11 | #### `HeaderBanner[path_String]`
12 |
13 | path 为上面输出的路径, 将下载的版头制成拼图.
14 |
15 | 可选项 `Path`, 指定输出目录
16 |
17 | ## Banner
18 |
19 | #### `HeaderBanner[]`
20 |
21 | 获取版头
22 |
23 | 可选项 `Path`, 指定输出目录
24 |
25 | 
26 |
27 | #### `HeaderBanner[path_String]`
28 |
29 | path 为上面输出的路径, 将下载的版头制成拼图.
30 |
31 | 可选项 `Path`, 指定输出目录
32 |
33 | ## IndexIcon
34 |
35 |
36 | #### `IndexIcon[]`
37 | 
38 |
39 |
40 | #### `IndexIcon["Markdown"]`
41 |
42 | 导出一个 markdown 文档
43 |
44 | 
45 |
46 | ## ErrorPage
47 |
48 | #### `ErrorPage[]`
49 |
50 |
51 | ## Emoji
52 |
53 | #### `VipEmoji[]`
54 |
55 |
56 | 
57 |
--------------------------------------------------------------------------------
/docs/Video/CP.md:
--------------------------------------------------------------------------------
1 | 全站视频爬虫依据 AV 号遍历所有视频.
2 |
3 | 当然你也可以不指定, 不指定会直接塞进 `$UserBaseDirectory`, 提醒你一下这个文件夹一般是在C盘的...
4 |
5 | 截止2018年上半年, B站视频ID总计有2600W, 其中有效ID号大约1800W.
6 |
7 | 
8 |
9 | CPU的内核数记为 X , 开启的内核越多速度越快, 但是相应每个内核的效率就越低
10 |
11 | 一般使用 4X 的内核, 6X 仍然能有少量提升, 但是内存占用就很高了, 8X 的话基本就得不偿失了.
12 |
13 | 一般来说要爬取一个小时左右, 速度大约是每秒 5400 条记录.
14 |
15 |
16 |
17 | 
18 |
19 | ## Database
20 |
21 |
22 | 当然这还没完, 只是下载了所有页面而已, 一般来说你得读进内存才能操作.
23 |
24 | 读取的话直接 `Import[path]` 即可, 但是问题在于全部读取需要约 20G 内存. 我想大多数人是没这么大内存了, 所以需要导入数据库.
25 |
26 |
27 |
28 | 把额外的内核全关了, 因为 mongodb 的端口就那点带宽, 线程开了好几个也是堵着.
29 |
30 | 
31 |
32 |
--------------------------------------------------------------------------------
/docs/Video/Object.md:
--------------------------------------------------------------------------------
1 | # Object
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/docs/Video/Readme.md:
--------------------------------------------------------------------------------
1 | # Functions
2 |
3 |
4 | ## TagInfo
5 |
6 | ### 参数
7 | 1. Integer, 代表需要查询的标签 id
8 | 2. List, 代表标签 id 列表
9 |
10 | ### 选项
11 | 无
12 |
13 | ### 返回值
14 |
15 | ```haskell
16 | <|
17 | "ID"->"tag ID 简称 tid",
18 | "Name"->"tag 的名字",
19 | "Detail"->"tag 的描述, 没有的话为空",
20 | "Date"->"tag 的创建日期",
21 | "Count"->"使用了该 tag 的视频数",
22 | "Watch"->"关注了该 tag 的人数"
23 | |>
24 | ```
25 |
26 |
27 | ::: tip ### 压力测试
28 | 每分钟 378 次请求后被封 ip 10 分钟
29 |
30 | 建议爬取速度, 每 ip 每分钟 240 次.
31 | :::
32 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "devDependencies": {
3 | "vuepress": "^0.10.2"
4 | },
5 | "scripts": {
6 | "docs:dev": "vuepress dev docs",
7 | "docs:build": "vuepress build docs"
8 | },
9 | "dependencies": {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------