From 8604066f77f4dc211558a3d64877e3f0194bd539 Mon Sep 17 00:00:00 2001 From: Christopher Meinhold Date: Sun, 15 Sep 2024 21:43:55 +0200 Subject: [PATCH] Push --- Grosshandel2/Grosshandel2.sln | 25 ++ Grosshandel2/Grosshandel2/Artikel.cs | 11 + Grosshandel2/Grosshandel2/DatabaseManager.cs | 132 +++++++ Grosshandel2/Grosshandel2/FrmMain.Designer.cs | 158 ++++++++ Grosshandel2/Grosshandel2/FrmMain.cs | 161 ++++++++ Grosshandel2/Grosshandel2/FrmMain.resx | 120 ++++++ Grosshandel2/Grosshandel2/Grosshandel2.csproj | 15 + Grosshandel2/Grosshandel2/Program.cs | 17 + webCrawlerGoogle/.gitattributes | 63 +++ webCrawlerGoogle/.gitignore | 363 ++++++++++++++++++ webCrawlerGoogle/webCrawlerGoogle.sln | 25 ++ .../webCrawlerGoogle/Form1.Designer.cs | 110 ++++++ webCrawlerGoogle/webCrawlerGoogle/Form1.cs | 267 +++++++++++++ webCrawlerGoogle/webCrawlerGoogle/Form1.resx | 120 ++++++ webCrawlerGoogle/webCrawlerGoogle/Program.cs | 17 + .../webCrawlerGoogle/Sicherung.txt | 198 ++++++++++ .../webCrawlerGoogle/app.manifest.xml | 10 + .../webCrawlerGoogle/webCrawlerGoogle.csproj | 20 + 18 files changed, 1832 insertions(+) create mode 100644 Grosshandel2/Grosshandel2.sln create mode 100644 Grosshandel2/Grosshandel2/Artikel.cs create mode 100644 Grosshandel2/Grosshandel2/DatabaseManager.cs create mode 100644 Grosshandel2/Grosshandel2/FrmMain.Designer.cs create mode 100644 Grosshandel2/Grosshandel2/FrmMain.cs create mode 100644 Grosshandel2/Grosshandel2/FrmMain.resx create mode 100644 Grosshandel2/Grosshandel2/Grosshandel2.csproj create mode 100644 Grosshandel2/Grosshandel2/Program.cs create mode 100644 webCrawlerGoogle/.gitattributes create mode 100644 webCrawlerGoogle/.gitignore create mode 100644 webCrawlerGoogle/webCrawlerGoogle.sln create mode 100644 webCrawlerGoogle/webCrawlerGoogle/Form1.Designer.cs create mode 100644 webCrawlerGoogle/webCrawlerGoogle/Form1.cs create mode 100644 webCrawlerGoogle/webCrawlerGoogle/Form1.resx create mode 100644 webCrawlerGoogle/webCrawlerGoogle/Program.cs create mode 100644 webCrawlerGoogle/webCrawlerGoogle/Sicherung.txt create mode 100644 webCrawlerGoogle/webCrawlerGoogle/app.manifest.xml create mode 100644 webCrawlerGoogle/webCrawlerGoogle/webCrawlerGoogle.csproj diff --git a/Grosshandel2/Grosshandel2.sln b/Grosshandel2/Grosshandel2.sln new file mode 100644 index 0000000..4ecc49f --- /dev/null +++ b/Grosshandel2/Grosshandel2.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.11.35222.181 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Grosshandel2", "Grosshandel2\Grosshandel2.csproj", "{5D9FD5F3-4DDE-4E45-9959-04AA4F5C3518}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5D9FD5F3-4DDE-4E45-9959-04AA4F5C3518}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5D9FD5F3-4DDE-4E45-9959-04AA4F5C3518}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5D9FD5F3-4DDE-4E45-9959-04AA4F5C3518}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5D9FD5F3-4DDE-4E45-9959-04AA4F5C3518}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E7F8D8D2-C3A7-4A56-A1E4-C87D3096EEC0} + EndGlobalSection +EndGlobal diff --git a/Grosshandel2/Grosshandel2/Artikel.cs b/Grosshandel2/Grosshandel2/Artikel.cs new file mode 100644 index 0000000..c5d972a --- /dev/null +++ b/Grosshandel2/Grosshandel2/Artikel.cs @@ -0,0 +1,11 @@ +namespace Grosshandel2 +{ + public class Artikel + { + public int ArtikelId { get; set; } + public string Name { get; set; } + public decimal Preis { get; set; } + public decimal Grosshandelspreis { get; set; } + public byte[] Bild { get; set; } + } +} diff --git a/Grosshandel2/Grosshandel2/DatabaseManager.cs b/Grosshandel2/Grosshandel2/DatabaseManager.cs new file mode 100644 index 0000000..ec654b0 --- /dev/null +++ b/Grosshandel2/Grosshandel2/DatabaseManager.cs @@ -0,0 +1,132 @@ +using System; +using System.Data; +using MySql.Data.MySqlClient; + +namespace Grosshandel2 +{ + public class DatabaseManager + { + private string _connectionString = "Server=192.168.178.201;Database=grosshandel;User ID=root;Password=1td5rugut8;"; + + public DataTable GetArtikelListe() + { + using (var connection = new MySqlConnection(_connectionString)) + { + var query = @"SELECT a.ArtikelId, a.Name, p.Preis, p.Grosshandelspreis + FROM Artikel a + JOIN Preise p ON a.ArtikelId = p.ArtikelId"; + + using (var adapter = new MySqlDataAdapter(query, connection)) + { + var dataTable = new DataTable(); + adapter.Fill(dataTable); + return dataTable; + } + } + } + + public void AddArtikel(Artikel artikel, byte[] bild) + { + using (var connection = new MySqlConnection(_connectionString)) + { + connection.Open(); + + using (var transaction = connection.BeginTransaction()) + { + // Füge den Artikel hinzu + var insertArtikelQuery = "INSERT INTO Artikel (Name, Bild) VALUES (@Name, @Bild); SELECT LAST_INSERT_ID();"; + var command = new MySqlCommand(insertArtikelQuery, connection, transaction); + command.Parameters.AddWithValue("@Name", artikel.Name); + command.Parameters.AddWithValue("@Bild", bild ?? (object)DBNull.Value); + + // Hole die zuletzt eingefügte ArtikelId + var artikelId = Convert.ToInt32(command.ExecuteScalar()); + + // Füge den Preis hinzu + var insertPreisQuery = "INSERT INTO Preise (ArtikelId, Preis, Grosshandelspreis) VALUES (@ArtikelId, @Preis, @Grosshandelspreis);"; + command = new MySqlCommand(insertPreisQuery, connection, transaction); + command.Parameters.AddWithValue("@ArtikelId", artikelId); + command.Parameters.AddWithValue("@Preis", artikel.Preis); + command.Parameters.AddWithValue("@Grosshandelspreis", artikel.Grosshandelspreis); + command.ExecuteNonQuery(); + + transaction.Commit(); + } + } + } + + + public void UpdateArtikel(Artikel artikel, byte[] bild) + { + using (var connection = new MySqlConnection(_connectionString)) + { + connection.Open(); + + using (var transaction = connection.BeginTransaction()) + { + var updateArtikelQuery = "UPDATE Artikel SET Name = @Name, Bild = @Bild WHERE ArtikelId = @ArtikelId;"; + var command = new MySqlCommand(updateArtikelQuery, connection, transaction); + command.Parameters.AddWithValue("@Name", artikel.Name); + command.Parameters.AddWithValue("@Bild", bild ?? (object)DBNull.Value); + command.Parameters.AddWithValue("@ArtikelId", artikel.ArtikelId); + command.ExecuteNonQuery(); + + var updatePreisQuery = "UPDATE Preise SET Preis = @Preis, Grosshandelspreis = @Grosshandelspreis WHERE ArtikelId = @ArtikelId;"; + command = new MySqlCommand(updatePreisQuery, connection, transaction); + command.Parameters.AddWithValue("@Preis", artikel.Preis); + command.Parameters.AddWithValue("@Grosshandelspreis", artikel.Grosshandelspreis); + command.Parameters.AddWithValue("@ArtikelId", artikel.ArtikelId); + command.ExecuteNonQuery(); + + transaction.Commit(); + } + } + } + + public void DeleteArtikel(int artikelId) + { + using (var connection = new MySqlConnection(_connectionString)) + { + connection.Open(); + + using (var transaction = connection.BeginTransaction()) + { + var deletePreisQuery = "DELETE FROM Preise WHERE ArtikelId = @ArtikelId;"; + var command = new MySqlCommand(deletePreisQuery, connection, transaction); + command.Parameters.AddWithValue("@ArtikelId", artikelId); + command.ExecuteNonQuery(); + + var deleteArtikelQuery = "DELETE FROM Artikel WHERE ArtikelId = @ArtikelId;"; + command = new MySqlCommand(deleteArtikelQuery, connection, transaction); + command.Parameters.AddWithValue("@ArtikelId", artikelId); + command.ExecuteNonQuery(); + + transaction.Commit(); + } + } + } + public byte[] GetBildByArtikelId(int artikelId) + { + byte[] bild = null; + + using (var connection = new MySqlConnection(_connectionString)) + { + connection.Open(); + var query = "SELECT Bild FROM Artikel WHERE ArtikelId = @ArtikelId"; + using (var command = new MySqlCommand(query, connection)) + { + command.Parameters.AddWithValue("@ArtikelId", artikelId); + using (var reader = command.ExecuteReader()) + { + if (reader.Read()) + { + bild = reader["Bild"] as byte[]; + } + } + } + } + + return bild; + } + } +} diff --git a/Grosshandel2/Grosshandel2/FrmMain.Designer.cs b/Grosshandel2/Grosshandel2/FrmMain.Designer.cs new file mode 100644 index 0000000..f6ca829 --- /dev/null +++ b/Grosshandel2/Grosshandel2/FrmMain.Designer.cs @@ -0,0 +1,158 @@ +namespace Grosshandel2 +{ + partial class FrmMain + { + private System.ComponentModel.IContainer components = null; + private System.Windows.Forms.DataGridView dataGridView1; + private System.Windows.Forms.TextBox txtName; + private System.Windows.Forms.NumericUpDown numericPreis; + private System.Windows.Forms.NumericUpDown numericGrosshandelspreis; + private System.Windows.Forms.Button btnAdd; + private System.Windows.Forms.Button btnUpdate; + private System.Windows.Forms.Button btnDelete; + private System.Windows.Forms.PictureBox pictureBox; + private System.Windows.Forms.TextBox txtBildPfad; + private System.Windows.Forms.Button btnBrowseImage; + + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + private void InitializeComponent() + { + this.dataGridView1 = new System.Windows.Forms.DataGridView(); + this.txtName = new System.Windows.Forms.TextBox(); + this.numericPreis = new System.Windows.Forms.NumericUpDown(); + this.numericGrosshandelspreis = new System.Windows.Forms.NumericUpDown(); + this.btnAdd = new System.Windows.Forms.Button(); + this.btnUpdate = new System.Windows.Forms.Button(); + this.btnDelete = new System.Windows.Forms.Button(); + this.pictureBox = new System.Windows.Forms.PictureBox(); + this.txtBildPfad = new System.Windows.Forms.TextBox(); + this.btnBrowseImage = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericPreis)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericGrosshandelspreis)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).BeginInit(); + this.SuspendLayout(); + // + // dataGridView1 + // + this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.dataGridView1.Location = new System.Drawing.Point(12, 12); + this.dataGridView1.Name = "dataGridView1"; + this.dataGridView1.RowHeadersWidth = 51; + this.dataGridView1.RowTemplate.Height = 24; + this.dataGridView1.Size = new System.Drawing.Size(776, 150); + this.dataGridView1.TabIndex = 0; + this.dataGridView1.SelectionChanged += new System.EventHandler(this.dataGridView1_SelectionChanged); + // + // txtName + // + this.txtName.Location = new System.Drawing.Point(12, 200); + this.txtName.Name = "txtName"; + this.txtName.Size = new System.Drawing.Size(200, 22); + this.txtName.TabIndex = 1; + // + // numericPreis + // + this.numericPreis.DecimalPlaces = 2; + this.numericPreis.Location = new System.Drawing.Point(12, 250); + this.numericPreis.Name = "numericPreis"; + this.numericPreis.Size = new System.Drawing.Size(120, 22); + this.numericPreis.TabIndex = 2; + // + // numericGrosshandelspreis + // + this.numericGrosshandelspreis.DecimalPlaces = 2; + this.numericGrosshandelspreis.Location = new System.Drawing.Point(12, 300); + this.numericGrosshandelspreis.Name = "numericGrosshandelspreis"; + this.numericGrosshandelspreis.Size = new System.Drawing.Size(120, 22); + this.numericGrosshandelspreis.TabIndex = 3; + // + // btnAdd + // + this.btnAdd.Location = new System.Drawing.Point(250, 200); + this.btnAdd.Name = "btnAdd"; + this.btnAdd.Size = new System.Drawing.Size(75, 23); + this.btnAdd.TabIndex = 4; + this.btnAdd.Text = "Hinzufügen"; + this.btnAdd.UseVisualStyleBackColor = true; + this.btnAdd.Click += new System.EventHandler(this.btnAdd_Click); + // + // btnUpdate + // + this.btnUpdate.Location = new System.Drawing.Point(250, 250); + this.btnUpdate.Name = "btnUpdate"; + this.btnUpdate.Size = new System.Drawing.Size(75, 23); + this.btnUpdate.TabIndex = 5; + this.btnUpdate.Text = "Aktualisieren"; + this.btnUpdate.UseVisualStyleBackColor = true; + this.btnUpdate.Click += new System.EventHandler(this.btnUpdate_Click); + // + // btnDelete + // + this.btnDelete.Location = new System.Drawing.Point(250, 300); + this.btnDelete.Name = "btnDelete"; + this.btnDelete.Size = new System.Drawing.Size(75, 23); + this.btnDelete.TabIndex = 6; + this.btnDelete.Text = "Löschen"; + this.btnDelete.UseVisualStyleBackColor = true; + this.btnDelete.Click += new System.EventHandler(this.btnDelete_Click); + // + // pictureBox + // + this.pictureBox.Location = new System.Drawing.Point(400, 200); + this.pictureBox.Name = "pictureBox"; + this.pictureBox.Size = new System.Drawing.Size(200, 200); + this.pictureBox.TabIndex = 7; + this.pictureBox.TabStop = false; + this.pictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; + // + // txtBildPfad + // + this.txtBildPfad.Location = new System.Drawing.Point(400, 150); + this.txtBildPfad.Name = "txtBildPfad"; + this.txtBildPfad.Size = new System.Drawing.Size(200, 22); + this.txtBildPfad.TabIndex = 8; + // + // btnBrowseImage + // + this.btnBrowseImage.Location = new System.Drawing.Point(625, 150); + this.btnBrowseImage.Name = "btnBrowseImage"; + this.btnBrowseImage.Size = new System.Drawing.Size(75, 23); + this.btnBrowseImage.TabIndex = 9; + this.btnBrowseImage.Text = "Durchsuchen"; + this.btnBrowseImage.UseVisualStyleBackColor = true; + this.btnBrowseImage.Click += new System.EventHandler(this.btnBrowseImage_Click); + // + // FrmMain + // + this.ClientSize = new System.Drawing.Size(800, 450); + this.Controls.Add(this.btnBrowseImage); + this.Controls.Add(this.txtBildPfad); + this.Controls.Add(this.pictureBox); + this.Controls.Add(this.btnDelete); + this.Controls.Add(this.btnUpdate); + this.Controls.Add(this.btnAdd); + this.Controls.Add(this.numericGrosshandelspreis); + this.Controls.Add(this.numericPreis); + this.Controls.Add(this.txtName); + this.Controls.Add(this.dataGridView1); + this.Name = "FrmMain"; + this.Text = "Artikelverwaltung"; + this.Load += new System.EventHandler(this.FrmMain_Load); + ((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericPreis)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericGrosshandelspreis)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + } + } +} diff --git a/Grosshandel2/Grosshandel2/FrmMain.cs b/Grosshandel2/Grosshandel2/FrmMain.cs new file mode 100644 index 0000000..4c396d1 --- /dev/null +++ b/Grosshandel2/Grosshandel2/FrmMain.cs @@ -0,0 +1,161 @@ +using System; +using System.Data; +using System.Windows.Forms; + +namespace Grosshandel2 +{ + public partial class FrmMain : Form + { + private DatabaseManager _dbManager; + private Artikel _currentArtikel; + + public FrmMain() + { + InitializeComponent(); + _dbManager = new DatabaseManager(); + } + + private void FrmMain_Load(object sender, EventArgs e) + { + LoadArtikelData(); + } + + private void LoadArtikelData() + { + try + { + var artikelTable = _dbManager.GetArtikelListe(); + if (artikelTable != null) + { + dataGridView1.DataSource = artikelTable; + } + else + { + MessageBox.Show("Keine Artikel gefunden."); + } + } + catch (Exception ex) + { + MessageBox.Show($"Fehler beim Laden der Artikel: {ex.Message}"); + } + } + + private void btnAdd_Click(object sender, EventArgs e) + { + // Erstelle ein neues Artikel-Objekt + var artikel = new Artikel + { + Name = txtName.Text, + Preis = numericPreis.Value, + Grosshandelspreis = numericGrosshandelspreis.Value + }; + + // Lade das Bild, falls ein Bildpfad angegeben ist + byte[] bildBytes = null; + if (!string.IsNullOrEmpty(txtBildPfad.Text)) + { + bildBytes = LoadImageFromFile(txtBildPfad.Text); + } + + try + { + // Füge den Artikel zur Datenbank hinzu + _dbManager.AddArtikel(artikel, bildBytes); + + // Lade die Artikel-Daten neu + LoadArtikelData(); + + // Bestätigungsnachricht + MessageBox.Show("Artikel erfolgreich hinzugefügt."); + } + catch (Exception ex) + { + MessageBox.Show("Fehler beim Hinzufügen des Artikels: " + ex.Message); + } + } + + private void btnUpdate_Click(object sender, EventArgs e) + { + if (_currentArtikel != null) + { + _currentArtikel.Name = txtName.Text; + _currentArtikel.Preis = numericPreis.Value; + _currentArtikel.Grosshandelspreis = numericGrosshandelspreis.Value; + _currentArtikel.Bild = File.ReadAllBytes(txtBildPfad.Text); + _dbManager.UpdateArtikel(_currentArtikel, _currentArtikel.Bild); + LoadArtikelData(); + } + } + + private void btnDelete_Click(object sender, EventArgs e) + { + if (_currentArtikel != null) + { + _dbManager.DeleteArtikel(_currentArtikel.ArtikelId); + LoadArtikelData(); + _currentArtikel = null; + ClearForm(); + } + } + + private void dataGridView1_SelectionChanged(object sender, EventArgs e) + { + if (dataGridView1.SelectedRows.Count > 0) + { + var selectedRow = dataGridView1.SelectedRows[0]; + var artikelId = Convert.ToInt32(selectedRow.Cells["ArtikelId"].Value); + + // Abrufen des Bildes aus der Datenbank + var bildBytes = _dbManager.GetBildByArtikelId(artikelId); + + if (bildBytes != null && bildBytes.Length > 0) + { + using (var ms = new MemoryStream(bildBytes)) + { + pictureBox.Image = Image.FromStream(ms); + } + } + else + { + pictureBox.Image = null; + } + + txtName.Text = selectedRow.Cells["Name"].Value.ToString(); + numericPreis.Value = Convert.ToDecimal(selectedRow.Cells["Preis"].Value); + numericGrosshandelspreis.Value = Convert.ToDecimal(selectedRow.Cells["Grosshandelspreis"].Value); + txtBildPfad.Text = string.Empty; // Optional, falls du den Bildpfad anzeigen möchtest + } + } + + private void ClearForm() + { + txtName.Clear(); + numericPreis.Value = 0; + numericGrosshandelspreis.Value = 0; + txtBildPfad.Clear(); + pictureBox.Image = null; + } + private void btnBrowseImage_Click(object sender, EventArgs e) + { + using (var openFileDialog = new OpenFileDialog()) + { + if (openFileDialog.ShowDialog() == DialogResult.OK) + { + txtBildPfad.Text = openFileDialog.FileName; + pictureBox.Image = Image.FromFile(openFileDialog.FileName); + } + } + } + private byte[] LoadImageFromFile(string filePath) + { + if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath)) + { + return null; + } + + return File.ReadAllBytes(filePath); + } + + + } +} diff --git a/Grosshandel2/Grosshandel2/FrmMain.resx b/Grosshandel2/Grosshandel2/FrmMain.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/Grosshandel2/Grosshandel2/FrmMain.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Grosshandel2/Grosshandel2/Grosshandel2.csproj b/Grosshandel2/Grosshandel2/Grosshandel2.csproj new file mode 100644 index 0000000..bd1d994 --- /dev/null +++ b/Grosshandel2/Grosshandel2/Grosshandel2.csproj @@ -0,0 +1,15 @@ + + + + WinExe + net8.0-windows + enable + true + enable + + + + + + + \ No newline at end of file diff --git a/Grosshandel2/Grosshandel2/Program.cs b/Grosshandel2/Grosshandel2/Program.cs new file mode 100644 index 0000000..0a7fa23 --- /dev/null +++ b/Grosshandel2/Grosshandel2/Program.cs @@ -0,0 +1,17 @@ +namespace Grosshandel2 +{ + internal static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + // To customize application configuration such as set high DPI settings or default font, + // see https://aka.ms/applicationconfiguration. + ApplicationConfiguration.Initialize(); + Application.Run(new FrmMain()); + } + } +} \ No newline at end of file diff --git a/webCrawlerGoogle/.gitattributes b/webCrawlerGoogle/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/webCrawlerGoogle/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/webCrawlerGoogle/.gitignore b/webCrawlerGoogle/.gitignore new file mode 100644 index 0000000..9491a2f --- /dev/null +++ b/webCrawlerGoogle/.gitignore @@ -0,0 +1,363 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd \ No newline at end of file diff --git a/webCrawlerGoogle/webCrawlerGoogle.sln b/webCrawlerGoogle/webCrawlerGoogle.sln new file mode 100644 index 0000000..c1cbc0e --- /dev/null +++ b/webCrawlerGoogle/webCrawlerGoogle.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.35122.118 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "webCrawlerGoogle", "webCrawlerGoogle\webCrawlerGoogle.csproj", "{36E507D2-6D2C-43DD-9E30-F7E151018942}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {36E507D2-6D2C-43DD-9E30-F7E151018942}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {36E507D2-6D2C-43DD-9E30-F7E151018942}.Debug|Any CPU.Build.0 = Debug|Any CPU + {36E507D2-6D2C-43DD-9E30-F7E151018942}.Release|Any CPU.ActiveCfg = Release|Any CPU + {36E507D2-6D2C-43DD-9E30-F7E151018942}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FB32F52A-3116-4EB2-A3D9-B6435A5B7A2E} + EndGlobalSection +EndGlobal diff --git a/webCrawlerGoogle/webCrawlerGoogle/Form1.Designer.cs b/webCrawlerGoogle/webCrawlerGoogle/Form1.Designer.cs new file mode 100644 index 0000000..11f1309 --- /dev/null +++ b/webCrawlerGoogle/webCrawlerGoogle/Form1.Designer.cs @@ -0,0 +1,110 @@ +namespace webCrawlerGoogle +{ + partial class Form1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + txtCategory = new TextBox(); + txtCity = new TextBox(); + btnSearch = new Button(); + lstResults = new ListBox(); + lblFortschritt = new Label(); + SuspendLayout(); + // + // txtCategory + // + txtCategory.Location = new Point(14, 14); + txtCategory.Margin = new Padding(4, 3, 4, 3); + txtCategory.Name = "txtCategory"; + txtCategory.PlaceholderText = "Rubrik (z.B. Restaurant)"; + txtCategory.Size = new Size(303, 23); + txtCategory.TabIndex = 0; + // + // txtCity + // + txtCity.Location = new Point(14, 44); + txtCity.Margin = new Padding(4, 3, 4, 3); + txtCity.Name = "txtCity"; + txtCity.PlaceholderText = "Stadt (z.B. Berlin)"; + txtCity.Size = new Size(303, 23); + txtCity.TabIndex = 1; + // + // btnSearch + // + btnSearch.Location = new Point(14, 74); + btnSearch.Margin = new Padding(4, 3, 4, 3); + btnSearch.Name = "btnSearch"; + btnSearch.Size = new Size(303, 27); + btnSearch.TabIndex = 2; + btnSearch.Text = "Suchen"; + btnSearch.UseVisualStyleBackColor = true; + btnSearch.Click += btnSearch_Click; + // + // lstResults + // + lstResults.FormattingEnabled = true; + lstResults.ItemHeight = 15; + lstResults.Location = new Point(14, 107); + lstResults.Margin = new Padding(4, 3, 4, 3); + lstResults.Name = "lstResults"; + lstResults.Size = new Size(303, 169); + lstResults.TabIndex = 3; + // + // lblFortschritt + // + lblFortschritt.AutoSize = true; + lblFortschritt.Location = new Point(18, 290); + lblFortschritt.Name = "lblFortschritt"; + lblFortschritt.Size = new Size(10, 15); + lblFortschritt.TabIndex = 4; + lblFortschritt.Text = "."; + // + // Form1 + // + AutoScaleDimensions = new SizeF(7F, 15F); + AutoScaleMode = AutoScaleMode.Font; + ClientSize = new Size(334, 350); + Controls.Add(lblFortschritt); + Controls.Add(lstResults); + Controls.Add(btnSearch); + Controls.Add(txtCity); + Controls.Add(txtCategory); + Margin = new Padding(4, 3, 4, 3); + Name = "Form1"; + Text = "Google Business Suche"; + ResumeLayout(false); + PerformLayout(); + } + + #endregion + private System.Windows.Forms.TextBox txtCategory; + private System.Windows.Forms.TextBox txtCity; + private System.Windows.Forms.Button btnSearch; + private System.Windows.Forms.ListBox lstResults; + private Label lblFortschritt; + } +} diff --git a/webCrawlerGoogle/webCrawlerGoogle/Form1.cs b/webCrawlerGoogle/webCrawlerGoogle/Form1.cs new file mode 100644 index 0000000..1209ea5 --- /dev/null +++ b/webCrawlerGoogle/webCrawlerGoogle/Form1.cs @@ -0,0 +1,267 @@ +using MySql.Data.MySqlClient; +using HtmlAgilityPack; +using System; +using System.Net.Http; +using System.Threading.Tasks; +using System.Diagnostics; +using OpenQA.Selenium; +using OpenQA.Selenium.Chrome; + +namespace webCrawlerGoogle +{ + public partial class Form1 : Form + { + private static string connectionString = "Server=192.168.178.201;Database=domainchecker;User ID=root;Password=1td5rugut8;"; + private static int searchCounter = 0; + private static int maxSearchesBeforeVPNChange = 20; // Anzahl der Suchanfragen, bevor der VPN gewechselt wird + private static int pauseAfterEachSearchMs = 500; // Pause nach jeder Suchanfrage (2 Sekunden) + private static int longPauseAfterBatchMs = 60000; // Längere Pause nach einer Reihe von Suchanfragen (1 Minute) + private static int fortschritt = 0; + public Form1() + { + InitializeComponent(); + } + + private async void btnSearch_Click(object sender, EventArgs e) + { + var searchParams = LoadSearchParamsFromDatabase(); + + foreach (var param in searchParams) + { + string category = param.Rubrik; + string city = param.Stadt; + + //AppendToOutput($"Suche nach: {category} in {city}"); + await ScrapeGoogleResults(category, city); + + searchCounter++; + if (searchCounter >= maxSearchesBeforeVPNChange) + { + ChangeVPN(); + searchCounter = 0; + + //AppendToOutput("Längere Pause nach VPN-Wechsel..."); + await Task.Delay(longPauseAfterBatchMs); + } + else + { + //AppendToOutput("Kurze Pause nach Suchanfrage..."); + await Task.Delay(pauseAfterEachSearchMs); + } + } + } + + private async Task ScrapeGoogleResults(string category, string city) + { + string query = $"{category}+in+{city}"; + string searchUrl = $"https://www.google.com/search?q=" + query; + //$"https://www.google.com/search?q={Uri.EscapeDataString(query)}"; + + var options = new ChromeOptions(); + options.AddArgument("headless"); + options.AddArgument("disable-gpu"); + + using (var driver = new ChromeDriver(options)) + { + driver.Navigate().GoToUrl(searchUrl); + + await Task.Delay(2000); // Warte ein wenig, damit die Seite vollständig geladen wird + + var titleNodes = driver.FindElements(By.XPath("//h3[@class='LC20lb MBeuO DKV0Md']")); + + if (titleNodes != null && titleNodes.Count > 0) + { + + foreach (var node in titleNodes) + { + // Hier könntest du auch die zugehörige URL extrahieren + var parent = node.FindElement(By.XPath("./ancestor::a")); + if (parent != null) + { + string url = parent.GetAttribute("href"); + string cleanedUrl = CleanUrl(url); + + if (!CheckIfUrlExistsInDatabase(cleanedUrl)) + { + fortschritt++; + SaveUrlToDatabase(cleanedUrl, city, category); + AppendToOutput(cleanedUrl); + lblFortschritt.Text = $"Aktuell hinzugefügt Anzahl {fortschritt}"; + Application.DoEvents(); + } + } + } + } + else + { + AppendToOutput("Keine Titel gefunden."); + } + } + } + bool CheckIfUrlExistsInDatabase(string url) + { + using (MySqlConnection conn = new MySqlConnection(connectionString)) + { + conn.Open(); + string query = "SELECT COUNT(*) FROM webCrawler WHERE webseite = @url"; + using (MySqlCommand cmd = new MySqlCommand(query, conn)) + { + cmd.Parameters.AddWithValue("@url", url); + int count = Convert.ToInt32(cmd.ExecuteScalar()); + return count > 0; + } + } + } + + void SaveUrlToDatabase(string url, string city, string category) + { + using (MySqlConnection conn = new MySqlConnection(connectionString)) + { + conn.Open(); + string query = "INSERT INTO webCrawler(email, webseite, stadt, rubrik) VALUES(@value1, @value2, @value3, @value4)"; + using (MySqlCommand cmd = new MySqlCommand(query, conn)) + { + cmd.Parameters.AddWithValue("@value1", ""); // Leere E-Mail, da nicht angegeben + cmd.Parameters.AddWithValue("@value2", url); + cmd.Parameters.AddWithValue("@value3", city); + cmd.Parameters.AddWithValue("@value4", category); + cmd.ExecuteNonQuery(); + } + } + } + + static string CleanUrl(string url) + { + // Uri-Objekt erstellen, um die URL zu parsen + Uri uri = new Uri(url); + + // Entfernen von "www." + string host = uri.Host.Replace("www.", ""); + + // Zusammensetzen der bereinigten URL + string cleanedUrl = $"{host}"; + + return cleanedUrl; + } + + private async void ChangeVPN() + { + AppendToOutput("Wechsel des VPN-Servers..."); + + // VPN trennen + ExecuteCommand("net stop nordvpn-service"); + await Task.Delay(30000); // Warte, um sicherzustellen, dass der Dienst vollständig gestoppt wird + + // VPN wieder verbinden + ExecuteCommand("net start nordvpn-service"); + await Task.Delay(30000); // Warte, um sicherzustellen, dass der Dienst vollständig gestartet wird + + AppendToOutput("VPN-Server gewechselt."); + } + + private void ExecuteCommand(string command) + { + var processInfo = new ProcessStartInfo("cmd.exe", "/c " + command) + { + CreateNoWindow = true, + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true + }; + + using (var process = Process.Start(processInfo)) + { + string output = process.StandardOutput.ReadToEnd(); + string error = process.StandardError.ReadToEnd(); + process.WaitForExit(); + + if (!string.IsNullOrEmpty(output)) + { + AppendToOutput("Output: " + output); + } + + if (!string.IsNullOrEmpty(error)) + { + AppendToOutput("Fehler: " + error); + } + + if (process.ExitCode != 0) + { + AppendToOutput("Der Befehl '" + command + "' wurde nicht erfolgreich ausgeführt."); + } + } + } + + private void AppendToOutput(string text) + { + if (InvokeRequired) + { + Invoke(new Action(() => AppendToOutput(text))); + return; + } + + lstResults.Items.Add(text + Environment.NewLine); + } + + private List LoadSearchParamsFromDatabase() + { + var searchParams = new List(); + + using (MySqlConnection conn = new MySqlConnection(connectionString)) + { + conn.Open(); + + // Städte aus der Tabelle Staedte laden + var staedte = new List(); + string queryStaedte = "SELECT staedte FROM staedte"; + using (MySqlCommand cmdStaedte = new MySqlCommand(queryStaedte, conn)) + { + using (MySqlDataReader readerStaedte = cmdStaedte.ExecuteReader()) + { + while (readerStaedte.Read()) + { + staedte.Add(readerStaedte.GetString("staedte")); + } + } + } + + // Rubriken aus der Tabelle Rubriken laden + var rubriken = new List(); + string queryRubriken = "SELECT rubriken FROM rubriken"; + using (MySqlCommand cmdRubriken = new MySqlCommand(queryRubriken, conn)) + { + using (MySqlDataReader readerRubriken = cmdRubriken.ExecuteReader()) + { + while (readerRubriken.Read()) + { + rubriken.Add(readerRubriken.GetString("rubriken")); + } + } + } + + // Kombiniere jede Rubrik mit jeder Stadt und füge sie zur Liste hinzu + foreach (var stadt in staedte) + { + foreach (var rubrik in rubriken) + { + searchParams.Add(new SearchParam + { + Rubrik = rubrik, + Stadt = stadt + }); + } + } + } + + return searchParams; + } + } + + public class SearchParam + { + public string Rubrik { get; set; } + public string Stadt { get; set; } + } +} + + diff --git a/webCrawlerGoogle/webCrawlerGoogle/Form1.resx b/webCrawlerGoogle/webCrawlerGoogle/Form1.resx new file mode 100644 index 0000000..8b2ff64 --- /dev/null +++ b/webCrawlerGoogle/webCrawlerGoogle/Form1.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/webCrawlerGoogle/webCrawlerGoogle/Program.cs b/webCrawlerGoogle/webCrawlerGoogle/Program.cs new file mode 100644 index 0000000..0d279ed --- /dev/null +++ b/webCrawlerGoogle/webCrawlerGoogle/Program.cs @@ -0,0 +1,17 @@ +namespace webCrawlerGoogle +{ + internal static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + // To customize application configuration such as set high DPI settings or default font, + // see https://aka.ms/applicationconfiguration. + ApplicationConfiguration.Initialize(); + Application.Run(new Form1()); + } + } +} \ No newline at end of file diff --git a/webCrawlerGoogle/webCrawlerGoogle/Sicherung.txt b/webCrawlerGoogle/webCrawlerGoogle/Sicherung.txt new file mode 100644 index 0000000..64aa8b0 --- /dev/null +++ b/webCrawlerGoogle/webCrawlerGoogle/Sicherung.txt @@ -0,0 +1,198 @@ +NUGET: + +Install-Package Selenium.WebDriver +Install-Package Selenium.WebDriver.ChromeDriver + + + + private const string ApiKey = "GELÖSCHT"; //"AIzaSyCjdysuuyc2bs4ikqT8xyIpPJHiDZ4CEo4"; // Füge hier deinen API-Schlüssel ein + private string connectionString = "Server=192.168.178.201;Database=domainchecker;User ID=root;Password=1td5rugut8;"; + + public Form1() + { + InitializeComponent(); + } + + private async void btnSearch_Click(object sender, EventArgs e) + { + var searchParams = LoadSearchParamsFromDatabase(); + + foreach (var param in searchParams) + { + string category = param.Rubrik; + string city = param.Stadt; + + string requestUri = $"https://maps.googleapis.com/maps/api/place/textsearch/json?query={category}+in+{city}&key={ApiKey}"; + await FetchResults(requestUri, city, category); + + } + Console.Beep(); + MessageBox.Show("Fertig!"); + } + + + private async Task FetchResults(string requestUri, string stadt, string rubrik) + { + using (HttpClient client = new HttpClient()) + { + bool hasNextPage = true; + + while (hasNextPage) + { + HttpResponseMessage response = await client.GetAsync(requestUri); + if (response.IsSuccessStatusCode) + { + string jsonResult = await response.Content.ReadAsStringAsync(); + JObject result = JObject.Parse(jsonResult); + + foreach (var place in result["results"]) + { + string placeId = (string)place["place_id"]; + string website = await GetPlaceDetails(placeId); + if (!string.IsNullOrEmpty(website)) + { + string cleanedUrl = CleanUrl(website); + lstResults.Items.Add(cleanedUrl); + SaveToDatabase(cleanedUrl, stadt, rubrik); + } + } + + if (result["next_page_token"] != null) + { + string nextPageToken = (string)result["next_page_token"]; + await Task.Delay(2000); // 2 Sekunden warten + requestUri = $"https://maps.googleapis.com/maps/api/place/textsearch/json?pagetoken={nextPageToken}&key={ApiKey}"; + } + else + { + hasNextPage = false; + } + } + else + { + MessageBox.Show("Fehler bei der Anfrage: " + response.StatusCode); + hasNextPage = false; + } + } + } + } + + + private async Task GetPlaceDetails(string placeId) + { + string requestUri = $"https://maps.googleapis.com/maps/api/place/details/json?place_id={placeId}&fields=website&key={ApiKey}"; + + using (HttpClient client = new HttpClient()) + { + HttpResponseMessage response = await client.GetAsync(requestUri); + if (response.IsSuccessStatusCode) + { + string jsonResult = await response.Content.ReadAsStringAsync(); + JObject result = JObject.Parse(jsonResult); + + return (string)result["result"]["website"]; + } + + return null; + } + } + + private void SaveToDatabase(string website, string stadt, string rubrik) + { + using (MySqlConnection conn = new MySqlConnection(connectionString)) + { + conn.Open(); + string queryCheck = "SELECT COUNT(*) FROM webCrawler WHERE webseite = @website"; + using (MySqlCommand cmdCheck = new MySqlCommand(queryCheck, conn)) + { + cmdCheck.Parameters.AddWithValue("@website", website); + int count = Convert.ToInt32(cmdCheck.ExecuteScalar()); + + if (count == 0) + { + string queryInsert = "INSERT INTO webCrawler (webseite, stadt, rubrik) VALUES (@website, @stadt, @rubrik)"; + using (MySqlCommand cmdInsert = new MySqlCommand(queryInsert, conn)) + { + cmdInsert.Parameters.AddWithValue("@website", website); + cmdInsert.Parameters.AddWithValue("@stadt", stadt); + cmdInsert.Parameters.AddWithValue("@rubrik", rubrik); + + cmdInsert.ExecuteNonQuery(); + } + } + } + } + } + public static string CleanUrl(string url) + { + // Entferne das Protokoll (http, https) und 'www.' + Uri uri = new Uri(url); + string host = uri.Host; + + // Prüfen, ob "www." am Anfang des Hosts ist und entfernen + if (host.StartsWith("www.")) + { + host = host.Substring(4); + } + + return host; + } + private List LoadSearchParamsFromDatabase() + { + var searchParams = new List(); + + using (MySqlConnection conn = new MySqlConnection(connectionString)) + { + conn.Open(); + + // Zuerst alle Städte aus der Tabelle Staedte laden + var staedte = new List(); + string queryStaedte = "SELECT staedte FROM staedte"; + using (MySqlCommand cmdStaedte = new MySqlCommand(queryStaedte, conn)) + { + using (MySqlDataReader readerStaedte = cmdStaedte.ExecuteReader()) + { + while (readerStaedte.Read()) + { + staedte.Add(readerStaedte.GetString("staedte")); + } + } + } + + // Dann alle Rubriken aus der Tabelle Rubriken laden + var rubriken = new List(); + string queryRubriken = "SELECT rubriken FROM rubriken"; + using (MySqlCommand cmdRubriken = new MySqlCommand(queryRubriken, conn)) + { + using (MySqlDataReader readerRubriken = cmdRubriken.ExecuteReader()) + { + while (readerRubriken.Read()) + { + rubriken.Add(readerRubriken.GetString("rubriken")); + } + } + } + + // Kombiniere jede Rubrik mit jeder Stadt und füge sie zur Liste hinzu + foreach (var stadt in staedte) + { + foreach (var rubrik in rubriken) + { + searchParams.Add(new SearchParam + { + Rubrik = rubrik, + Stadt = stadt + }); + } + } + } + + return searchParams; + } + } + + public class SearchParam + { + public string Rubrik { get; set; } + public string Stadt { get; set; } + } \ No newline at end of file diff --git a/webCrawlerGoogle/webCrawlerGoogle/app.manifest.xml b/webCrawlerGoogle/webCrawlerGoogle/app.manifest.xml new file mode 100644 index 0000000..bb32719 --- /dev/null +++ b/webCrawlerGoogle/webCrawlerGoogle/app.manifest.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/webCrawlerGoogle/webCrawlerGoogle/webCrawlerGoogle.csproj b/webCrawlerGoogle/webCrawlerGoogle/webCrawlerGoogle.csproj new file mode 100644 index 0000000..8bf19ad --- /dev/null +++ b/webCrawlerGoogle/webCrawlerGoogle/webCrawlerGoogle.csproj @@ -0,0 +1,20 @@ + + + + WinExe + net8.0-windows + enable + true + enable + app.manifest.xml + + + + + + + + + + + \ No newline at end of file