Nano Hash - криптовалюты, майнинг, программирование

Собрать информацию с веб-страниц с помощью Java?

Я пытаюсь извлечь данные с веб-страницы, например, допустим, я хочу получить информацию с chess.org.

Я знаю, что идентификатор игрока 25022, что означает, что я могу запросить http://www.chess.org.il/Players/Player.aspx?Id=25022

На этой странице я вижу, что идентификатор fide этого игрока = 2821109.
Отсюда я могу запросить эту страницу:
http://ratings.fide.com/card.phtml?event=2821109

И из этого я вижу, что stdRating=1602.

Как я могу получить вывод «stdRating» из заданного ввода «localID» в Java?

(localID, fideID и stdRating — вспомогательные параметры, которые я использую для уточнения вопроса)


  • Добро пожаловать в Stack Overflow. В дополнение к вашему словесному описанию того, что вы делаете, очень поможет увидеть некоторый код, чтобы показать, что вы пробовали. Ознакомьтесь с минимально воспроизводимым примером, чтобы получить несколько советов по созданию примера кода. Также прочитайте Как спросить, чтобы получить советы по улучшению вашего вопроса. 18.06.2018
  • Вам нужно будет проанализировать эти параметры из страниц, возвращенных на эти запросы. Для этого отлично подходят такие инструменты, как JSoup, jsoup.org. 18.06.2018

Ответы:


1

Как указал @Alex R, для этого вам понадобится библиотека Web Scraping.
Тот, который он рекомендуемый, JSoup, достаточно надежен и довольно часто используется для этой задачи в Java, по крайней мере, по моему опыту.

Сначала вам нужно создать документ, который извлекает вашу страницу, например:

int localID = 25022; //your player's ID.
Document doc = Jsoup.connect("http://www.chess.org.il/Players/Player.aspx?Id=" + localID).get();

Из этого объекта Document можно извлечь много информации, например например, запрошенный вами идентификатор ФИДЕ, к сожалению, веб-страницу, на которую вы ссылаетесь, очень легко очистить, и вам нужно будет пройти по каждой ссылке на странице, чтобы найти соответствующую ссылку, например:

Elements fidelinks = doc.select("a[href*=fide.com]");

Этот объект Elements должен предоставить вам список всех ссылок, ведущих на все, что содержит текст fide.com, но вероятно вам нужен только первый, например:

Element fideurl = doc.selectFirst("a[href=*=fide.com]");

С этого момента я не хочу писать весь код за вас, но, надеюсь, этот ответ послужит хорошей отправной точкой!

Вы можете получить идентификатор самостоятельно, вызвав text(). для вашего объекта Element, но вы также можете получить саму ссылку, просто позвонив Element.attr('href')

Селектор css, который вы можете использовать для получения другого значения, — div#main-col table.contentpaneopen tbody tr td table tbody tr td table tbody tr:nth-of-type(4) td table tbody tr td:first-of-type, который даст вам стандартную оценку, по крайней мере, со стандартным css, так что это также должно работать с jsoup.

18.06.2018
  • Я использую: Element fideurl = doc.selectFirst(a[href*=fide.com]); int fideID = Integer.parseInt(fideurl.text()); и это работает, но для второго параметра: Element stdRatingurl = doc2.selectFirst(a[small*=std.]); или: Элемент stdRatingurl = doc2.selectFirst(table.contentpaneopen.tr.td.table.tr.td.table.tr.td.Federation); (для другого параметра) не сработало... не могли бы вы мне помочь? 19.06.2018
  • Они действительно не упрощают поиск этого элемента, один момент. 20.06.2018
  • Я добавил решение вопроса, пожалуйста, не забудьте пометить ответы как принятые, если они решают вашу проблему 20.06.2018
  • И если вы хотите получить stdRatingURl из идентификатора fide, вы можете просто вызвать fideurl.attr('href'), который должен дать вам ссылку, на которую ссылается элемент привязки. 20.06.2018

  • 2

    Вы можете попробовать univocity-html-parser, это очень просто использовать и избежать большого количества спагетти-кода.

    Например, чтобы получить стандартный рейтинг, вы можете использовать этот код:

    public static void main(String... args) {
        UrlReaderProvider url = new UrlReaderProvider("http://ratings.fide.com/card.phtml?event={EVENT}");
        url.getRequest().setUrlParameter("EVENT", 2821109);
    
        HtmlElement doc = HtmlParser.parseTree(url);
    
        String rating = doc.query()
                .match("small").withText("std.")
                .match("br").getFollowingText()
                .getValue();
    
        System.out.println(rating);
    }
    

    Что дает значение 1602.

    Но получить данные, запрашивая отдельные узлы и пытаясь сшить все части воедино, не совсем просто.

    Я расширил код, чтобы проиллюстрировать, как вы можете использовать парсер для получения дополнительной информации в записях. Здесь я создал записи для игрока и сведения о его ранге, которые доступны в таблице на второй странице. На это у меня ушло менее 1 часа:

    public static void main(String... args) {
        UrlReaderProvider url = new UrlReaderProvider("http://www.chess.org.il/Players/Player.aspx?Id={PLAYER_ID}");
        url.getRequest().setUrlParameter("PLAYER_ID", 25022);
    
        HtmlEntityList entities = new HtmlEntityList();
        HtmlEntitySettings player = entities.configureEntity("player");
        player.addField("id").match("b").withExactText("מספר שחקן").getFollowingText().transform(s -> s.replaceAll(": ", ""));
        player.addField("name").match("h1").followedImmediatelyBy("b").withExactText("מספר שחקן").getText();
        player.addField("date_of_birth").match("b").withExactText("תאריך לידה:").getFollowingText();
        player.addField("fide_id").matchFirst("a").attribute("href", "http://ratings.fide.com/card.phtml?event=*").getText();
    
        HtmlLinkFollower playerCard = player.addField("fide_card_url").matchFirst("a").attribute("href", "http://ratings.fide.com/card.phtml?event=*").getAttribute("href").followLink();
        playerCard.addField("rating_std").match("small").withText("std.").match("br").getFollowingText();
        playerCard.addField("rating_rapid").match("small").withExactText("rapid").match("br").getFollowingText();
        playerCard.addField("rating_blitz").match("small").withExactText("blitz").match("br").getFollowingText();
        playerCard.setNesting(Nesting.REPLACE_JOIN);
    
        HtmlEntitySettings ratings = playerCard.addEntity("ratings");
        configureRatingsBetween(ratings, "World Rank", "National Rank ISR", "world");
        configureRatingsBetween(ratings, "National Rank ISR", "Continent Rank Europe", "country");
        configureRatingsBetween(ratings, "Continent Rank Europe", "Rating Chart", "continent");
    
        Results<HtmlParserResult> results = new HtmlParser(entities).parse(url);
        HtmlParserResult playerData = results.get("player");
        String[] playerFields = playerData.getHeaders();
    
        for(HtmlRecord playerRecord : playerData.iterateRecords()){
            for(int i = 0; i < playerFields.length; i++){
                System.out.print(playerFields[i] + ": " + playerRecord.getString(playerFields[i]) +"; ");
            }
            System.out.println();
    
            HtmlParserResult ratingData = playerRecord.getLinkedEntityData().get("ratings");
            for(HtmlRecord ratingRecord : ratingData.iterateRecords()){
                System.out.print(" * " + ratingRecord.getString("rank_type") + ": ");
                System.out.println(ratingRecord.fillFieldMap(new LinkedHashMap<>(), "all_players", "active_players", "female", "u16", "female_u16"));
            }
        }
    }
    
    private static void configureRatingsBetween(HtmlEntitySettings ratings, String startingHeader, String endingHeader, String rankType) {
        Group group = ratings.newGroup()
                .startAt("table").match("b").withExactText(startingHeader)
                .endAt("b").withExactText(endingHeader);
    
        group.addField("rank_type", rankType);
    
        group.addField("all_players").match("tr").withText("World (all", "National (all", "Rank (all").match("td", 2).getText();
        group.addField("active_players").match("tr").followedImmediatelyBy("tr").withText("Female (active players):").match("td", 2).getText();
        group.addField("female").match("tr").withText("Female (active players):").match("td", 2).getText();
        group.addField("u16").match("tr").withText("U-16 Rank (active players):").match("td", 2).getText();
        group.addField("female_u16").match("tr").withText("Female U-16 Rank (active players):").match("td", 2).getText();
    }
    

    Вывод будет:

    id: 25022; name: יעל כהן; date_of_birth: 02/02/2003; fide_id: 2821109; rating_std: 1602; rating_rapid: 1422; rating_blitz: 1526; 
     * world: {all_players=195907, active_players=94013, female=5490, u16=3824, female_u16=586}
     * country: {all_players=1595, active_players=1024, female=44, u16=51, female_u16=3}
     * continent: {all_players=139963, active_players=71160, female=3757, u16=2582, female_u16=372}
    

    Надеюсь, поможет

    Раскрытие информации: я автор этой библиотеки. Это коммерческий закрытый исходный код, но он может сэкономить вам много времени на разработку.

    09.07.2018
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..