C# Selenium调用GoToUrl访问随机URL时链接尾部被截断无法正确跳转
问题背景
基于Selenium开发随机访问Lightshot(prnt.sc)公开截图页的C#程序,经控制台打印输出验证,自定义的URLRandomizer()方法可以生成符合格式要求的目标链接,但程序实际运行时不会跳转到生成的完整URL,反而会截断URL尾部内容,最终访问错误地址。
原始问题代码如下:
static void Main(string[] args) { IWebDriver chromeDriver = new ChromeDriver(); Restart: chromeDriver.Navigate().GoToUrl(URLRandomizer()); Thread.Sleep(1000); goto Restart; } static string URLRandomizer() { Random random = new Random(); string linkPart = "https://prnt.sc/"; string URL; char[] allLetters = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'X'}; URL = linkPart + allLetters[random.Next(0, allLetters.Length)].ToString() + allLetters[random.Next(0, allLetters.Length)].ToString() + random.Next(0, 10).ToString() + random.Next(0, 10).ToString() + random.Next(0, 10).ToString() + random.Next(0, 10).ToString(); return URL; } }
故障原因
Random实例化逻辑错误:每次调用URLRandomizer()都会新建一个Random对象,而C#中Random的默认种子取自系统时钟,程序设置的循环间隔仅1秒,短时间高频调用会生成大量重复URL,很容易触发prnt.sc的反爬拦截,站点会返回重定向/拦截响应,直接改写地址栏URL,表现为尾部内容被截断。- 导航逻辑存在竞态问题:使用
goto实现无限循环,且只固定等待1秒就发起下一次导航,多数场景下页面还没完成初始导航、URL还没完全加载到地址栏,就被新的导航请求打断,自然会出现URL截断的现象。 - 存在笔误:大写字母字符数组最后一位重复写了
X,缺失大写Z,会导致生成的URL覆盖范围不符合预期。
修复方案
- 将
Random实例提升为类级别的静态成员,整个程序生命周期只实例化一次,避免短时间生成重复URL。 - 移除
goto写法,使用标准while(true)实现无限循环。 - 替换固定时长的
Thread.Sleep(),使用Selenium内置的页面加载等待,确认当前页面导航完成后再发起下一次请求,避免导航中断。 - 修正字符数组的笔误,补全大写
Z,移除重复的X。 - 适当调大访问间隔,降低被站点反爬拦截的概率。
修复后的可运行代码:
using OpenQA.Selenium; using OpenQA.Selenium.Chrome; using OpenQA.Selenium.Support.UI; class Program { // 全局唯一Random实例,避免重复播种 private static readonly Random random = new Random(); private static readonly char[] allLetters = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; static void Main(string[] args) { IWebDriver chromeDriver = new ChromeDriver(); // 设置页面加载超时时间为10秒 chromeDriver.Manage().Timeouts().PageLoad = TimeSpan.FromSeconds(10); WebDriverWait wait = new WebDriverWait(chromeDriver, TimeSpan.FromSeconds(10)); while (true) { try { string targetUrl = URLRandomizer(); // 调试用:打印实际访问的URL Console.WriteLine($"正在访问:{targetUrl}"); chromeDriver.Navigate().GoToUrl(targetUrl); // 等待页面加载完成,判断条件为页面DOM就绪 wait.Until(d => ((IJavaScriptExecutor)d).ExecuteScript("return document.readyState").Equals("complete")); // 访问间隔调整为3秒,降低反爬触发概率 Thread.Sleep(3000); } catch (WebDriverTimeoutException) { // 加载超时就刷新重试 chromeDriver.Navigate().Refresh(); } catch (Exception ex) { Console.WriteLine($"访问异常:{ex.Message}"); Thread.Sleep(2000); } } } static string URLRandomizer() { const string linkPart = "https://prnt.sc/"; // 拼接6位随机路径:2位字母+4位数字,和原逻辑一致 string randomPath = allLetters[random.Next(allLetters.Length)].ToString() + allLetters[random.Next(allLetters.Length)].ToString() + random.Next(0, 10).ToString() + random.Next(0, 10).ToString() + random.Next(0, 10).ToString() + random.Next(0, 10).ToString(); return linkPart + randomPath; } }
注意:如果修复后仍然出现URL被跳转到其他路径的情况,是prnt.sc针对无真实浏览器指纹、高频访问的爬虫请求做的拦截,需要额外配置浏览器参数模拟真实用户行为,不属于代码逻辑错误。
内容的提问来源于stack exchange,提问作者Arnas Bies
相关产品推荐
相关产品推荐

