-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
680 additions
and
164 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using System.Windows; | ||
using XstarS; | ||
|
||
namespace YandereSpider | ||
{ | ||
/// <summary> | ||
/// 控制台模式的交互逻辑。 | ||
/// </summary> | ||
public static class ConsoleWindow | ||
{ | ||
/// <summary> | ||
/// 当前正在工作的后台线程的数量。 | ||
/// </summary> | ||
private static int WorkingThreadCount = -1; | ||
|
||
/// <summary> | ||
/// 所有图片的链接。 | ||
/// </summary> | ||
private static readonly ICollection<string> ImageLinks = new HashSet<string>(); | ||
|
||
/// <summary> | ||
/// 显示控制台窗口,并传递程序启动参数。 | ||
/// </summary> | ||
/// <param name="args">程序启动参数。</param> | ||
public static void Show(string[] args) | ||
{ | ||
ConsoleManager.Show(); | ||
var param = new ParamReader(args, true, new[] { "-e", "-t" }, new[] { "-h" }); | ||
|
||
if (param.GetSwitch("-h")) | ||
{ | ||
ConsoleWindow.ShowHelp(); | ||
} | ||
else | ||
{ | ||
var page = new YanderePage(param.GetParam(0) ?? YanderePage.IndexPageLink); | ||
if (!YanderePage.IsYanderePage(page)) | ||
{ | ||
throw new ArgumentException(new ArgumentException().Message, "PageLink"); | ||
} | ||
|
||
int enumCount = int.Parse(param.GetParam("-e") ?? 0.ToString()); | ||
|
||
if (!(param.GetParam("-t") is null)) | ||
{ | ||
int maxThreads = int.Parse(param.GetParam("-t")); | ||
if (maxThreads < 1) { throw new ArgumentOutOfRangeException("-t MaxThreads"); } | ||
ThreadPool.SetMaxThreads(maxThreads, maxThreads); | ||
} | ||
|
||
if (enumCount == 0) { ConsoleWindow.ExtractPage(page); } | ||
else { ConsoleWindow.EnumeratePages(page, enumCount); } | ||
|
||
while (ConsoleWindow.WorkingThreadCount != 0) { Thread.Sleep(10); } | ||
Clipboard.SetText(string.Join(Environment.NewLine, ConsoleWindow.ImageLinks)); | ||
Console.WriteLine(); | ||
Console.WriteLine("Completed."); | ||
Console.ReadKey(); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// 隐藏命令行窗口,释放标准输入流和错误流。 | ||
/// </summary> | ||
public static void Hide() | ||
{ | ||
ConsoleManager.Hide(); | ||
} | ||
|
||
/// <summary> | ||
/// 将帮助信息输出到控制台。 | ||
/// </summary> | ||
private static void ShowHelp() | ||
{ | ||
Console.WriteLine(@" | ||
YandereSpider.exe PageLink [-e PageCount] [-t MaxThreads] [-h] | ||
PageLink URL of yande.re page which contains image links. | ||
Absolute URL only, should start with 'https://yande.re'. | ||
-e PageCount Count of pages you want to enumerate from input page. | ||
0 means no enumeration, -1 means enumerating to end. | ||
-t MaxThreads The maximum threads in HTTP access. | ||
-h Show this help message. | ||
"); | ||
} | ||
|
||
/// <summary> | ||
/// 提取页面中包含的图片链接。 | ||
/// </summary> | ||
/// <param name="page"></param> | ||
private static void ExtarctLinks(YanderePage page) | ||
{ | ||
if (ConsoleWindow.WorkingThreadCount == -1) | ||
{ | ||
ConsoleWindow.WorkingThreadCount = 0; | ||
} | ||
|
||
ConsoleWindow.WorkingThreadCount++; | ||
var imageLinks = page.ImageLinks; | ||
Console.WriteLine(string.Join(Environment.NewLine, imageLinks)); | ||
foreach (var imageLink in imageLinks) | ||
{ | ||
ConsoleWindow.ImageLinks.Add(imageLink); | ||
} | ||
ConsoleWindow.WorkingThreadCount--; | ||
} | ||
|
||
/// <summary> | ||
/// 提取页面及其子页面中包含的图片链接。 | ||
/// </summary> | ||
/// <param name="page">页面链接提取对象。</param> | ||
private static void ExtractPage(YanderePage page) | ||
{ | ||
void callback(object state) => ConsoleWindow.ExtarctLinks(state as YanderePage); | ||
|
||
if (YanderePage.IsPoolsPage(page)) | ||
{ | ||
foreach (var poolPage in page) | ||
{ | ||
ThreadPool.QueueUserWorkItem(callback, poolPage); | ||
} | ||
} | ||
else | ||
{ | ||
ThreadPool.QueueUserWorkItem(callback, page); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// 遍历并提取各个页面的图片链接。 | ||
/// </summary> | ||
/// <param name="page">页面链接提取对象。</param> | ||
/// <param name="enumCount">指定遍历的页面数量; | ||
/// 为 -1 则遍历至最后一页,为 0 则不进行遍历。默认为 0。</param> | ||
private static void EnumeratePages(YanderePage page, int enumCount = -1) | ||
{ | ||
enumCount = (enumCount < 0) ? | ||
(page.Count - page.Index + 1) : | ||
((enumCount == 0) ? 1 : enumCount); | ||
for (int i = page.Index; i < page.Index + enumCount; i++) | ||
{ | ||
ConsoleWindow.ExtractPage(page[i]); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
#if !CORE | ||
|
||
using System; | ||
using System.IO; | ||
using System.Runtime.InteropServices; | ||
using System.Reflection; | ||
using System.Security; | ||
|
||
namespace XstarS | ||
{ | ||
/// <summary> | ||
/// 提供窗口应用程序的控制台窗口管理方法。 | ||
/// </summary> | ||
[SuppressUnmanagedCodeSecurity] | ||
internal static class ConsoleManager | ||
{ | ||
/// <summary> | ||
/// 为当前应用程序分配控制台窗口。 | ||
/// </summary> | ||
/// <returns>是否成功分配控制台窗口。</returns> | ||
[DllImport("kernel32.dll")] | ||
private static extern bool AllocConsole(); | ||
|
||
/// <summary> | ||
/// 释放当前已经分配的控制台窗口。 | ||
/// </summary> | ||
/// <returns>是否成功释放控制台窗口。</returns> | ||
[DllImport("kernel32.dll")] | ||
private static extern bool FreeConsole(); | ||
|
||
/// <summary> | ||
/// 获取当前已分配的控制台窗口的句柄。 | ||
/// </summary> | ||
/// <returns>当前已分配的控制台窗口的句柄。 | ||
/// 若并未分配控制台窗口,则返回 <see cref="IntPtr.Zero"/>。</returns> | ||
[DllImport("kernel32.dll")] | ||
private static extern IntPtr GetConsoleWindow(); | ||
|
||
/// <summary> | ||
/// 指示当前是否已经分配了控制台窗口。 | ||
/// </summary> | ||
public static bool HasConsole => | ||
ConsoleManager.GetConsoleWindow() != IntPtr.Zero; | ||
|
||
/// <summary> | ||
/// 为当前应用程序分配控制台窗口。 | ||
/// </summary> | ||
public static void Show() | ||
{ | ||
if (!ConsoleManager.HasConsole) | ||
{ | ||
ConsoleManager.AllocConsole(); | ||
ConsoleManager.InvalidateStdOutError(); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// 释放当前已经分配的控制台窗口。 | ||
/// </summary> | ||
public static void Hide() | ||
{ | ||
if (ConsoleManager.HasConsole) | ||
{ | ||
ConsoleManager.SetStdOutErrorNull(); | ||
ConsoleManager.FreeConsole(); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// 切换控制台窗口的显示状态。 | ||
/// </summary> | ||
public static void Toggle() | ||
{ | ||
if (ConsoleManager.HasConsole) | ||
{ | ||
ConsoleManager.Hide(); | ||
} | ||
else | ||
{ | ||
ConsoleManager.Show(); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// 释放 <see cref="Console"/> 的标准输出流和错误流,以触发其重新初始化。 | ||
/// </summary> | ||
private static void InvalidateStdOutError() | ||
{ | ||
var t_Console = typeof(Console); | ||
var staticNoPublic = BindingFlags.Static | BindingFlags.NonPublic; | ||
|
||
var sf__in = t_Console.GetField("_in", staticNoPublic); | ||
var sf__out = t_Console.GetField("_out", staticNoPublic); | ||
var sf__error = t_Console.GetField("_error", staticNoPublic); | ||
var sm_InitializeStdOutError = | ||
t_Console.GetMethod("InitializeStdOutError", staticNoPublic); | ||
|
||
sf__out.SetValue(null, null); | ||
sf__error.SetValue(null, null); | ||
sm_InitializeStdOutError.Invoke(null, new object[] { true }); | ||
} | ||
|
||
/// <summary> | ||
/// 将 <see cref="Console"/> 的标准输出流和错误流重定向至 <see cref="TextWriter.Null"/>。 | ||
/// </summary> | ||
private static void SetStdOutErrorNull() | ||
{ | ||
Console.SetOut(TextWriter.Null); | ||
Console.SetError(TextWriter.Null); | ||
} | ||
} | ||
} | ||
|
||
#endif |
Oops, something went wrong.