尝试抓取网页时出现“无 javascript”错误

时间:2021-02-08 04:38:54

标签: java

public class SearchWalm {
    public static void main(String[] args) throws IOException, InterruptedException {
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://www.walmart.ca/en/electronics/N-32+103/page-13?sortBy=newest&orderBy=DESC"))
                .GET()
                .build();

        HttpResponse<String> response = client.send(request,
                HttpResponse.BodyHandlers.ofString());

        System.out.println(response.body());
    }
}

我正在尝试编写一个程序,该程序将筛选沃尔玛清仓部分的页面,然后选择一个关键字并告诉我它在哪个页面上找到了该关键字。

我收到错误“没有 javascript”和“您的网络浏览器没有运行 javascript”。我需要通过浏览器运行它还是只有 Java 才能做到这一点?

2 个答案:

答案 0 :(得分:1)

无头浏览器可以解决抓取问题,但不幸的是,您的网站使用 javascript 按需加载内容。要抓取按需数据加载,需要一个实际的浏览器。

我们使用 JsoupSelenium WebDeiver 来解决这个问题。 Selenium WebDriver 可以允许隐式等待(您设置一个计时器)或流畅等待。使用此等待,我们将等到所需数据完全加载。收到我们的内容后,您使用jsoup解析数据并找出您想要的结果。

您还需要在您的机器上安装 Chrome/Firefox 浏览器,并需要 ChromeDriver/FirefoxDriver。

  • 安装了 Homebrew 的 Mac 用户:brew tap homebrew/cask && brew cask install chromedriver
  • 基于 Debian 的 Linux 发行版:sudo apt-get installchromium-chromedriver
  • 安装了 Chocolatey 的 Windows 用户:choco install chromedriver

现在你运行下面的代码,它可以从搜索结果中搜索并显示标题。

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import java.io.IOException;
import java.util.concurrent.TimeUnit;


public class WebScraperJsOnload {
    public static void main(String[] args) throws IOException {
        
        String queryString = "https://www.walmart.ca/en/electronics/N-32+103/page-13?sortBy=newest&orderBy=DESC";
        
        WebDriver driver = new ChromeDriver();
        driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
        driver.get(queryString);
        
        Document doc = Jsoup.parse(driver.getPageSource());
        
        Elements newsHeadlines = doc.select(".title");
        for (Element headline : newsHeadlines) {
            log("Log: %s",headline.html());
        }
        
    }

    private static void log(String msg, String... vals) {
        System.out.println(String.format(msg, vals));
    }
}

此导入的 Maven 依赖项,

<dependency>
    <!-- jsoup HTML parser library @ https://jsoup.org/ -->
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.13.1</version>
</dependency>
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>3.141.59</version>
</dependency>

这个代码输出看起来像,

Log: <h2 class="thumb-header">Clearance Sale DR-E15 Fake Battery DC Coupler Battery Holder Mount Plate Power Supply Set Black</h2>
Log: <h2 class="thumb-header">Clearance Sale 2 in 1 4.7 inch Wireless U Disk Memory Expansion Phone Case for iPhone 6/6S/7 Red</h2>
Log: <h2 class="thumb-header">Clearance Sale USB Charging Power LED Selfie Ring Filling Light With Mobile Phone Clip Holder Black</h2>
Log: <h2 class="thumb-header">Clearance Sale Nillkin Protective Cover Plastic Hard Back Case Protect Mobile Phone Shell Red</h2>
Log: <h2 class="thumb-header">Clearance Sale Children'S Alarm Clock Creative Cute Cartoon Luminous Led Electronic Clock Pink</h2>
...
... 

要获取完整的项目,请下载此 Github Repo

答案 1 :(得分:0)

这有点像Java。在 Java 内部执行请求时,您会发送不同的标头集。当您附加“接受:*/*”标题时,我尝试了该网址并正常工作。

您无法使用当前的实现来实现,请使用 HttpClient 重新实现并添加缺少的标头。