如何修复:HtmlUnit GetElementById Returns Null
How To Fix: HtmlUnit GetElementById Returns Null
我正在编写网络抓取工具,并试图在搜索框中输入搜索词。但是,当我尝试按 ID 访问搜索框时,我似乎得到了 null。我刚刚开始学习 HtmlUnit,所以我可能遗漏了一些非常明显的东西,但我自己还无法识别。
这是网站的代码:
<html xmlns="http://www.w3.org/1999/xhtml" xml:1ang="en" class="no-touch">
<head>-</head>
<body lang="en" class="garageBrand" emailcookiename="grgemailca" loyaltycookiename="grgloyaltyca">
<div id="fb-root" class="fb_reset">-</div>
<noscript>...</noscript>
<script>...</script>
<div id="container">
<div id="avsDialog" sty1e="disp1ay: none; position: absolute; top: 0; right: 0;"></div>
<input type="hidden" value="en" id="displayLanguage">
<input type="hidden" value="garageSiteCA" id="currSiteId">
<input type="hidden" value="en_CA" id="currLocale">
<div id="contentarea">
<div id="header" class="nonHeaderScroll">
<div id="topnav">...</div>
<div class="socialSearch">
<div id="searchMenu">
<form action="//www.garageclothing.com/ca/search/search.jsp" method="GET">
<input type="hidden" name="N" value="0">
<input type="hidden" name="Dy" value="1">
<input type="hidden" name="Nty" value="1">
<input type="hidden" name="Ntk" value="All">
<input type="hidden" name="Ntx" value="mode matchall">
<input id="searchText" maxlength="40" type="text" name="Ntt" class="textInput" placeholder="Search..." autocomplete="off">
<input class="mainSearchButton" type="image" src="//images.gdicdn.com/img/magnifying-glass.png?version=375" name="search">
</form>
</div>
这是我的代码:
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
import com.gargoylesoftware.htmlunit.html.HtmlInput;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
WebClient client = new WebClient();
client.getOptions().setJavaScriptEnabled(true);
client.getOptions().setCssEnabled(false);
client.getOptions().setUseInsecureSSL(true);
try {
HtmlPage page = client.getPage("https://www.garageclothing.com/ca");
// Check for popup.
if(page.getElementById("cboxClose") != null) {
page = page.getElementById("cboxClose").click();
}
// Debugging line that returns null:
System.out.println(page.getElementById("searchText"));
// What I would like to do:
/*HtmlInput searchInput = (HtmlInput) page.getElementById("searchText");
searchInput.setValueAttribute("red scarf");
HtmlSubmitInput submitBtn = page.getElementByName("search");
page = submitBtn.click();
System.out.println(page.asXml());*/
} catch (IOException e) {
e.printStackTrace();
}
}
}
您应该检查您传递给 WebClient
的 URL 是您正在使用的网络浏览器中查看的那个。
我访问了您在代码中使用的 link (https://www.garageclothing.com),但我得到的页面不是您期望的页面。它要求我选择一个国家(美国或加拿大),然后在我点击任何选项后,它会带我到你期望的页面。
尝试将 URL 更改为“https://www.garageclothing.com/us/" or "https://www.garageclothing.com/ca/”
即使页面看起来很简单,这个页面(就像许多购物门户网站一样)真的很复杂并且基于大量 javascript(不仅是页面本身,而且所有这些讨厌的跟踪器都需要观察用户)。如果您想了解有关此页面的更多信息,我建议使用像 Charles 这样的网络代理来捕获整个流量。
现在回到你的问题...
由于 HtmlUnit javascript 支持(基于 Rhino)并不完美,您会遇到一些 javascript 错误。为了不停止在 js 错误,你必须配置客户端
webClient.getOptions().setThrowExceptionOnScriptError(false);
下一步是获取页面。这也不是那么简单,因为所有的 js 东西。看起来 js 的东西也替换了最初通过获取 url 返回的页面。因此,您必须执行三个步骤
- 获取页面
- 等待一些时间让js做一些工作
- 从当前页面获取当前页面window
现在您可以找到搜索字段了;在其中输入一些搜索内容,最后按下搜索按钮。然后你必须再次执行这三个步骤才能获取当前内容。
希望对您有所帮助....
public static void main(String[] args) throws IOException {
String url = "https://www.garageclothing.com/ca";
try (final WebClient webClient = new WebClient()) {
// do not stop at js errors
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getPage(url);
webClient.waitForBackgroundJavaScript(10000);
HtmlPage page = (HtmlPage) webClient.getCurrentWindow().getEnclosedPage();
HtmlInput searchInput = (HtmlInput) page.getElementById("searchText");
searchInput.type("red scarf");
HtmlElement submitBtn = (HtmlElement) page.getElementByName("search");
submitBtn.click();
webClient.waitForBackgroundJavaScript(10000);
page = (HtmlPage) webClient.getCurrentWindow().getEnclosedPage();
// System.out.println("------------------------------------------------");
// System.out.println(page.asXml());
System.out.println("------------------------------------------------");
final DomNodeList<DomNode> divs = page.querySelectorAll(".divProdPriceSale");
for (DomNode div : divs) {
System.out.println(div.asText());
}
}
}
我正在编写网络抓取工具,并试图在搜索框中输入搜索词。但是,当我尝试按 ID 访问搜索框时,我似乎得到了 null。我刚刚开始学习 HtmlUnit,所以我可能遗漏了一些非常明显的东西,但我自己还无法识别。
这是网站的代码:
<html xmlns="http://www.w3.org/1999/xhtml" xml:1ang="en" class="no-touch">
<head>-</head>
<body lang="en" class="garageBrand" emailcookiename="grgemailca" loyaltycookiename="grgloyaltyca">
<div id="fb-root" class="fb_reset">-</div>
<noscript>...</noscript>
<script>...</script>
<div id="container">
<div id="avsDialog" sty1e="disp1ay: none; position: absolute; top: 0; right: 0;"></div>
<input type="hidden" value="en" id="displayLanguage">
<input type="hidden" value="garageSiteCA" id="currSiteId">
<input type="hidden" value="en_CA" id="currLocale">
<div id="contentarea">
<div id="header" class="nonHeaderScroll">
<div id="topnav">...</div>
<div class="socialSearch">
<div id="searchMenu">
<form action="//www.garageclothing.com/ca/search/search.jsp" method="GET">
<input type="hidden" name="N" value="0">
<input type="hidden" name="Dy" value="1">
<input type="hidden" name="Nty" value="1">
<input type="hidden" name="Ntk" value="All">
<input type="hidden" name="Ntx" value="mode matchall">
<input id="searchText" maxlength="40" type="text" name="Ntt" class="textInput" placeholder="Search..." autocomplete="off">
<input class="mainSearchButton" type="image" src="//images.gdicdn.com/img/magnifying-glass.png?version=375" name="search">
</form>
</div>
这是我的代码:
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
import com.gargoylesoftware.htmlunit.html.HtmlInput;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
WebClient client = new WebClient();
client.getOptions().setJavaScriptEnabled(true);
client.getOptions().setCssEnabled(false);
client.getOptions().setUseInsecureSSL(true);
try {
HtmlPage page = client.getPage("https://www.garageclothing.com/ca");
// Check for popup.
if(page.getElementById("cboxClose") != null) {
page = page.getElementById("cboxClose").click();
}
// Debugging line that returns null:
System.out.println(page.getElementById("searchText"));
// What I would like to do:
/*HtmlInput searchInput = (HtmlInput) page.getElementById("searchText");
searchInput.setValueAttribute("red scarf");
HtmlSubmitInput submitBtn = page.getElementByName("search");
page = submitBtn.click();
System.out.println(page.asXml());*/
} catch (IOException e) {
e.printStackTrace();
}
}
}
您应该检查您传递给 WebClient
的 URL 是您正在使用的网络浏览器中查看的那个。
我访问了您在代码中使用的 link (https://www.garageclothing.com),但我得到的页面不是您期望的页面。它要求我选择一个国家(美国或加拿大),然后在我点击任何选项后,它会带我到你期望的页面。
尝试将 URL 更改为“https://www.garageclothing.com/us/" or "https://www.garageclothing.com/ca/”
即使页面看起来很简单,这个页面(就像许多购物门户网站一样)真的很复杂并且基于大量 javascript(不仅是页面本身,而且所有这些讨厌的跟踪器都需要观察用户)。如果您想了解有关此页面的更多信息,我建议使用像 Charles 这样的网络代理来捕获整个流量。
现在回到你的问题... 由于 HtmlUnit javascript 支持(基于 Rhino)并不完美,您会遇到一些 javascript 错误。为了不停止在 js 错误,你必须配置客户端
webClient.getOptions().setThrowExceptionOnScriptError(false);
下一步是获取页面。这也不是那么简单,因为所有的 js 东西。看起来 js 的东西也替换了最初通过获取 url 返回的页面。因此,您必须执行三个步骤
- 获取页面
- 等待一些时间让js做一些工作
- 从当前页面获取当前页面window
现在您可以找到搜索字段了;在其中输入一些搜索内容,最后按下搜索按钮。然后你必须再次执行这三个步骤才能获取当前内容。
希望对您有所帮助....
public static void main(String[] args) throws IOException {
String url = "https://www.garageclothing.com/ca";
try (final WebClient webClient = new WebClient()) {
// do not stop at js errors
webClient.getOptions().setThrowExceptionOnScriptError(false);
webClient.getPage(url);
webClient.waitForBackgroundJavaScript(10000);
HtmlPage page = (HtmlPage) webClient.getCurrentWindow().getEnclosedPage();
HtmlInput searchInput = (HtmlInput) page.getElementById("searchText");
searchInput.type("red scarf");
HtmlElement submitBtn = (HtmlElement) page.getElementByName("search");
submitBtn.click();
webClient.waitForBackgroundJavaScript(10000);
page = (HtmlPage) webClient.getCurrentWindow().getEnclosedPage();
// System.out.println("------------------------------------------------");
// System.out.println(page.asXml());
System.out.println("------------------------------------------------");
final DomNodeList<DomNode> divs = page.querySelectorAll(".divProdPriceSale");
for (DomNode div : divs) {
System.out.println(div.asText());
}
}
}