Anwendungsfälle

Nachrichten- und Medienaggregation mit CAPTCHA-Verwaltung

Der Engpass bei der Nachrichtenaggregation ist selten ein einzelnes CAPTCHA – es ist die Vielzahl der Quellen. Sobald Sie dutzende Newswires, Regionalzeitungen und Presseportale parallel abfragen, treffen Sie auf reCAPTCHA v2, reCAPTCHA v3 und Cloudflare Turnstile in bunter Mischung, jede mit eigener Auslöselogik. CaptchaAI löst diese Abfragen über eine einheitliche API, sodass Ihr Aggregator nicht für jede Quelle einen Sonderfall pflegen muss.

Dieser Leitfaden zeigt, welche CAPTCHA-Typen auf Nachrichtenplattformen auftreten, wie schnell Sie pro Quelle sammeln dürfen und wie ein Python-Aggregator mit automatischer CAPTCHA-Lösung aussieht – inklusive Keyword-Monitoring für die Medienbeobachtung.

Welche CAPTCHAs auf Nachrichtenseiten auftreten

Der CAPTCHA-Typ verrät oft, welche Schutzstrategie eine Quelle fährt – und wie vorsichtig Sie abfragen sollten.

Quelltyp CAPTCHA Auslöser Inhalt
Große Nachrichtenagenturen Cloudflare Turnstile Bot-Erkennung Artikel, Schlagzeilen
Newswires (AP, Reuters) reCAPTCHA v2 Massenzugriffe Aktuelle Meldungen
Bezahlinhalte hinter Paywall reCAPTCHA v3 Zugriffsscoring Premium-Artikel
Lokale und regionale Portale reCAPTCHA v2 Rate-Limiting Regionale Nachrichten
Nachrichtenaggregatoren Cloudflare Challenge Scraping-Erkennung Gebündelte Feeds
Presseportale Bild-CAPTCHA Download-Seiten PR-Material

Sammelkadenz pro Quelle richtig wählen

Der entscheidende operative Unterschied liegt meist nicht im CAPTCHA-Typ, sondern in der Sammelstrategie pro Quelle. Breaking-News-Feeds, lokale Nachrichtenseiten und Presseportale vertragen selten dieselbe Abrufkadenz oder denselben Session-Rhythmus.

Quelltyp Empfohlene Kadenz Begründung
Große Newswires und schnelle Feeds Häufig, aber gedrosselt Inhalte ändern sich laufend, reagieren aber empfindlich auf aggressive Muster
Lokale und regionale Portale Moderat Seltenere Updates, oft schwächere Infrastruktur
Pressemitteilungen und statische Archive Langsamer Batch Änderungen sind selten; unnötige Last provoziert nur zusätzliche Schutzmechanismen
Paywall- und Premium-Inhalte Sehr vorsichtig, sitzungsstabil Reibung entsteht aus Session- und Zugriffsmustern, nicht nur aus dem CAPTCHA

Ein typisches Szenario: Eine PR-Agentur in Berlin verfolgt die Berichterstattung über einen Kunden über überregionale Newswires, ein Dutzend Regionalzeitungen und mehrere Fachportale hinweg. Die großen Feeds prüft sie im Minutentakt, die Regionalseiten stündlich, die Archive einmal täglich – so bleibt die Last je Quelle unauffällig, und dieselbe Aggregator-Instanz deckt alle Kadenzen ab.

Nachrichtenaggregator in Python

Der folgende Aggregator kapselt Session-Handling, CAPTCHA-Erkennung und automatische Lösung in einer Klasse. Erkennt _has_captcha eine Abfrage im HTML, extrahiert _solve_and_retry den Sitekey, schickt ihn an CaptchaAI und sendet das Token zurück an die Quelle – cf-turnstile-response für Turnstile, g-recaptcha-response für reCAPTCHA.

import requests
import time
import re
from bs4 import BeautifulSoup
from datetime import datetime
import json

CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"


def solve_captcha(method, sitekey, pageurl, **kwargs):
    data = {
        "key": CAPTCHAAI_KEY, "method": method,
        "googlekey": sitekey, "pageurl": pageurl, "json": 1,
    }
    data.update(kwargs)
    resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data=data)
    task_id = resp.json()["request"]
    for _ in range(60):
        time.sleep(5)
        result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
            "key": CAPTCHAAI_KEY, "action": "get",
            "id": task_id, "json": 1,
        })
        r = result.json()
        if r["request"] != "CAPCHA_NOT_READY":
            return r["request"]
    raise TimeoutError("Timeout")


class NewsAggregator:
    def __init__(self, proxy=None):
        self.session = requests.Session()
        if proxy:
            self.session.proxies = {"http": proxy, "https": proxy}
        self.session.headers.update({
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36",
            "Accept-Language": "en-US,en;q=0.9",
        })

    def collect_headlines(self, source_url, section=None):
        """Collect headlines from a news source."""
        url = f"{source_url}/{section}" if section else source_url
        resp = self.session.get(url, timeout=30)

        if self._has_captcha(resp.text):
            resp = self._solve_and_retry(resp.text, url)

        soup = BeautifulSoup(resp.text, "html.parser")
        articles = []

        for item in soup.select("article, .story, .headline-item, h2 a, h3 a"):
            link = item if item.name == "a" else item.select_one("a")
            if link:
                articles.append({
                    "title": link.get_text(strip=True),
                    "url": self._abs_url(source_url, link.get("href", "")),
                    "source": source_url,
                    "collected_at": datetime.now().isoformat(),
                })

        return articles

    def get_article(self, article_url):
        """Fetch full article content."""
        resp = self.session.get(article_url, timeout=30)

        if self._has_captcha(resp.text):
            resp = self._solve_and_retry(resp.text, article_url)

        soup = BeautifulSoup(resp.text, "html.parser")

        # Remove unwanted elements
        for tag in soup.select("script, style, nav, footer, .ad, .sidebar"):
            tag.decompose()

        content_el = soup.select_one(
            "article, .article-body, .story-body, .entry-content"
        )

        return {
            "url": article_url,
            "title": self._text(soup, "h1, .article-title"),
            "author": self._text(soup, ".author, .byline, [rel='author']"),
            "date": self._text(soup, "time, .publish-date, .article-date"),
            "content": content_el.get_text(separator="\n", strip=True) if content_el else "",
            "word_count": len(content_el.get_text().split()) if content_el else 0,
        }

    def aggregate_sources(self, sources, max_articles_per=20):
        """Aggregate headlines across multiple sources."""
        all_articles = []

        for source in sources:
            try:
                articles = self.collect_headlines(source["url"], source.get("section"))
                all_articles.extend(articles[:max_articles_per])
                print(f"{source['name']}: {len(articles)} headlines")
            except Exception as e:
                print(f"{source['name']}: Error - {e}")
            time.sleep(3)

        return all_articles

    def _has_captcha(self, html):
        return any(tag in html.lower() for tag in [
            'data-sitekey', 'g-recaptcha', 'cf-turnstile',
        ])

    def _solve_and_retry(self, html, url):
        match = re.search(r'data-sitekey="([^"]+)"', html)
        if not match:
            return self.session.get(url)
        sitekey = match.group(1)
        if 'cf-turnstile' in html:
            token = solve_captcha("turnstile", sitekey, url)
            return self.session.post(url, data={"cf-turnstile-response": token})
        token = solve_captcha("userrecaptcha", sitekey, url)
        return self.session.post(url, data={"g-recaptcha-response": token})

    def _text(self, soup, selector):
        el = soup.select_one(selector)
        return el.get_text(strip=True) if el else ""

    def _abs_url(self, base, href):
        if href.startswith("http"):
            return href
        return base.rstrip("/") + "/" + href.lstrip("/")


# Usage
aggregator = NewsAggregator(
    proxy="http://user:pass@residential.proxy.com:5000"
)

sources = [
    {"name": "Tech News A", "url": "https://technews-a.example.com", "section": "latest"},
    {"name": "Business B", "url": "https://business-b.example.com", "section": "tech"},
    {"name": "Industry C", "url": "https://industry-c.example.com"},
]

headlines = aggregator.aggregate_sources(sources)
print(f"Total: {len(headlines)} headlines collected")

Keyword-Monitoring für die Medienbeobachtung

Für die laufende Medienbeobachtung setzt der NewsMonitor auf dem Aggregator auf: Er filtert Schlagzeilen nach Ihren Suchbegriffen, überspringt bereits gesehene URLs und kann in einem festen Intervall dauerhaft laufen – ideal, um Marken- oder Themennennungen über viele Quellen hinweg zu verfolgen.

class NewsMonitor:
    def __init__(self, keywords, sources, proxy=None):
        self.keywords = [kw.lower() for kw in keywords]
        self.aggregator = NewsAggregator(proxy=proxy)
        self.sources = sources
        self.seen_urls = set()

    def scan(self):
        """Scan for articles matching keywords."""
        headlines = self.aggregator.aggregate_sources(self.sources)
        matches = []

        for article in headlines:
            if article["url"] in self.seen_urls:
                continue

            title_lower = article["title"].lower()
            matched_kws = [kw for kw in self.keywords if kw in title_lower]

            if matched_kws:
                article["matched_keywords"] = matched_kws
                matches.append(article)
                self.seen_urls.add(article["url"])

        return matches

    def continuous_monitor(self, interval_min=30):
        """Run continuous monitoring with alerts."""
        while True:
            matches = self.scan()
            if matches:
                print(f"\n=== {len(matches)} new matches found ===")
                for m in matches:
                    print(f"  [{', '.join(m['matched_keywords'])}] {m['title']}")
                    print(f"    {m['url']}")
            else:
                print(f"No new matches at {datetime.now().strftime('%H:%M')}")

            time.sleep(interval_min * 60)


# Monitor for specific topics
monitor = NewsMonitor(
    keywords=["captcha", "bot detection", "web scraping", "automation"],
    sources=sources,
    proxy="http://user:pass@residential.proxy.com:5000",
)
matches = monitor.scan()

Parallel sammeln: Threads statt Einzellösungen

Medienbeobachtung ist von Natur aus parallel – Sie überwachen viele Quellen gleichzeitig, nicht eine nach der anderen. CaptchaAI rechnet deshalb pro gleichzeitigem Thread ab, nicht pro gelöstem CAPTCHA. Ein Thread ist eine laufende Abfrage; sobald sie fertig ist, nimmt derselbe Thread die nächste auf. Innerhalb eines Tarifs gibt es keine Tageslimits und keine Aufpreise nach CAPTCHA-Typ.

Für den Einstieg reicht BASIC (15 $/Monat, 5 Threads), um mehrere Quellen gleichzeitig abzufragen. Wer dutzende Feeds im Minutentakt scannt, fährt mit STANDARD (30 $/Monat, 15 Threads) oder ADVANCE (90 $/Monat, 50 Threads) ruhiger. Die Preise verstehen sich in US-Dollar.

Fehlerbehebung

Problem Ursache Lösung
Cloudflare blockiert alle Anfragen Aggressive Bot-Erkennung Residential-Proxy + realistischen User-Agent verwenden
Paywall statt Artikel Inhalt hinter Abo Paywall erkennen, überspringen oder markieren
CAPTCHA auf jeder Seite IP markiert Proxy rotieren, Verzögerungen über 5 Sekunden einbauen
Artikelinhalt bleibt leer JS-gerenderter Inhalt Für SPA-Seiten Selenium/Puppeteer nutzen
Doppelte Artikel Gleiche Meldung aus mehreren Quellen Nach Titelähnlichkeit deduplizieren

Rechtliches und DSGVO im DACH-Raum

Im deutschsprachigen Raum lohnt ein zweiter Blick auf die Rechtslage, bevor ein Monitor produktiv läuft:

  • IP-Adressen gelten nach DSGVO als personenbezogene Daten. Wenn Ihre Pipeline Nutzerdaten, Kommentare oder Autorenprofile mitschneidet, prüfen Sie Rechtsgrundlage und Löschfristen.
  • Schlagzeilen, Metadaten und kurze Snippets für Recherche oder Monitoring zu sammeln, ist gängige Praxis. Vollständige, urheberrechtlich geschützte Artikel ohne Erlaubnis zu reproduzieren, ist es nicht – arbeiten Sie mit Ausschnitten und verlinken Sie die Originalquelle.
  • Respektieren Sie robots.txt und die Nutzungsbedingungen der jeweiligen Seite. Greifen Sie nur auf Inhalte zu, die Sie einsehen dürfen.
  • Wer Vergleichswerte veröffentlicht, sollte sie nach § 6 UWG sachlich und nachprüfbar halten.

CaptchaAI löst dabei ausschließlich die CAPTCHA-Abfrage – die Auswahl der Quellen und die Rechtmäßigkeit des Zugriffs bleiben in Ihrer Verantwortung.

Häufige Fragen

Wie viele Quellen kann ich gleichzeitig überwachen?

So viele, wie Ihre Threads erlauben. Jede gleichzeitige Abfrage belegt einen Thread; BASIC (15 $/Monat) bietet 5, STANDARD (30 $/Monat) 15. Zwischen den Abrufen liegen ohnehin Verzögerungen, sodass schon wenige Threads viele Quellen abdecken.

Welcher CAPTCHA-Typ tritt auf Nachrichtenseiten am häufigsten auf?

Cloudflare Turnstile und reCAPTCHA v2. Große Agenturen setzen meist auf Cloudflare, Paywall-Seiten oft auf reCAPTCHA v3 mit Zugriffsscoring. CaptchaAI löst alle drei über dieselbe API.

Ist das Aggregieren von Nachrichten in Deutschland zulässig?

Das Sammeln von Schlagzeilen und Metadaten für Recherche oder Monitoring ist üblich. Ganze Artikel ohne Genehmigung zu übernehmen, verletzt jedoch das Urheberrecht – nutzen Sie Snippets und verlinken Sie die Quelle. Beachten Sie zusätzlich DSGVO und die Nutzungsbedingungen der Seite.

Wie oft sollte der Monitor laufen, ohne blockiert zu werden?

Richten Sie das Intervall nach dem Quelltyp: schnelle Newswires im Minutentakt, Regionalseiten stündlich, Archive täglich. Bei häufigen CAPTCHAs helfen rotierende Proxys und Verzögerungen über 5 Sekunden.

Welcher Proxy-Typ eignet sich für Nachrichtenseiten am besten?

Rotierende Residential-Proxys. Große Nachrichtenagenturen nutzen Cloudflare, das Rechenzentrums-IPs aggressiv blockiert.


Verwandte Leitfäden


Nachrichten aus beliebigen Quellen automatisiert zusammenführen – Holen Sie sich Ihren CaptchaAI-Schlüssel und starten Sie das Monitoring.

Kommentare sind für diesen Artikel deaktiviert.