Sprawdzanie czy link prowadzi do strony

0

Hej!
Piszę w Javie modyfikator schowka systemowego.
Potrafię już rozpoznać jego typ (czy schowek jest dostępny w postaci plaintext).
Chciałbym sprawdzić czy tekst schowka prowadzi do jakiejkolwiek strony internetowej (czy jest linkiem).
Nie interesuje mnie strona a wynikami wyszukiwań w Google (tekst "forum" wpisany w pasku przeglądarki prowadzi do niej).
Wyrażenia regularne nie chcą działać, gdyż pojawiają się też różne dziwne linki.
Pozdrawiam!

0

Nie pisałem nic sieciowego jeszcze ale może po prostu spróbuj wywołać na danym tekście metodę ping. Wtedy po otrzymanej odpowiedzi z serwera nie tylko dowiesz się czy tekst jest linkiem ale też możesz sprawdzić czy serwer odpowiada czy nie.

0

Dzięki! Wpadłem właśnie na taki pomysł jakieś 10 minut temu.

Coś w stylu:

public static boolean isItValidLink (String linkCadidate) {
		
		HttpURLConnection connection = null;
		try {
			/*
			 * The next line can throw a MalformedURLException.
			 */
	        URL u = new URL(linkCadidate);
	        
	        
	        
	        /*
	         * The next two lines can throw many kinds of exceptions.
	         */
	        connection = (HttpURLConnection) u.openConnection();
	        connection.setRequestMethod("HEAD");
	        
	        
	        /*
	         * Returns -1 if no code can be discerned from the response (i.e., the response is not valid HTTP).
	         */
	        if (connection.getResponseCode() == -1)
	        	return false;
	    } catch (Exception e) {
	        return false;
	    }
		return true;
		
	}

Czekam na konstruktywną krytykę tego kodu.

0

Niestety dla: wp.pl wyrzuca wyjątek... tzn. nie jest to uznawane za URL przez Javę.

0

Pokaż cały kod

0

Przecież wp.pl nie jest linkiem.

0

Dla wp.pl czy też www.wp.pl nie działa opakowanie w javowego URLa.
Dla zdjęcia na facebooku - plik JPG (String rozpoczynający się od https://scontent.fwaw3-1.fna.fbcdn.net/hprofile-xpa1/v/t1.0-1/12105886...) nie działa z kolei ping.

Dlaczego tak się dzieje?

String linkCandidate = "www.wp.pl";
URL u = new URL(linkCadidate);

Wyrzuca wyjątek MalformedURLException. To samo dla "wp.pl".

Ping zależny od systemu:

 public static boolean isReachableByPing(String host) {
    try{
            String cmd = "";
            if(System.getProperty("os.name").startsWith("Windows")) {   
                    // For Windows
                    cmd = "ping -n 1 " + host;
            } else {
                    // For Linux and OSX
                    cmd = "ping -c 1 " + host;
            }

            Process myProcess = Runtime.getRuntime().exec(cmd);
            myProcess.waitFor();

            if(myProcess.exitValue() == 0) {

                    return true;
            } else {

                    return false;
            }

    } catch( Exception e ) {

            e.printStackTrace();
            return false;
    }
}

Nie działa dla zdjęcia na facebooku.
Z debuggera wiem, że myProcess.exitValue() wyrzuca 1.
Why?
Z góry dziękuję.

Zapomniałem dodać. Jest to publicznie dostępne zdjęcie.
Klikam prawym i daję na Copy Image Location w Mozilli Firefox.
Sorry, że rozpisałem kilka postów, powinien być jeden :p

0

www.wp.pl też nie jest linkiem, umieść w pliku html

<a href="www.wp.pl">Wirtualna Polska</a>

i spróbuj się połączyć.
Dokładniej, to jest link, ale nie do serwera tylko do pliku o nazwie www.wp.pl, który musi się znajdować obok pliku html z tym linkiem.
Poprawny URL rozpoczyna się od protokołu, np.

new URL("file://www.wp.pl");
new URL("http://www.wp.pl");
new URL("https://www.wp.pl");

Jeśli chodzi o ping, to nie wiem jaka jest wartość zmiennej host.
Polecenie

Process p = Runtime.getRuntime().exec("ping scontent.fwaw3-1.fna.fbcdn.net");

działa poprawnie. Być może Ty pingujesz do zdjęcia :P, a nie do serwera.

0

www.wp.pl też nie jest linkiem, umieść w pliku html

Dziękuję za odpowiedź!
Nie rozumiemy się, bo źle napisałem. Chodzi mi o "link" podany jako String w Javie.

Celem mojego programu (podprogramu) jest sprawdzenie dostępności danego adresu.
Prościej: co stanie się, jeśli wpiszemy ten String do paska adresu w przeglądarce.
Nie interesuje mnie strona Google z wynikami wyszukiwań (od kiedy większość przeglądarek ma taką funkcję, że z paska adresu możemy wyszukiwać jak w Google).
Interesuje mnie dostępność zarówno zdjęć czy innych plików, jak i innych nazw (np. wp.pl), z którymi można nawiązać połączenie.
Dlatego ani **ping **ani połączenie po próbie utworzenia URLa niezawsze działa... :(

Jeśli chodzi o ping, to nie wiem jaka jest wartość zmiennej host.
Polecenie

Process p = Runtime.getRuntime().exec("ping scontent.fwaw3-1.fna.fbcdn.net");

działa poprawnie. Być może Ty pingujesz do zdjęcia :P, a nie do serwera.

Tak pingowałem do zdjęcia.

Zauważyłem, że jeśli sprawdzę czy conajmniej jedna metoda (ping albo URL) nawiąże połączenie i zwróci true, można się połączyć, ale nie wiem czy jest to w pełni poprawne rozwiązanie.

Z góry dziękuję!

0

Ty czegoś nie rozumiesz, jeśli wpiszesz w pasku przeglądarki ciąg znaków np. jasna.dupa, to przeglądarka dopisze z przodu protokół (http://) oraz ciąg www i spróbuje się połączyć z adresem http://www.jasna.dupa. Natomiast konstruktor w klasie URL niczego nie dopisuje z przodu, Ty musisz podać poprawny adres, łącznie z protokołem.

0

Dziękuję za odpowiedź.

U mnie dopisuje z przodu tylko www.

Program ma być na tyle inteligentny, że rozpozna również skrócone nazwy :)
nietylko ładnie sformatowane URLe.

Za wiki:

Dzięki DNS nazwa mnemoniczna, np. pl.wikipedia.org jest tłumaczona na odpowiadający jej adres IP, czyli 91.198.174.192.

Pokusiło mnie to o trzecią metodę...

Podsumuję.

  1. Metoda sprawdza czy da się utworzyć na podstawie danego Stringu URLa oraz czy strona o tym URLu jest dostępna:
public static boolean isItValidLink (String linkCadidate) {
		
		HttpURLConnection connection = null;
		try {
			/*
			 * The next line can throw a MalformedURLException.
			 */
	        URL u = new URL(linkCadidate);
	        
	        
	        
	        /*
	         * The next two lines can throw many kinds of exceptions.
	         */
	        connection = (HttpURLConnection) u.openConnection();
	        connection.setRequestMethod("HEAD");
	        
	        
	        /*
	         * Returns -1 if no code can be discerned from the response (i.e., the response is not valid HTTP).
	         */
	        if (connection.getResponseCode() == -1)
	        	return false;
	    } catch (Exception e) {
	        return false;
	    }
		return true;
		
	}
  1. Metoda pinguje dany String.
public static boolean isReachableByPing(String host) {
	    try{
	            String cmd = "";
	            if(System.getProperty("os.name").startsWith("Windows")) {   
	                    // For Windows
	                    cmd = "ping -n 1 " + host;
	            } else {
	                    // For Linux and OSX
	                    cmd = "ping -c 1 " + host;
	            }

	            Process myProcess = Runtime.getRuntime().exec(cmd);
	            myProcess.waitFor();

	            if(myProcess.exitValue() == 0) {
	                    return true;
	            } else {
	                    return false;
	            }

	    } catch (Exception e ) {
	            e.printStackTrace();
	            return false;
	    }
	}
  1. Po trzecie klasa InetAdress.
import java.net.InetAddress;

W metodzie main:

System.out.println(ClipboardLinkShortener.isReachableByPing("www.wp.pl"));
    	System.out.println(ClipboardLinkShortener.isReachableByPing("wp.pl"));
    	System.out.println(ClipboardLinkShortener.isReachableByPing
    			("https://scontent-waw1-1.xx.fbcdn.net/hphotos-xft1/t31.0-8/1614068_820991184585112_155787083_o.jpg"));
        
    	System.out.println();
    	
    	System.out.println(ClipboardLinkShortener.isItValidLink("www.wp.pl"));
    	System.out.println(ClipboardLinkShortener.isItValidLink("wp.pl"));
    	System.out.println(ClipboardLinkShortener.isItValidLink
    			("https://scontent-waw1-1.xx.fbcdn.net/hphotos-xft1/t31.0-8/1614068_820991184585112_155787083_o.jpg"));	
    	
    	System.out.println();
    	
    	
    	System.out.println(InetAddress.getByName("wp.pl").isReachable(5000));
    	System.out.println(InetAddress.getByName("www.wp.pl").isReachable(5000));
    	System.out.println(InetAddress.getByName("https://scontent-waw1-1.xx.fbcdn.net/hphotos-xft1/t31.0-8/1614068_820991184585112_155787083_o.jpg").isReachable(5000));
    	

Co daje mi:

true
true
false

false
false
true

false
false
Exception in thread "main" java.net.UnknownHostException: https://scontent-waw1-1.xx.fbcdn.net/hphotos-xft1/t31.0-8/1614068_820991184585112_155787083_o.jpg
	at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)
	at java.net.InetAddress$1.lookupAllHostAddr(Unknown Source)
	at java.net.InetAddress.getAddressesFromNameService(Unknown Source)
	at java.net.InetAddress.getAllByName0(Unknown Source)
	at java.net.InetAddress.getAllByName(Unknown Source)
	at java.net.InetAddress.getAllByName(Unknown Source)
	at java.net.InetAddress.getByName(Unknown Source)
	at ClipboardLinkShortener.main(ClipboardLinkShortener.java:167)

Wniosek: alternatywa pierwszej oraz drugiej metody to może być rozwiązanie, ale czy na pewno poprawne?

0

U mnie dopisuje z przodu tylko www.

Mylisz się, dopisuje również protokół, ale go nie wyświetla. Skopiuj adres z paska przeglądarki do schowka i wklej do jakiegoś edytora.

Co Cię powstrzymuje przed najbardziej naturalnym rozwiązaniem: samemu uzupełniać kandydata na link protokołem z przodu? Coś w rodzaju

import java.net.*;
public class Test
{
    public static void main(String[] args)
    {
        System.out.println(isItValidLink("wp.pl"));
        System.out.println(isItValidLink("www.wp.pl"));
        System.out.println(isItValidLink("http://www.wp.pl"));
        System.out.println(isItValidLink("https://www.wp.pl"));
        System.out.println(isItValidLink("http://jasna.dupa"));
    }
    public static boolean isItValidLink (String linkCandidate) 
    {
        String[] urls;
        if(linkCandidate.toLowerCase().startsWith("https:"))
        {            
            urls = new String[]{linkCandidate,linkCandidate.replace("https:","http:")};
        }
        else if(linkCandidate.toLowerCase().startsWith("http:"))
        {
            urls = new String[]{linkCandidate,linkCandidate.replace("http:","https:")};
        }
        else
        {
            urls = new String[]{"http://"+linkCandidate,"https://"+linkCandidate};            
        }
        String protocol = "";
        HttpURLConnection connection = null;
        for(String url:urls)
        {
            try 
            {
                if(protocol.isEmpty())
                {
                    URL u = new URL(url);
                    connection = (HttpURLConnection) u.openConnection();
                    connection.setRequestMethod("HEAD");
                    if (connection.getResponseCode() != -1)
                    {
                        if(url.toLowerCase().startsWith("http:"))
                        {
                            protocol = "http";
                        }
                        else
                        {
                            protocol = "https";
                        }
                    }
                }
            } 
            catch (Exception e) 
            {
                System.out.println(e);
            }
        }
        System.out.println("Kandydat: "+linkCandidate+"  Protokol: "+protocol);
        return !protocol.isEmpty();
    }    
}

Wyjście

Kandydat: wp.pl  Protokol: http
true
Kandydat: www.wp.pl  Protokol: http
true
Kandydat: http://www.wp.pl  Protokol: http
true
java.net.ConnectException: Connection timed out: connect
Kandydat: https://www.wp.pl  Protokol: http
true
java.net.UnknownHostException: jasna.dupa
java.net.UnknownHostException: jasna.dupa
false

Działanie tej funkcji jest trochę mylące, zwraca true dla niepoprawnego adresu "https://www.wp.pl" - poprawia błędny protokół.
Przydatna byłaby też funkcja o sygnaturze

String createValidLink(String condidateLink)
0

Skopiuj adres z paska przeglądarki do schowka i wklej do jakiegoś edytora.

Tak, rzeczywiście dopisuje http.

Przydatna byłaby też funkcja o sygnaturze

String createValidLink(String condidateLink)

W dużej mierze byłoby to wydzielenie napisanego przez Ciebie kodu do tej metody.

Podoba mi się przedstawione przez Ciebie rozwiązanie, ale zastanawiam się jeszcze nad jakimiś kontrprzykładami.
Np. URLami z innych protokołów niż HTTP czy HTTPS, które również coś sobą reprezentują w przeglądarce.
Takie coś istnieje?

Z góry dzięki.

0

Generalnie celem programu jest wykrycie długiego adresu zapisanego w schowku systemowym oraz automatyczne skrócenie go.

1 użytkowników online, w tym zalogowanych: 0, gości: 1