mirror of
https://codeberg.org/icewind/ugc-scaper.git
synced 2026-06-03 18:24:10 +02:00
team list
This commit is contained in:
parent
e20a9cdae9
commit
202917c318
12 changed files with 128772 additions and 5 deletions
37
src/lib.rs
37
src/lib.rs
|
|
@ -3,10 +3,10 @@ mod error;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
|
|
||||||
use crate::data::{MembershipHistory, Player, RosterHistory, Seasons, Team, TeamSeason};
|
use crate::data::{MembershipHistory, Player, RosterHistory, Seasons, Team, TeamRef, TeamSeason};
|
||||||
use crate::parser::{
|
use crate::parser::{
|
||||||
Parser, PlayerDetailsParser, PlayerParser, SeasonsParser, TeamMatchesParser, TeamParser,
|
Parser, PlayerDetailsParser, PlayerParser, SeasonsParser, TeamLookupParser, TeamMatchesParser,
|
||||||
TeamRosterHistoryParser,
|
TeamParser, TeamRosterHistoryParser,
|
||||||
};
|
};
|
||||||
pub use error::*;
|
pub use error::*;
|
||||||
use reqwest::redirect::Policy;
|
use reqwest::redirect::Policy;
|
||||||
|
|
@ -24,6 +24,7 @@ pub struct UgcClient {
|
||||||
team_roster_history_parser: TeamRosterHistoryParser,
|
team_roster_history_parser: TeamRosterHistoryParser,
|
||||||
team_matches_parser: TeamMatchesParser,
|
team_matches_parser: TeamMatchesParser,
|
||||||
seasons_parser: SeasonsParser,
|
seasons_parser: SeasonsParser,
|
||||||
|
team_lookup_parser: TeamLookupParser,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// "API client" for ugc by scraping the website
|
/// "API client" for ugc by scraping the website
|
||||||
|
|
@ -37,6 +38,7 @@ impl UgcClient {
|
||||||
team_roster_history_parser: TeamRosterHistoryParser::new(),
|
team_roster_history_parser: TeamRosterHistoryParser::new(),
|
||||||
team_matches_parser: TeamMatchesParser::new(),
|
team_matches_parser: TeamMatchesParser::new(),
|
||||||
seasons_parser: SeasonsParser::new(),
|
seasons_parser: SeasonsParser::new(),
|
||||||
|
team_lookup_parser: TeamLookupParser::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,4 +132,33 @@ impl UgcClient {
|
||||||
.await?;
|
.await?;
|
||||||
self.seasons_parser.parse(&body)
|
self.seasons_parser.parse(&body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn teams(&self, link: &str) -> Result<Vec<TeamRef>> {
|
||||||
|
let body = self.client.get(link).send().await?.text().await?;
|
||||||
|
self.team_lookup_parser.parse(&body)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a list of all 9v9 teams
|
||||||
|
pub async fn teams_9v9(&self) -> Result<Vec<TeamRef>> {
|
||||||
|
self.teams("https://www.ugcleague.com/team_lookup_tf2h.cfm")
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a list of all 6v6 teams
|
||||||
|
pub async fn teams_6v6(&self) -> Result<Vec<TeamRef>> {
|
||||||
|
self.teams("https://www.ugcleague.com/team_lookup_tf26.cfm")
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a list of all 4v4 teams
|
||||||
|
pub async fn teams_4v4(&self) -> Result<Vec<TeamRef>> {
|
||||||
|
self.teams("https://www.ugcleague.com/team_lookup_tf24.cfm")
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a list of all 2v2 teams
|
||||||
|
pub async fn teams_2v2(&self) -> Result<Vec<TeamRef>> {
|
||||||
|
self.teams("https://www.ugcleague.com/team_lookup_tf22.cfm")
|
||||||
|
.await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ mod player;
|
||||||
mod player_details;
|
mod player_details;
|
||||||
mod seasons;
|
mod seasons;
|
||||||
mod team;
|
mod team;
|
||||||
|
mod team_lookup;
|
||||||
mod team_matches;
|
mod team_matches;
|
||||||
mod team_roster_history;
|
mod team_roster_history;
|
||||||
|
|
||||||
|
|
@ -15,6 +16,7 @@ pub use player::*;
|
||||||
pub use player_details::*;
|
pub use player_details::*;
|
||||||
pub use seasons::*;
|
pub use seasons::*;
|
||||||
pub use team::*;
|
pub use team::*;
|
||||||
|
pub use team_lookup::*;
|
||||||
pub use team_matches::*;
|
pub use team_matches::*;
|
||||||
pub use team_roster_history::*;
|
pub use team_roster_history::*;
|
||||||
|
|
||||||
|
|
|
||||||
65
src/parser/team_lookup.rs
Normal file
65
src/parser/team_lookup.rs
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
use super::Parser;
|
||||||
|
use crate::data::TeamRef;
|
||||||
|
use crate::parser::{team_id_from_link, ElementExt};
|
||||||
|
use crate::{ParseError, Result};
|
||||||
|
use scraper::{Html, Selector};
|
||||||
|
|
||||||
|
const SELECTOR_SELECT: &str = "select[name=\"clan_select\"]";
|
||||||
|
const SELECTOR_OPTION: &str = "option[value^=\"team_page\"]";
|
||||||
|
|
||||||
|
pub struct TeamLookupParser {
|
||||||
|
selector_select: Selector,
|
||||||
|
selector_option: Selector,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TeamLookupParser {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TeamLookupParser {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
TeamLookupParser {
|
||||||
|
selector_select: Selector::parse(SELECTOR_SELECT).unwrap(),
|
||||||
|
selector_option: Selector::parse(SELECTOR_OPTION).unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parser for TeamLookupParser {
|
||||||
|
type Output = Vec<TeamRef>;
|
||||||
|
|
||||||
|
fn parse(&self, document: &str) -> Result<Self::Output> {
|
||||||
|
let document = Html::parse_document(document);
|
||||||
|
|
||||||
|
let select =
|
||||||
|
document
|
||||||
|
.select(&self.selector_select)
|
||||||
|
.next()
|
||||||
|
.ok_or(ParseError::ElementNotFound {
|
||||||
|
selector: SELECTOR_SELECT,
|
||||||
|
role: "team list",
|
||||||
|
})?;
|
||||||
|
select
|
||||||
|
.select(&self.selector_option)
|
||||||
|
.map(|option| {
|
||||||
|
let link = option.attr("value").ok_or(ParseError::EmptyText {
|
||||||
|
role: "team link",
|
||||||
|
selector: SELECTOR_OPTION,
|
||||||
|
})?;
|
||||||
|
let text = option.first_text().ok_or(ParseError::EmptyText {
|
||||||
|
role: "team name",
|
||||||
|
selector: SELECTOR_OPTION,
|
||||||
|
})?;
|
||||||
|
let (_, name) = text.split_once("-").unwrap_or_default();
|
||||||
|
|
||||||
|
let id = team_id_from_link(link)?;
|
||||||
|
Ok(TeamRef {
|
||||||
|
id,
|
||||||
|
name: name.trim().to_string(),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
2983
tests/data/lookup_2v2.html
Normal file
2983
tests/data/lookup_2v2.html
Normal file
File diff suppressed because it is too large
Load diff
7157
tests/data/lookup_4v4.html
Normal file
7157
tests/data/lookup_4v4.html
Normal file
File diff suppressed because it is too large
Load diff
11476
tests/data/lookup_6v6.html
Normal file
11476
tests/data/lookup_6v6.html
Normal file
File diff suppressed because it is too large
Load diff
11729
tests/data/lookup_9v9.html
Normal file
11729
tests/data/lookup_9v9.html
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,8 +1,8 @@
|
||||||
use insta::assert_json_snapshot;
|
use insta::assert_json_snapshot;
|
||||||
use std::fs::read_to_string;
|
use std::fs::read_to_string;
|
||||||
use ugc_scraper::parser::{
|
use ugc_scraper::parser::{
|
||||||
Parser, PlayerDetailsParser, PlayerParser, SeasonsParser, TeamMatchesParser, TeamParser,
|
Parser, PlayerDetailsParser, PlayerParser, SeasonsParser, TeamLookupParser, TeamMatchesParser,
|
||||||
TeamRosterHistoryParser,
|
TeamParser, TeamRosterHistoryParser,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -60,3 +60,35 @@ fn test_parse_seasons_html() {
|
||||||
let parsed = parser.parse(&body).unwrap();
|
let parsed = parser.parse(&body).unwrap();
|
||||||
assert_json_snapshot!(parsed);
|
assert_json_snapshot!(parsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_seasons_9_html() {
|
||||||
|
let body = read_to_string("tests/data/lookup_9v9.html").unwrap();
|
||||||
|
let parser = TeamLookupParser::new();
|
||||||
|
let parsed = parser.parse(&body).unwrap();
|
||||||
|
assert_json_snapshot!(parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_seasons_6_html() {
|
||||||
|
let body = read_to_string("tests/data/lookup_6v6.html").unwrap();
|
||||||
|
let parser = TeamLookupParser::new();
|
||||||
|
let parsed = parser.parse(&body).unwrap();
|
||||||
|
assert_json_snapshot!(parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_seasons_4_html() {
|
||||||
|
let body = read_to_string("tests/data/lookup_4v4.html").unwrap();
|
||||||
|
let parser = TeamLookupParser::new();
|
||||||
|
let parsed = parser.parse(&body).unwrap();
|
||||||
|
assert_json_snapshot!(parsed);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_seasons_2_html() {
|
||||||
|
let body = read_to_string("tests/data/lookup_2v2.html").unwrap();
|
||||||
|
let parser = TeamLookupParser::new();
|
||||||
|
let parsed = parser.parse(&body).unwrap();
|
||||||
|
assert_json_snapshot!(parsed);
|
||||||
|
}
|
||||||
|
|
|
||||||
2526
tests/snapshots/snapshot__parse_seasons_2_html.snap
Normal file
2526
tests/snapshots/snapshot__parse_seasons_2_html.snap
Normal file
File diff suppressed because it is too large
Load diff
19114
tests/snapshots/snapshot__parse_seasons_4_html.snap
Normal file
19114
tests/snapshots/snapshot__parse_seasons_4_html.snap
Normal file
File diff suppressed because it is too large
Load diff
36390
tests/snapshots/snapshot__parse_seasons_6_html.snap
Normal file
36390
tests/snapshots/snapshot__parse_seasons_6_html.snap
Normal file
File diff suppressed because it is too large
Load diff
37262
tests/snapshots/snapshot__parse_seasons_9_html.snap
Normal file
37262
tests/snapshots/snapshot__parse_seasons_9_html.snap
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue