Skip to content

Commit

Permalink
Added SystemRequirements for games (Product.cs) and updated readme (b…
Browse files Browse the repository at this point in the history
…igtime)
  • Loading branch information
liebki committed Jul 27, 2022
1 parent 8a32dd3 commit 6d19eb0
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 31 deletions.
4 changes: 3 additions & 1 deletion MMOGAScraper/Product.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{
public class Product
{
public Product(bool isNotAvailable, string shopCategory, string cover, ProductType type, string link, string title, decimal price, bool isPriceReduced, decimal reducedPrice, string platformLogo, ProductDeliveryTime deliveryTime, DateTime deliveryTimeCustomDate, ProductAvailability availability, string region, string platform, string description, string extendedDescription, bool isPaypalAvailable)
public Product(bool isNotAvailable, string shopCategory, string cover, ProductType type, string link, string title, decimal price, bool isPriceReduced, decimal reducedPrice, string platformLogo, ProductDeliveryTime deliveryTime, DateTime deliveryTimeCustomDate, ProductAvailability availability, string region, string platform, string description, string extendedDescription, Requirements systemRequirements, bool isPaypalAvailable)
{
IsNotAvailable = isNotAvailable;
ShopCategory = shopCategory;
Expand All @@ -21,6 +21,7 @@ public Product(bool isNotAvailable, string shopCategory, string cover, ProductTy
Platform = platform;
Description = description;
ExtendedDescription = extendedDescription;
SystemRequirements = systemRequirements;
IsPaypalAvailable = isPaypalAvailable;
}

Expand All @@ -41,6 +42,7 @@ public Product(bool isNotAvailable, string shopCategory, string cover, ProductTy
public string Platform { get; set; }
public string Description { get; set; }
public string ExtendedDescription { get; set; }
public Requirements SystemRequirements { get; set; }
public bool IsPaypalAvailable { get; set; }
}
}
14 changes: 13 additions & 1 deletion MMOGAScraper/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public static void Main()
MmogaScraper scraper = new(ScraperRegion.DE);

const string querystring = "fifa"; //What to search for on mmoga.de
const int pages = 8;
const int pages = 2;//What number of pages to search for on mmoga.de
Console.WriteLine($"Querying: {querystring} for {pages} pages");

#region Page number example
Expand Down Expand Up @@ -90,6 +90,18 @@ private static void PrintProduct(Product product)
{
Console.WriteLine($"Delivery time: {product.DeliveryTime}");
}
if (product.SystemRequirements.Available)
{
if (product.SystemRequirements.Uncomplete)
{
Console.WriteLine($"Requirements: {product.SystemRequirements.Text}");
}
else
{
Console.WriteLine($"Requirements (minimum): {product.SystemRequirements.Minimum}");
Console.WriteLine($"Requirements (maximum): {product.SystemRequirements.Maximum}");
}
}
Console.WriteLine($"Paypal available: {product.IsPaypalAvailable}");
Console.WriteLine($"Region: {product.Region}");
Console.WriteLine($"Platform: {product.Platform}");
Expand Down
25 changes: 25 additions & 0 deletions MMOGAScraper/Requirements.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
namespace MMOGAScraper
{
public class Requirements
{
public Requirements(bool available, string minimum, string maximum, bool uncomplete, string text)
{
Available = available;
Minimum = minimum;
Maximum = maximum;
Uncomplete = uncomplete;
Text = text;
}

public bool Available { get; set; }
public string Minimum { get; set; }
public string Maximum { get; set; }
public bool Uncomplete { get; set; }
public string Text { get; set; }

public override string ToString()
{
return $"{{{nameof(Available)}={Available}, {nameof(Minimum)}={Minimum}, {nameof(Maximum)}={Maximum}, {nameof(Uncomplete)}={Uncomplete}, {nameof(Text)}={Text}}}";
}
}
}
35 changes: 34 additions & 1 deletion MMOGAScraper/ScraperMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,11 @@ internal static Product GetProductType(string ProductLink)
IsConsoleGame = true;
}

Requirements requirements = new(false, "", "", true, "");
ProductType Type;
if (doc.DocumentNode.SelectSingleNode("/html/body/div[2]/div/div[5]/ul/li[2]/p") != null && !IsDlc && !IsGiftcard && !IsRandomObject)
{
requirements = ParseRequirementsNode(doc, requirements);
Type = ProductType.Game;
}
else if (IsDlc)
Expand Down Expand Up @@ -223,7 +225,7 @@ internal static Product GetProductType(string ProductLink)

#region Product object

Product product = new(IsGameNotAvailable, ShopCategory, CoverImage, Type, ProductLink, ProductTitle, ReturnDecimalValue(Price), PriceReduced, ReturnDecimalValue(ReducedPrice), PlatformLogoSource, DeliveryTime, CustomDeliveryTime, Availability, Region, Platform, ProductDescription, DescriptionText, IsPaypalAvailable);
Product product = new(IsGameNotAvailable, ShopCategory, CoverImage, Type, ProductLink, ProductTitle, ReturnDecimalValue(Price), PriceReduced, ReturnDecimalValue(ReducedPrice), PlatformLogoSource, DeliveryTime, CustomDeliveryTime, Availability, Region, Platform, ProductDescription, DescriptionText, requirements, IsPaypalAvailable);

#endregion Product object

Expand All @@ -233,6 +235,37 @@ internal static Product GetProductType(string ProductLink)
return null;
}

private static Requirements ParseRequirementsNode(HtmlDocument doc, Requirements requirements)
{
HtmlNode RequirementsData = doc.DocumentNode.SelectSingleNode("/html/body/div[2]/div/div[5]/ul/li[2]/div/p[2]");
string RequirementsText = WhitespaceNewLineRemover(RequirementsData.InnerText);
if (RequirementsText.Contains("Minimum") && RequirementsText.Contains("Empfohlen"))
{
string[] RequirementsTextParsed = RequirementsText.Split("Empfohlen");
string RequirementsMinimum = RequirementsTextParsed[0].Split("Minimum")[1];
string RequirementsMaximum = RequirementsTextParsed[1];
RequirementsMinimum = FilterRequirementsData(RequirementsMinimum, false);
RequirementsMaximum = FilterRequirementsData(RequirementsMaximum, false);
requirements = new(true, RequirementsMinimum, RequirementsMaximum, false, "");
}
else
{
requirements.Text = FilterRequirementsData(RequirementsText, true);
}

return requirements;
}

private static string FilterRequirementsData(string input, bool small)
{
if (small)
{
input = input.Replace("Betriebssystem:", " Betriebssystem:");
}
input = input.Replace("Prozessor:", " Prozessor:").Replace("Arbeitsspeicher:", " Arbeitsspeicher:").Replace("Grafikkarte:", " Grafikkarte:").Replace("Speicherplatz:", " Speicherplatz:").Replace("Breitband", " Breitband");
return input;
}

internal static int CalculateQueryPageNumber(HtmlDocument doc)
{
int MaxPagesForProduct = 1;
Expand Down
69 changes: 41 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,52 @@
# MMOGA Product Scraper - MMOGA-PS (API)
# MMOGA Product Scraper (API)

#### Projekt von https://github.com/liebki
##### Projekt von https://github.com/liebki

A scraper to get products including the (possible) data of https://mmoga.de
## Introduction

### Why does this exist?

I originally needed a way to parse prices for games, for [BlazorLibrary](https://github.com/liebki/BlazorLibrary), now I created this and I might implement it in some time.

### General

So this tool/api, is scraper to get products (and their data) of https://mmoga.de (And soon all other regions like US, UK etc.)

## Technologies

### Created using
- .NET Core 6.0

### Nuget(s)
- HtmlAgilityPack
### Nugets/Dependencies
- [HtmlAgilityPack](https://www.nuget.org/packages/HtmlAgilityPack/)

## Features

### What data is available right now?
- To see what data is available, please take a look in the Product.cs and/or LightProduct.cs

To see what data is available, please take a look in the [LightProduct](https://github.com/liebki/MMOGA-Product-Scraper/blob/master/MMOGAScraper/LightProduct.cs)/[Product](https://github.com/liebki/MMOGA-Product-Scraper/blob/master/MMOGAScraper/Product.cs).cs classes

### General
- Get a list of product objects, those can be used to get prices, availabilities, platforms etc.
- Some products wont be found using the DeeperSearch, because atm I didn't include a way to parse them
- To get **every** (possible made) product, use the QuickSearch but you will loose detail
- I will include every product in the DeeperSearch but it is one of my things on the TO-DO so you have to wait

Get a ```List<LightProduct>``` or ```List<Product>```, the objects inside of the lists (depending on the object), contain data like availabilities, prices and much more.

#### Information

Some products wont be parsed by the "DeeperSearch", to get **every** (parseable) product, use the "QuickSearch" (you will loose some data, compare the LightProduct and Product to know which).
Im working on including every product for the "DeeperSearch" but it is one of my things on the TO-DO so you have to wait

## Usage

### Code/Methods to use

The MmogaScraper class contains a "QuickSearch" and a "DeeperSearch" method.
QuickSearch will provide you faster results but with fewer detail, it will miss following data of the DeeperSearch:
Type
Platform/Logo
Delivery time
Region
Description
Extended description
Paypal availability

Because of this there is a LightProduct (QuickSearch) and a Product (DeeperSearch).
The MmogaScraper class contains a "QuickSearch", "DeeperSearch", "PagenumberSearch" and "DeeperSearch_Alpha" method.
- QuickSearch: Provides you with faster results but with fewer detail
- DeeperSearch: Provides you with the complete data but it is slower
- PagenumberSearch: Provides you with the number of pages a query gives back
- DeeperSearch_Alpha: Provides you with the complete data but it is slower and you can select the number of pages you want to have the data of

```
//Get the number of pages a query produces
int QueryPagenumber = MmogaScraper.PagenumberSearch("what I got");
Expand All @@ -52,30 +59,34 @@ List<Product> ProductList = MmogaScraper.DeeperSearch("what you need");
//This version of DeeperSearch is not 100% finished, tho it is working!
//Get all the data, using the slower search AND search on more than just the first page
List<Product> ProductListAlpha = MmogaScraper.DeeperSearch_Alpha("search them good", pages_as_int);
```

## Example

### Code (Program.cs)
Please take a look in the *Program.cs*, the code there is showing a working example for scraping "fifa", using Quick- and DeeperSearch.
### Code

Please take a look in the *[Program.cs](https://github.com/liebki/MMOGA-Product-Scraper/blob/master/MMOGAScraper/Program.cs)*, the code there is showing a working example for scraping "fifa", using
"QuickSearch", "DeeperSearch_Alpha" and "PagenumberSearch".

### Output

GIF shows content of "cyberpunk" scraping:
![Logo](https://iili.io/ksX3Vp.gif)

## FAQ

#### Does this work on every mmoga page?
#### Does this work on every mmoga region?

I created this for mmoga.**DE** I don't know about mmoga.com or other regions in general
I created this explicitly for mmoga.(DE) I don't know about mmoga.com or other regions in general, but I am working on including them.

#### Why can't I obtain data X?

I'm trying my best, so please be patient or include the things you like to see yourself or contact me :)

#### Is it working?

Right now in end of July '22, this tool is working pretty good
Right now in end of July '22, this tool is working pretty nice!

## License

Expand All @@ -90,8 +101,10 @@ Right now in end of July '22, this tool is working pretty good
## Roadmap

#### Sorted by importancy
- Include more pages than just the first page of the search (WIP, 50% done)
- Option to change region of mmoga
- Include more pages than just the first page of the search (Almost done, WIP)
- Option to change region of mmoga (WIP)
- Create more objects for things, like payment ways etc.
- Parse similar products on a products site
- Parse "coming soon" products
- Parse "hits" products
- Parse "preorder" products
Expand Down

0 comments on commit 6d19eb0

Please sign in to comment.