From e8ef1fe6c4715a4c297588440e920cbd5f609eba Mon Sep 17 00:00:00 2001 From: Kate Date: Sun, 4 Jun 2023 17:21:24 +0100 Subject: [PATCH] Initial Commit --- .gitignore | 168 +++++++++++++++++++++++++++++++++++++++++++++++++ Pipfile | 15 +++++ group_info.py | 71 +++++++++++++++++++++ main.py | 24 +++++++ player_info.py | 28 +++++++++ 5 files changed, 306 insertions(+) create mode 100644 .gitignore create mode 100644 Pipfile create mode 100644 group_info.py create mode 100644 main.py create mode 100644 player_info.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1504fcf --- /dev/null +++ b/.gitignore @@ -0,0 +1,168 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +# ignore live config +config.py + +#i dont care if this is not recommended +Pipfile.lock + +.DS_Store \ No newline at end of file diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000..9f60daf --- /dev/null +++ b/Pipfile @@ -0,0 +1,15 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +requests = "*" +beautifulsoup4 = "*" +lxml = "*" +ratelimit = "*" + +[dev-packages] + +[requires] +python_version = "3.11" diff --git a/group_info.py b/group_info.py new file mode 100644 index 0000000..89856e2 --- /dev/null +++ b/group_info.py @@ -0,0 +1,71 @@ +import requests +from bs4 import BeautifulSoup +from ratelimit import limits, sleep_and_retry + +# Set up rate limiter, one request per second +CALLS = 1 +RATE_LIMIT = 1 + +@sleep_and_retry +@limits(calls=CALLS, period=RATE_LIMIT) +def get_group_details(group_url_name): + # Regular group page URL + group_url = f"https://steamcommunity.com/groups/{group_url_name}" + + try: + group_page_response = requests.get(group_url) + group_page_response.raise_for_status() + except requests.HTTPError as http_err: + print(f"HTTP error occurred: {http_err}") + return + except Exception as err: + print(f"Other error occurred: {err}") + return + + group_page_soup = BeautifulSoup(group_page_response.text, "lxml") + + # Group Tag + tag_span = group_page_soup.find("span", {"class": "grouppage_header_abbrev"}) + tag = tag_span.text.strip() if tag_span else "No tag" + + # Group details XML page URL + group_details_url = ( + f"https://steamcommunity.com/groups/{group_url_name}/memberslistxml/?xml=1" + ) + + try: + group_details_response = requests.get(group_details_url) + group_details_response.raise_for_status() + except requests.HTTPError as http_err: + print(f"HTTP error occurred: {http_err}") + return + except Exception as err: + print(f"Other error occurred: {err}") + return + + try: + group_details_soup = BeautifulSoup(group_details_response.content, "lxml-xml") + + # Group Name + group_name = group_details_soup.find("groupName").text + + # Group ID64 + group_id64 = group_details_soup.find("groupID64").text + + # Member List + members = [member.text for member in group_details_soup.find_all("steamID64")] + + return { + "group_id64": group_id64, + "group_name": group_name, + "group_url": group_url, + "tag": tag, + "members": members, + } + + except Exception as err: + print(f"Error occurred during parsing of group details XML page: {err}") + +if __name__ == "__main__": + # Replace 'ilovebloop' with the desired group URL name + print(get_group_details("CheeseFraud")) diff --git a/main.py b/main.py new file mode 100644 index 0000000..8fe5d72 --- /dev/null +++ b/main.py @@ -0,0 +1,24 @@ +from ratelimit import limits, sleep_and_retry +import group_info, player_info + +# Set up rate limiter, one request per second +CALLS = 1 +RATE_LIMIT = 1 + +starting_group = "ilovebloop" + +# Get the members of the starting group +print("[*] Getting members of starting group...") +starting_group_details = group_info.get_group_details(starting_group) +starting_group_members = starting_group_details["members"] + +# Get the groups of the starting group members +groups_of_starting_group_members = [] +for member in starting_group_members: + print(f"[*] Getting groups for member {member}...") + groups_of_starting_group_members.extend(player_info.get_group_links(member)) + +# Remove duplicates +groups_of_starting_group_members = list(set(groups_of_starting_group_members)) + +print(groups_of_starting_group_members) \ No newline at end of file diff --git a/player_info.py b/player_info.py new file mode 100644 index 0000000..b0e8a76 --- /dev/null +++ b/player_info.py @@ -0,0 +1,28 @@ +import requests +from bs4 import BeautifulSoup +from ratelimit import limits, sleep_and_retry + +# Set up rate limiter, one request per second +CALLS = 1 +RATE_LIMIT = 1 + +@sleep_and_retry +@limits(calls=CALLS, period=RATE_LIMIT) +def get_group_links(user_id): + url = f'https://steamcommunity.com/profiles/{user_id}/groups/' + response = requests.get(url) + + soup = BeautifulSoup(response.text, 'lxml') + + group_blocks = soup.find_all('div', class_='group_block') + group_links = [] + for block in group_blocks: + link_element = block.find('a', class_='linkTitle') + if link_element: + group_links.append(link_element['href'].split('/')[-1]) + + return group_links + +if __name__ == "__main__": + group_ids = get_group_links('76561198084483014') + print(group_ids) \ No newline at end of file