首页 > 解决方案 > 浏览 Javascript 生成的网页

问题描述

有这个在线表格(https://servizi.ivass.it/RuirPubblica/),您可以在其中进行搜索(只需进行空白搜索)。对于它给出的每个结果,我需要单击结果并导出详细信息页面第 5 个表中的列表。

所以基本上我想制作一个为我做这件事的软件:

  1. 使用我自己的条件提交搜索
  2. 访问结果项的每一页
  3. 访问每个项目的详细信息页面
  4. 获取第 5 个标签中的行,以便我可以将它们附加到列表中

当我单击“搜索”按钮时,我使用 Fiddler 检查了 POST 请求中使用了哪些参数,并尝试对 .Net 执行相同操作。如果我尝试使用 HttpClient 访问基址,它会返回搜索表单的正确 HTML,但是当我使用搜索参数提交以下 POST 请求时,我会得到一个显示错误“警告:会话已过期”的网页。

如果我在没有首先访问主页的情况下单独进行搜索 POST 调用,也会发生这种情况,所以我不确定它是否与保持两个请求之间的会话不存在有关。

public MainWindow()
        {
            InitializeComponent();

            var cookieJar = new CookieContainer();
            var handler = new HttpClientHandler
            {
                CookieContainer = cookieJar,
                UseCookies = true,
                UseDefaultCredentials = false
            };

            client = new HttpClient(handler)
            {
                BaseAddress = new Uri("https://servizi.ivass.it/RuirPubblica/Search.faces")
            };
        }

        private async Task TryHttp()
        {
            // Access the search page
            var response = await client.GetAsync(client.BaseAddress);

            var responseString = await response.Content.ReadAsStringAsync();

            // Perform the search
            var values = new Dictionary<string, string>
            {
                { "FormSearch", "FormSearch" },
                { "FormSearch:j_id_jsp_558348152_13", "PG" },
                { "FormSearch:j_id_jsp_558348152_16", "custom" },
                { "FormSearch:SecE", "on" },
                { "FormSearch:matricola", "" },
                { "FormSearch:ragioneSociale", "" },
                { "FormSearch:provincia", "NA" },
                { "FormSearch:SearchButton", "Ricerca" },
                { "javax.faces.ViewState", "j_id1:j_id5" },
            };

            var content = new FormUrlEncodedContent(values);

            response = await client.PostAsync(client.BaseAddress, content);

            // Here I'm getting a web page showing the error "Warning: Session expired"
            responseString = await response.Content.ReadAsStringAsync();
        }

        private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            TryHttp();
        }

标签: c#

解决方案


如果你能定义它,它就可以完成。正如您将从评论中了解到的那样,StackOverflow 都是关于编程问题的,所以我只会帮助您解决这个问题。

原则上,如果网页是“可解析”为 HTML 并使用 HTTP 进行通信,那么您可以用它做任何普通 Web 浏览器会做的事情。您引用的网站最初似乎确实做了任何不寻常的事情。

HTMLAgilityPack对于解析 DOM 以及导航和提取内容非常有用。

要使用 C# 发出 HTTP 请求,您应该使用HttpClient类。

有一些较旧的选项,例如HttpWebClient,这里有很好的答案,可以帮助您在两者之间做出决定。


为了快速参考,Fiddler 在这里可用,我也用过很多次并且会推荐它,尽管它可能会导致 HTTPS 流量和调试问题。


推荐阅读