Selaa lähdekoodia

[trails] Add alltrails and gaiagps ids to model

Colin Powell 2 kuukautta sitten
vanhempi
commit
da8d26fcd9

+ 23 - 0
vrobbler/apps/trails/migrations/0005_trail_alltrails_id_trail_gaiagps_id.py

@@ -0,0 +1,23 @@
+# Generated by Django 4.2.19 on 2025-06-16 14:20
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("trails", "0004_alter_trail_run_time_seconds"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="trail",
+            name="alltrails_id",
+            field=models.CharField(blank=True, max_length=255, null=True),
+        ),
+        migrations.AddField(
+            model_name="trail",
+            name="gaiagps_id",
+            field=models.CharField(blank=True, max_length=255, null=True),
+        ),
+    ]

+ 9 - 5
vrobbler/apps/trails/models.py

@@ -9,9 +9,7 @@ from locations.models import GeoLocation
 BNULL = {"blank": True, "null": True}
 
 
-
 class Trail(ScrobblableMixin):
-
     class PrincipalType(models.TextChoices):
         WOODS = "WOODS"
         ROAD = "ROAD"
@@ -19,7 +17,7 @@ class Trail(ScrobblableMixin):
         MOUNTAIN = "MOUNTAIN"
 
     class ActivityType(models.TextChoices):
-        WALK= "WALK"
+        WALK = "WALK"
         HIKE = "HIKE"
         RUN = "RUN"
         BIKE = "BIKE"
@@ -39,8 +37,14 @@ class Trail(ScrobblableMixin):
     )
     strava_id = models.CharField(max_length=255, **BNULL)
     trailforks_id = models.CharField(max_length=255, **BNULL)
-    principal_type = models.CharField(max_length=10, choices=PrincipalType.choices, **BNULL)
-    default_activity_type = models.CharField(max_length=10, choices=ActivityType.choices, **BNULL)
+    alltrails_id = models.CharField(max_length=255, **BNULL)
+    gaiagps_id = models.CharField(max_length=255, **BNULL)
+    principal_type = models.CharField(
+        max_length=10, choices=PrincipalType.choices, **BNULL
+    )
+    default_activity_type = models.CharField(
+        max_length=10, choices=ActivityType.choices, **BNULL
+    )
 
     def get_absolute_url(self):
         return reverse("trails:trail_detail", kwargs={"slug": self.uuid})

+ 61 - 0
vrobbler/apps/trails/sources/gaiagps.py

@@ -0,0 +1,61 @@
+from typing import Optional
+import requests
+from bs4 import BeautifulSoup
+
+
+def get_description_from_soup(soup) -> Optional[int]:
+    rating = None
+    try:
+        potential_desc = soup.find("div", id_="descriptionContainer")
+        potential_rating = soup.find("div", class_="allmusic-rating")
+        if potential_rating:
+            rating = int(strip_and_clean(potential_rating.get_text()))
+    except ValueError:
+        pass
+    return rating
+
+
+def scrape_gaia_trail(url):
+    headers = {"User-Agent": "Mozilla/5.0"}
+    r = requests.get(url, headers=headers)
+    r.raise_for_status()
+    soup = BeautifulSoup(r.text, "html.parser")
+
+    # Title
+    title = soup.select_one("h1").get_text(strip=True)
+
+    # Stats are inside divs with classes like "flex" and label-value pairs
+    stats = {}
+    stat_blocks = soup.select("div.flex.flex-col.items-start.text-sm span")
+    for i in range(0, len(stat_blocks) - 1, 2):
+        label = stat_blocks[i].get_text(strip=True)
+        value = stat_blocks[i + 1].get_text(strip=True)
+        stats[label] = value
+
+    # Description (under 'Overview' header)
+    overview_heading = soup.find(
+        lambda tag: tag.name == "h2" and "Overview" in tag.text
+    )
+    if overview_heading:
+        desc_parts = []
+        for sib in overview_heading.next_siblings:
+            if sib.name and sib.name.startswith("h"):
+                break
+            if sib.name == "p":
+                desc_parts.append(sib.get_text(strip=True))
+        description = "\n\n".join(desc_parts).strip()
+    else:
+        description = None
+
+    return {
+        "url": url,
+        "title": title,
+        "stats": stats,
+        "description": description,
+    }
+
+
+# Example usage
+url = "https://www.gaiagps.com/hike/318136/"
+trail_data = scrape_gaia_trail(url)
+print(trail_data)