【问题标题】:Easiest way to "browse" to a page and submit form in Java在 Java 中“浏览”页面并提交表单的最简单方法
【发布时间】:2013-01-22 08:14:53
【问题描述】:

我需要做的是浏览到一个网页,登录,然后浏览到该站点上需要您登录的另一个网页,因此它需要保存 cookie。之后,我需要单击该页面上的一个元素,我将在其中填写表单并获取网页返回给我的消息。我需要实际转到页面并单击按钮的原因是假设只是直接导航到链接,因为每次登录并单击链接时都会为您分配一个会话 ID,而且它总是不同的。按钮看起来像这样,它不是普通的href链接:

<span id=":tv" idlink="" class="sA" tabindex="0" role="link">Next</span>

无论如何,最简单的方法是什么?谢谢。

更新: 在尝试了 HTMLunit 和其他无头浏览器库之后,似乎没有使用任何“无头”。我最近发现的关于这个页面的另一件事是,所有的 HTML 都是一些奇怪的格式......它都在一个脚本标签中。这是一个示例。

"?ui\x3d2\x26view\x3dss\x26mset\x3dmain\x26ver\x3d-68igm85d1771\x26am\x3d!Zsl-0RZ-XLv0BO3aNKsL0sgMg3nH10t5WrPgJSU8CYS-KNWlyrLmiW3HvC5ykER_n_5dDw\x26fri"],"http://example.com/?ctx\x3d%67mail\x26hl\x3den",,0,"Gmail","Gmail",[["us","c130f0854ca2c2bb",[["n"],["m","New features!"],["u"],["k","0"],["p","1000:500000,10,200000,5,100000,3,75000,2,0,1"],["h","https://survey.googleratings.com/wix/p1679258.aspx?l\x3d1033"],["at","query,5,contacts,5,adv,5,cf,5,default,20"],["v","https://www.youtube.com/embed/Ra8HG6MkOXY?showinfo\x3d0"],

当我检查按钮上的元素时,我在上面为按钮发布的 HTML 代码会出现,但在查看源代码时不会出现。基本上,我需要做的是使用某种 GUI,让用户导航到链接,然后让程序填写信息。有谁知道我该怎么做?谢谢。

【问题讨论】:

  • 查看 Selenium 和 Selenium IDE。网上有很多文章和操作方法可以让您在几个小时内起床并开始工作。

标签: java html web-scraping httprequest headless-browser


【解决方案1】:

查看 Selenium 的 5 分钟入门指南:http://code.google.com/p/selenium/wiki/GettingStarted

【讨论】:

  • 该堆栈中的另一个宝贵工具是用于 Firefox 的 SeleniumIDE 插件。它允许您在页面上记录您的操作,然后将交互导出到 Java 代码。
【解决方案2】:

在登录页面上,查看表单的 HTML 以查看它发布到的 url 和 url 参数。然后用正确的信息填充相同的参数请求该 url,并确保保存所有 cookie 标头以发送到第二页。然后使用 html 解析器找到您的链接。 sourceforge 上有几个 html 解析器,你甚至可以尝试 java 内置的 xml 解析器,但如果网站有一个很小的 ​​html 错误,它们就会出现故障。

EDIT 没有注意到它不是正常链接的事实。在这种情况下,您需要查看网站的 javascript 以查看链接指向的位置。如果链接需要运行 javascript,它会变得更加复杂。 Java 无法执行浏览器 javascript,但我找到了一个名为 DJ native swing 的库,其中包含一个可以添加到 jframe 的 Web 浏览器类。它使用您的本机浏览器来呈现和运行 javascript。

【讨论】:

  • 是否可以让用户使用 GUI 浏览器库手动浏览页面,而不是让库从代码中为用户填写表单?这是使用 DJ Native。
  • 是的,当然。这是一个很好的解决方案。查看 DJ Native swing 库。在框架中添加 Web 浏览器就像 JWebBrowser b=new JWebBrowser(); frame.add(b); 一样简单
  • 请看帖子的编辑。有没有办法可以合并这样的 GUI 库,但不是以编程方式填写页面上的表格?我会让用户导航到页面,然后程序会填写表单/点击按钮等。
【解决方案3】:

正如其他人所指出的,这在 Selenium 中应该是可能的。

我使用 Selenium 登录然后爬取一个站点并发现站点上每个表单(30 多个表单)的每个值的排列。这些值稍后用于填写和提交具有特定值排列的表单。这个站点非常重 JS/jQuery,我使用 Selenium 的内置支持 javascript 执行器、css 选择器和 XPath 来完成这个。

我将 HtmlUnit 和 HttpUnit 实现为更快的替代方案,但鉴于我正在抓取的网站的 JS 语义,我发现它们不如 Selenium 可靠。

很难为您提供有关如何完成它的代码,因为您的 Selenium 实现将非常特定于页面,我无法查看您正在编码的页面来弄清楚该按钮脚本垃圾发生了什么。但是,我已经包含了一些可能相关的硒代码(Java)sn-ps:

Element element = driver.findElements(By.id(value)); //find element on page
List<Element> buttons = parent.findElements(By.xpath("./tr/td/button")); //find child element
button.click();
element.submit() //submit enclosing form
element.sendKeys(text); //enter text in an input
String elementText = (String) ((JavascriptExecutor) driver).executeScript("return arguments[0].innerText || arguments[0].textContent", element); //interact with a selenium element via JS

如果您在不同的页面上编写类似的功能,那么接口后面的PageObjects 会有所帮助。

Anew 发布的链接是一个很好的起点,而且 StackOverflow 可以解决几乎所有 Selenium 问题。

【讨论】:

    【解决方案4】:

    不要尝试以编程方式浏览,而是尝试执行登录请求并保存 cookie,然后在下一个请求中将它们设置为表单帖子。

    【讨论】:

      【解决方案5】:

      HTMLUnit 在处理 JavaScript 方面非常糟糕,Rhino JS 库经常产生错误(实际上没有错误是例外)。我建议使用Selenium,它基本上是一个控制无头浏览器(基于chrome、firefox)的框架。

      对于您的问题,以下代码可以解决问题

      selenium.open(myurl);
      selenium.click("id=:tv");
      

      然后您必须等待页面加载

      selenium.waitForPageToLoad(someTime);
      

      【讨论】:

        【解决方案6】:

        我会随时推荐 htmlunit。这是一个很棒的图书馆。

        首先,查看他们的网页 (http://htmlunit.sourceforge.net/) 以启动并运行 htmlunit。确保你使用最新的快照(写这篇文章时是 2.12)

        尝试这些设置几乎可以忽略任何障碍:

        WebClient webClient = new WebClient(BrowserVersion.FIREFOX_17);
        webClient.getOptions().setRedirectEnabled(true);
        webClient.getOptions().setCssEnabled(false);
        webClient.getOptions().setThrowExceptionOnScriptError(false);
        webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
        webClient.getOptions().setUseInsecureSSL(true);
        webClient.getOptions().setJavaScriptEnabled(true);
        webClient.getCookieManager().setCookiesEnabled(true);
        

        然后在获取您的页面时,请确保在对页面执行任何操作之前等待后台 Javascript,例如发布登录表单:

        //Get Page
        HtmlPage page1 = webClient.getPage("https://login-url/");
        
        //Wait for background Javascript
        webClient.waitForBackgroundJavaScript(10000);
        
        //Get first form on page
        HtmlForm form = page1.getForms().get(0);
        
        //Get login input fields using input field name
        HtmlTextInput userName = form.getInputByName("UserName");
        HtmlPasswordInput password = form.getInputByName("Password");
        
        //Set input values
        userName.setValueAttribute("MyUserName"); 
        password.setValueAttribute("MyPassword"); 
        
        //Find the first button in form using name, id or xpath
        HtmlElement button = (HtmlElement) form.getFirstByXPath("//button");
        
        //Post by clicking the button and cast the result, login arrival url, to a new page and repeat what you did with page1 or something else :) 
        HtmlPage page2 = (HtmlPage) button.click(); 
        
        //Profit
        System.out.println(page2.asXml());    
        

        希望这个基本示例对您有所帮助!

        【讨论】:

          猜你喜欢
          • 2021-11-23
          • 2013-03-09
          • 2011-02-16
          • 1970-01-01
          • 2013-03-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-08-20
          相关资源
          最近更新 更多