最简单的方法是“浏览”页面并使用Java提交表单

时间:2013-02-06 23:22:22

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

我需要做的是浏览网页,登录,然后浏览到该网站上需要您登录的其他网页,因此需要保存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并让用户导航到链接,然后让程序填写信息。有谁知道我怎么做到这一点?感谢。

6 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:2)

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

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

答案 2 :(得分:1)

其他人已经注意到,这应该可以在Selenium中实现。

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

我实现了HtmlUnit和HttpUnit作为更快的替代方案,但发现它们不像Selenium那样可靠,考虑到我抓取的网站的JS语义。

很难为您提供有关如何完成它的代码,因为您的Selenium实现将非常特定于页面,我无法查看您正在编码的页面以找出该按钮脚本垃圾的内容。但是,我已经包含了一些可能相关的selenium代码(Java)代码段:

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问题。

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

对于您的问题,以下代码将完成工作

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

然后你必须等待页面加载

selenium.waitForPageToLoad(someTime);

答案 5 :(得分:0)

我会建议任何一天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());    

我希望这个基本的例子可以帮到你!