Evaluate JavaScript returning empty list , but working in PowerShell and CMD

270 views Asked by At

I have two evaluate javascript one is returning a null value and the other is returning an emptylist[1] when the list size is not greater than 0

both of them were giving the output when run in PowerShell with node on the local Windows machine

here is the Android code

public void ProfileData(String url, AllMediaCallback callback) {
        final ArrayList<String>[] arrayOfLists = new ArrayList[3]; // Change the size to match the number of lists you need
        arrayOfLists[0] = new ArrayList<>(); // Initialize the first ArrayList
        arrayOfLists[1] = new ArrayList<>(); // Initialize the second ArrayList
        arrayOfLists[2] = new ArrayList<>(); // Initialize the third ArrayList
        AtomicInteger evaluationCounter = new AtomicInteger(); // Define the evaluationCounter here
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Handler handler = new Handler(Looper.getMainLooper());
        webView.loadUrl(url);
        // Delayed operation
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public void onPageFinished(WebView view, String url) {
                new Handler().postDelayed(() -> webView.evaluateJavascript("javascript: \n" +
                        "    const pressableContainers = document.querySelectorAll('data-pressable-container=\"true\"');\n" +
                        "    const profileImgUrls = [];\n" +
                        "    pressableContainers.forEach(container => {\n" +
                        "        const draggables = container.querySelectorAll('draggable=\"false\"');\n" +
                        "        draggables.forEach(draggable => {\n" +
                        "            const srcValue = draggable.getAttribute('src');\n" +
                        "            profileImgUrls.push(srcValue);\n" +
                        "        });\n" +
                        "    });\n" +
                        "    \n" +
                        "    profileImgUrls;\n", value -> {


                    Collections.addAll(arrayOfLists[0], value);
                    // Increase the evaluation counter
                    evaluationCounter.getAndIncrement();

                    // Check if both evaluations are done
                    if (evaluationCounter.get() == 3 && callback != null) {
                        callback.onAllMediiaStatusRecived(arrayOfLists);
                    }

                }), 2000);

                new Handler().postDelayed(() ->  webView.evaluateJavascript(
                        "javascript: \n" +
                                "    const pressableContainers = document.querySelectorAll('data-pressable-container=\"true\"');\n" +
                                "    const profileImgUrls = [];\n" +
                                "    pressableContainers.forEach(container => {\n" +
                                "        const videos = container.querySelectorAll('video');\n" +
                                "        \n" +
                                "        videos.forEach(video => {\n" +
                                "            const srcValue = video.getAttribute('src');\n" +
                                "            profileImgUrls.push(srcValue);\n" +
                                "        });\n" +
                                "    });\n" +
                                "    \n" +
                                "    profileImgUrls;\n", value -> {


                    Collections.addAll(arrayOfLists[1], value);
                    // Increase the evaluation counter
                    evaluationCounter.getAndIncrement();

                    // Check if both evaluations are done
                    if (evaluationCounter.get() == 3 && callback != null) {
                        callback.onAllMediiaStatusRecived(arrayOfLists);
                    }

                }), 2000);

               // Ignore this one its not related to evaluatejavascript 
                executor.execute(new Runnable() {
                    @Override
                    public void run() {

                        try {
                            Document document = Jsoup.connect(url).get();
                            Elements metaTags = document.getElementsByTag("meta");

                            for (Element metaTag : metaTags) {
                                String property = metaTag.attr("property");
                                String content = metaTag.attr("content");

                                if (property.equals("og:description")) {
                                    arrayOfLists[2].add(content);
                                }

                                if (property.equals("og:image")) {
                                    content = content.replace("&amp;", "&");
                                    arrayOfLists[2].add(content);
                                }
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                        handler.post(() -> {
                            // Increase the evaluation counter
                            evaluationCounter.getAndIncrement();

                            // Check if both evaluations are done
                            if (evaluationCounter.get() == 3 && callback != null) {
                                callback.onAllMediiaStatusRecived(arrayOfLists);
                            }
                        });
                    }
                });


            }
        });


    }


    public interface AllMediaCallback {
    void onAllMediiaStatusRecived(ArrayList<String>[] ArrayOfLists);
}

 ProfileData(linkUrl, new AllMediaCallback() {
                @Override
                public void onAllMediiaStatusRecived(ArrayList<String>[] ArrayOfLists) {
                
                    if (ArrayOfLists[0].size() > 0) {
                        for (String strImage : ArrayOfLists[0]) {
                            Toast.makeText(getApplicationContext(), strImage, Toast.LENGTH_SHORT).show();
                        }
                    } else {
                        Toast.makeText(getApplicationContext(), "Empty List[0]", Toast.LENGTH_SHORT).show();
                    }

                    if (ArrayOfLists[1].size() > 0) {
                        for (String strImage : ArrayOfLists[1]) {
                            Toast.makeText(getApplicationContext(), strImage, Toast.LENGTH_SHORT).show();
                        }

                    } else {
                        Toast.makeText(getApplicationContext(), "Empty List[1]", Toast.LENGTH_SHORT).show();
                    }


                }
            });

And here is the node.js script, please note here I have used puppter for loading the webpage, as it is not needed in webview client in android

Image.js

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  // Replace 'your_url_here' with the actual URL you want to load
  await page.goto('https://www.threads.net/@sagar_v_raval');

  // Wait for the content to load (you might need to adjust the selector and waiting time)
  await page.waitForSelector('[data-pressable-container="true"]');

  const srcValues = await page.evaluate(() => {
    const pressableContainers = document.querySelectorAll('[data-pressable-container="true"]');
    const srcValues = [];

    pressableContainers.forEach(container => {
      const draggables = container.querySelectorAll('[draggable="false"]');
      
      draggables.forEach(draggable => {
        const srcValue = draggable.getAttribute('src');
        srcValues.push(srcValue);
      });
    });

    return srcValues;
  });

  console.log(srcValues);

  await browser.close();
})();

Video.js

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({ headless: 'new' });
  const page = await browser.newPage();

  // Replace 'your_url_here' with the actual URL you want to load
  await page.goto('https://www.threads.net/@sagar_v_raval');

  // Wait for the content to load (you might need to adjust the selector and waiting time)
  await page.waitForSelector('[data-pressable-container="true"]');

  const srcValues = await page.evaluate(() => {
    const pressableContainers = document.querySelectorAll('[data-pressable-container="true"]');
    const srcValues = [];

    pressableContainers.forEach(container => {
      const videos = container.querySelectorAll('video'); // Select video elements with the 'video-class' class
      
      videos.forEach(video => {
        const srcValue = video.getAttribute('src');
        srcValues.push(srcValue);
      });
    });

    return srcValues;
  });

  console.log(srcValues);

  await browser.close();
})();
3

There are 3 answers

4
Ron Gilchrist On

You are missing brackets I think. Change this line:

"    const pressableContainers = document.querySelectorAll('data-pressable-container=\"true\"');\n" +

To include brackets when querying for an attribute

"    const pressableContainers = document.querySelectorAll('[data-pressable-container=\"true\"]');\n" +
1
KennyC On

I might be wrong, but far as I know, browser will render html and Js line by line, while facing async/ await the function will go to event loop, so browser can keep rendering, call Js function in on page finished, could lead a possibility that html parsing is finish, but async/await function is not, therefore you execute your Js function before async/ await result back.

A simple way to verify this is using a button, you manually check website has right data, then trigger Js.

The other possiblity come to my mind is WebView does not support some methods, I believe mdn will mentioned those situations.

8
LickingFilth On

Use js to check if media elements loaded before running your main js code - window.onload or document.addEventListener('DOMContentLoaded', function() {}) will do the trick.

webView.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageFinished(WebView view, String url) {
        webView.evaluateJavascript("javascript: \n" +
            "    window.onload = function() {\n" +
            "        // code here\n" +
            "    };\n", value -> {
            // android code here
        });
    }
});