如何在WebBrowser控件和CookieAwareWebClient之间共享cookie?

问题描述 投票:0回答:1

在工作中,我们登录到提供商的网站,该网站充当文件存储库。出现文件列表。每个文件名都是一个链接。单击该链接,然后下载该文件。这是一个非常轻量级的网站。

我正在尝试登录并下载文件而不需要单击每个文件的繁琐任务(没有“全选”复选框)。我正在使用带有Go按钮的表单上的WebBrowser控件开始。这是代码。请跳到星号行。

Private Sub btnGo_Click(sender As Object, e As EventArgs) Handles btnGo.Click
    Try
        PageLoaded = False
        browser.Navigate("https://[the website]/Account/Login.htm", False)
        While Not PageLoaded
            Application.DoEvents()
        End While
    Catch ex As Exception
        MsgBox(ex.Message)
    End Try
    Try
        browser.Document.GetElementById("username").InnerText = [username]
        browser.Document.GetElementById("password").InnerText = [password]
        PageLoaded = False
        browser.Document.Forms("mainform").InvokeMember("submit")
        While Not PageLoaded
            Application.DoEvents()
        End While
    Catch ex As Exception
        MsgBox(ex.Message)
    End Try

    ' ************************************
    Dim mycookies As String
    mycookies = browser.Document.Cookie
    ' DEBUG: verified cookies are indeed present

    Try
        Dim cookieJar As New CookieContainer
        Dim cookies As String() = browser.Document.Cookie.Split({"; "}, StringSplitOptions.RemoveEmptyEntries)
        Dim cookievaluepairs() = cookies(0).Split("=")
        Dim cky As New Cookie(cookievaluepairs(0), cookievaluepairs(1))
        cky.Domain = browser.Document.Domain
        cookieJar.Add(cky)
        Dim cookievaluepairs1() = cookies(1).Split("=")
        Dim cky1 As New Cookie(cookievaluepairs(0), cookievaluepairs(1))
        cky1.Domain = browser.Document.Domain
        cookieJar.Add(cky1)
        ' DEBUG: verified cookieJar contains expected cookies

        Dim wwwclient As New CookieAwareWebClient(cookieJar)
        ' DEBUG: please see class code below

        Dim x As Integer
        Dim dlurl As String = ""
        Dim inputs As HtmlElementCollection = browser.Document.Links
        For Each elm As HtmlElement In inputs
            If Microsoft.VisualBasic.Left(elm.OuterHtml, 10) = "<A href=""/" Then
                dlurl = elm.GetAttribute("href")
                ' DEBUG: crappily named dlurl indeed has correct URI

                wwwclient.DownloadFile(dlurl, "D:\Desktop\file" & x)
                ' DEBUG: overriden function GetWebRequest fires
                '        please see class code below

            End If
        Next
    Catch ex As Exception
        MsgBox(ex.Message)
        ' DEBUG: always lands here with 401 error

    End Try
End Sub

这是在SO上找到的CookieAwareWebClient的众多版本之一。

Public Class CookieAwareWebClient
    Inherits WebClient

    Private m_container As CookieContainer = New CookieContainer()

    Public Sub New(cc As CookieContainer)
        m_container = cc
        ' DEBUG: verified m_container now has cookieJar passed as cc
    End Sub


    Protected Overrides Function GetWebRequest(ByVal address As Uri) As WebRequest
        Dim request As WebRequest = MyBase.GetWebRequest(address)
        Dim webRequest As HttpWebRequest = TryCast(request, HttpWebRequest)

        If webRequest IsNot Nothing Then
            webRequest.CookieContainer = m_container
        End If

        Return webRequest
        ' DEBUG: verified webRequest.CookieContainer is correct
    End Function
End Class

我单步执行代码一直到wwwclient.DownloadFile语句,然后通过GetWebRequest函数中的代码,暂停后,我得到一个401 Not Authorized。这已经发生在我发现的CookieAwareWebClient的五六种变体中。

在代码成功登录后,我从WebBrowser控件检索到的两个cookie看起来像这样(每次obv都有不同的令牌)。

"samlssologgedout=SSO%20Logged%20Out" "token=A4AA416E-46C8-11e9-92CD-005056A005E4"

我已经验证了那些与'webRequest.CookieContainer'相同的cookie。同样,在WebBrowser控件中,登录后,您可以单击文件的链接进行下载。

有没有人在代码中看到任何明显错误的内容?

在写这个问题时仍然在谷歌搜索,我刚刚在WebClient的MS文档中遇到了Notes to Inheritors - “派生类应该调用WebClient的基类实现,以确保派生类按预期工作。”

这听起来像你在构造函数中会做的事情?或者这是在MyBase.GetWebRequest(address)声明中处理的?

.net vb.net web-scraping webclient
1个回答
0
投票

经过多次破解和谷歌,我将得出结论,这是一个神话,你可以使WebClient“cookie意识到”。我从来没有能够使它工作,我读到的几乎所有关于它的线程都没有解决方案。无论如何,WebClient显然已被弃用。

回顾一下,任务是从使用表单身份验证的低安全性网站自动登录和下载文件。 WebBrowser控件可以正常工作,除了它使用IE,IE拒绝静默下载PDF文件。它坚持提示是否打开,保存或丢弃。

我开始使用HTTPWebRequest,HTTPRequest,WebRequest,HTTPClient和一堆变体,并且无处可去。然后我想到了一个基于Chrome的WebBrowser控件,我偶然发现了Selenium。事实证明这是我的解决方案。

Selenium的主要用途似乎是测试软件,但它也可以让你操作网页。您可以通过NuGet在Visual Studio中轻松安装它。您还需要安装特定于浏览器的驱动程序。每个主要浏览器都有驱动程序,但使用IE驱动程序将毫无意义,因为我仍然会遇到每个文件都被提示的问题。我改为下载了Chrome和Firefox驱动程序。它们允许用户在这两者之间进行选择,大约是50/50。

这是代码到底有多简单。

Dim Options = New FirefoxOptions
Options.SetPreference("browser.download.folderList", 2)
'Options.SetPreference("browser.download.dir", "C:\\Windows\\temp")
Options.SetPreference("browser.download.useDownloadDir", True)
Options.SetPreference("browser.helperApps.neverAsk.saveToDisk", "application/octet-stream")
Options.SetPreference("pdfjs.disabled", True)
Dim driverService = FirefoxDriverService.CreateDefaultService()
driverService.HideCommandPromptWindow = True
Dim browser = New FirefoxDriver(driverService, Options)
browser.Url = "https://[the website]"
browser.Navigate()
Dim elm = browser.FindElementById("username")
elm.SendKeys([the username])
elm = browser.FindElementById("password")
elm.SendKeys([the password])
elm = browser.FindElementById("loginSubmit")
elm.Click()
While InStr(browser.Url, "token") = 0
    Application.DoEvents()
End While
Dim links As IList(Of IWebElement) = browser.FindElementsByPartialLinkText(".")
For Each link As IWebElement In links
    link.Click()
Next

我遇到了neverAsk.saveToDisk部分的问题。它只是没有用。事实证明我有错误的mime类型。我从这个评论中得到了解决方案 - Set Firefox profile to download files automatically using Selenium and Java

© www.soinside.com 2019 - 2024. All rights reserved.