Handler三秒跳转 + 第一次进入有,第二次没有

本文介绍了一个简单的启动页实现方案,利用Handler进行倒计时,并根据SharedPreferences中记录的登录状态来决定是否跳过欢迎页面直接进入主界面。此外,还展示了如何设置ImageView作为背景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

xlm控件

设置图片(也可以设置为背景色)

<ImageView
        android:id="@+id/imageView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@drawable/tb" />

    <TextView
        android:id="@+id/tv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignRight="@+id/imageView1"
        android:layout_alignTop="@+id/imageView1"
        android:layout_marginRight="18dp"
        android:layout_marginTop="29dp"
        android:textSize="20sp"/>


主方法

TextView tv;

    SharedPreferences preferences;
    Editor editor;
    Handler handler = new Handler();
    // 设置跳转时长
    int time = 5;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //无标题
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        tv = (TextView) findViewById(R.id.tv);
        preferences = getSharedPreferences("cof", MODE_PRIVATE);
        editor = preferences.edit();
        
        boolean Login = preferences.getBoolean("isLogin", false);
        if(Login){
            Intent intent = new Intent(MainActivity.this,HomeActivity.class);
            startActivity(intent);
            finish();
            return;
        }
        handler.postDelayed(new Runnable() {
            
            @Override
            public void run() {
                tv.setText(time+"");
                time -- ;
                if(time == 0){
                    Intent intent = new Intent(MainActivity.this,HomeActivity.class);
                    startActivity(intent);
                    
                //    进行判断是否第一次
                    editor.putBoolean("isLogin", true);
                    editor.commit();
                  
                    finish();
                    return;
                }
                handler.postDelayed(this, 1000);
            }
        }, 1000);
    }
<think>好的,我现在需要帮助用户解决如何使用C#爬取一个带有token验证且会二次跳转的网页的问题。首先,我需要回顾之前用户的问题和我的回答历史。用户之前询问过C#是否适合开发爬虫,我给出了详细的肯定回答,并介绍了相关技术栈和流程。现在用户的问题更具体,涉及token验证和二次跳转,这两个都是比较常见的反爬机制。 首先,我需要确定用户的具体需求。他们可能遇到的是一个需要处理身份验证和页面重定向的复杂爬虫场景。用户可能已经尝试过简单的请求,但遇到了障碍,比如无法获取token或者处理跳转后的页面。这时候,我需要分步骤解释如何处理这两个问题。 接下来,我应该考虑token验证的常见形式。通常,token可能在页面中的隐藏表单字段、JavaScript生成,或者通过API响应获取。针对不同的情况,需要不同的处理方法,比如解析HTML获取隐藏字段,或者执行JavaScript来生成动态token。而二次跳转可能涉及HTTP重定向或JavaScript重定向,需要模拟浏览器行为来处理。 然后,我需要回忆C#中常用的库和工具。比如HttpClient用于处理HTTP请求,但默认情况下可能不会自动处理重定向,需要配置。对于JavaScript生成的内容,可能需要使用无头浏览器如PuppeteerSharp或Selenium。此外,处理Cookie和会话是关键,因为token通常与会话相关。 接下来,我应该构建一个清晰的步骤指南。可能包括分析请求流程、获取初始token、携带token发起请求、处理二次跳转、确保会话保持等。每个步骤需要具体的代码示例,比如使用HttpClient时禁用自动重定向,手动处理302响应,或者使用AngleSharp解析HTML中的token。 同时,需要提醒用户注意反爬策略,比如设置合理的请求头、使用代理、处理异常等。此外,法律和道德问题也不能忽视,必须遵守robots.txt和网站的使用条款。 在组织回答时,应该分点说明,结构清晰,让用户能够逐步跟随。可能需要比较不同工具的选择,比如何时使用HttpClient,何时需要无头浏览器。代码示例要简洁,突出关键部分,如配置HttpClient、提取token、处理重定向等。 最后,总结适用场景和注意事项,帮助用户评估是否选择C#以及需要注意的问题。确保回答覆盖了用户可能遇到的各种情况,并提供解决方案,同时保持建议的实用性。</think>以下是使用 C# 爬取带 Token 验证和二次跳转网页的完整解决方案(分步骤实现): --- ### 一、核心流程分析 $$请求流程图$$ ``` 首次请求 -> 获取 Token -> 携带 Token 二次请求 -> 处理跳转 -> 获取目标数据 ``` --- ### 二、关键技术实现 #### 1. 基础请求配置 ```csharp var handler = new HttpClientHandler { UseCookies = true, // 必须启用 Cookie 容器 AllowAutoRedirect = false // 禁用自动跳转 }; using var client = new HttpClient(handler); client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"); ``` #### 2. Token 获取方式 **场景 1:HTML 隐藏字段** ```csharp // 使用 AngleSharp 解析 var context = BrowsingContext.New(Configuration.Default); var document = await context.OpenAsync(req => req.Content(htmlContent)); var token = document.QuerySelector("input[name='__RequestVerificationToken']")? .GetAttribute("value"); ``` **场景 2:API 动态获取** ```csharp // 先请求获取 Token 的 API var tokenResponse = await client.GetAsync("https://api.example.com/token"); var tokenJson = await tokenResponse.Content.ReadAsStringAsync(); var token = JObject.Parse(tokenJson)["data"]["token"].ToString(); ``` --- ### 三、处理二次跳转 #### 1. 手动处理 302 跳转 ```csharp // 首次请求 var firstResponse = await client.GetAsync("https://example.com/login"); // 检查是否需要跳转 if (firstResponse.StatusCode == HttpStatusCode.Redirect) { var redirectUrl = firstResponse.Headers.Location; // 构造跳转请求 var redirectRequest = new HttpRequestMessage(HttpMethod.Get, redirectUrl); redirectRequest.Headers.Add("X-Custom-Token", token); // 发送跳转请求 var finalResponse = await client.SendAsync(redirectRequest); } ``` #### 2. 处理 JavaScript 跳转 ```csharp // 使用无头浏览器处理 await using var browser = await Puppeteer.LaunchAsync(); var page = await browser.NewPageAsync(); // 监听跳转事件 page.Response += async (sender, e) => { if (e.Response.Url.Contains("target-page")) { var content = await e.Response.TextAsync(); // 处理目标页面数据 } }; await page.GoToAsync("https://example.com/secured-page"); ``` --- ### 四、会话保持方案 #### 1. Cookie 容器配置 ```csharp var cookieContainer = new CookieContainer(); handler.CookieContainer = cookieContainer; // 手动添加认证 Cookie cookieContainer.Add(new Uri("https://example.com"), new Cookie("AuthToken", "xxxxxx")); ``` #### 2. 请求头签名验证 ```csharp // 生成时间戳签名 var timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); var signature = GenerateSignature(token, timestamp); client.DefaultRequestHeaders.Add("X-Signature", signature); client.DefaultRequestHeaders.Add("X-Timestamp", timestamp.ToString()); ``` --- ### 五、完整案例演示 ```csharp public async Task<string> CrawlProtectedPage() { // 第一阶段:获取 Token var token = await GetSecurityTokenAsync(); // 第二阶段:构造认证请求 var request = new HttpRequestMessage(HttpMethod.Post, "https://example.com/auth"); request.Content = new FormUrlEncodedContent(new Dictionary<string, string> { ["auth_token"] = token, ["user"] = "demo" }); // 第三阶段:处理跳转 var response = await client.SendAsync(request); if (response.Headers.Location != null) { var finalResponse = await client.GetAsync(response.Headers.Location.AbsoluteUri); return await finalResponse.Content.ReadAsStringAsync(); } return null; } ``` --- ### 六、反反爬策略 1. **请求频率控制** ```csharp await Task.Delay(new Random().Next(800, 1500)); // 随机延时 ``` 2. **代理轮换方案** ```csharp var proxy = new WebProxy("121.36.84.237:8080"); handler.Proxy = proxy; ``` 3. **TLS 指纹伪装** ```csharp // 使用 BouncyCastle 库自定义加密套件 client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"); ``` --- ### 七、调试技巧 1. 使用 Fiddler 抓包分析实际请求流程 2. 在代码中记录请求日志: ```csharp var logger = new HttpClientDiagnosticHandler(new FileLogger()); var client = new HttpClient(logger); ``` --- **适用场景**:适用于银行系统、政府网站、ERP 系统等采用严格认证机制的平台数据采集。建议优先使用 PuppeteerSharp 处理现代前端框架(如 React/Vue)构建的网站。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值