Получить HTML часть в Java - PullRequest
0 голосов
/ 20 ноября 2018

У меня возникли проблемы с пониманием того, как я могу загрузить только часть html-страницы.Я попробовал традиционный способ URL::openStream и BufferedReader, но я не совсем уверен, подтолкнет ли меня этот способ к загрузке всей страницы.Проблема в том, что у меня довольно большая HTML-страница, и мне нужно разобрать с нее 2 числа, которые обновляются как минимум раз в секунду.Способ выше помогает обнаруживать изменения раз в 2-3 секунды, и мне интересно, есть ли способ сделать это быстрее.Так что я подумал, что если отчасти получение страницы может мне помочь.

Ответы [ 2 ]

0 голосов
/ 21 ноября 2018

Написал помощник для чтения содержимого URL.Парсер для элементов другого класса.

public class HTMLReaderHelper {

private final URL currentURL;

HTMLReaderHelper(URL url){
    currentURL = url;
}

public CharIterator charIterator(){
    CharIterator iterator;
    try {
        iterator = new CharIterator();
    } catch(IOException ex){
        return null;
    }
    return iterator;
}

public StringIterator stringIterator(){
    return new StringIterator();
}

class CharIterator implements java.util.Iterator<Character>{

    private InputStream urlStream;

    private boolean isValid;

    private Queue<Character> buffer;

    private CharIterator() throws IOException {
        urlStream = currentURL.openStream();
        isValid = true;
        buffer = new ArrayDeque<>();
    }

    @Override
    public boolean hasNext() {
        char c;
        try {
            c = (char)urlStream.read();
            buffer.add(c);
        } catch (IOException ex) {
            markInvalid();
            return false;
        }
        return c != (char) -1;
    }

    @Override
    public Character next() {
        if(!isValid){
            return null;
        }
        char c;
        try {
            if(buffer.size() > 0){
                return buffer.remove();
            }
            c = (char)urlStream.read();
        } catch (IOException ex) {
            markInvalid();
            return null;
        }
        return (c != (char)-1) ? c : null;
    }

    private void markInvalid(){
        isValid = false;
    }
}

class StringIterator implements java.util.Iterator<String>{

    private CharIterator charPointer;

    private Queue<String> buffer;

    private boolean isValid;

    private StringIterator(){
        charPointer = charIterator();
        isValid = true;
        buffer = new ArrayDeque<>();
    }

    @Override
    public boolean hasNext() {
        String value = next();
        try {
            buffer.add(value);
        } catch (NullPointerException ex){
            markInvalid();
            return false;
        }
        return isValid;
    }

    @Override
    public String next() {
        if(buffer.size() > 0){
            return buffer.remove();
        }
        if(!isValid){
            return null;
        }
        StringBuilder sb = new StringBuilder();
        Character currentChar = charPointer.next();
        if(currentChar == null){
            return null;
        }
        while (currentChar.equals('\n') || currentChar.equals('\r')){
            currentChar = charPointer.next();
            if(currentChar == null){
                return null;
            }
        }
        while (currentChar != Character.valueOf('\n') && currentChar != Character.valueOf('\r')){
            sb.append(currentChar);
            currentChar = charPointer.next();
        }
        return sb.toString();
    }
    private void markInvalid(){
        isValid = false;
    }
}
}
0 голосов
/ 20 ноября 2018

Я думаю, вы должны увидеть, как извлекаются данные (SSE или WebSocket) и просто попытаться подписаться на эту услугу.Если это невозможно, попробуйте более эффективный анализатор XML.Я рекомендую https://vtd -xml.sourceforge.io / это может быть в ~ 10 раз быстрее, чем DOM-парсер, который поставляется с JDK.

Также будьте осторожны с BufferedReader.readLine(), так как естьскрытая стоимость выделения (это довольно сложный процесс, так как вам нужно думать о пропускной способности памяти процессора, пропусках кэша L1 и т. д.) для строк, которые вам на самом деле не нужны.

Пример использования библиотеки, о которой я говорил:

byte[] pageInBytes = readAllBytesFromTheURL();
VTDGen vg = new VTDGen();
vg.setDoc(pageInBytes);
vg.parse(false);
VTDNav vn = vg.getNav();

AutoPilot ap = new AutoPilot(vn);

//Jump to the section that we want to process
ap.selectXPath("/html/body/div");
String fileId = vn.toString(vu.getElementFragment());
...