GOOGLE PLACES API v1 • WORDPRESS 5.8+ • PHP 7.4+

GM Lead Scraper

Inne scrapery dają Ci listę adresów. Ten mówi, które trafią do właściciela.
Oficjalne Places API, 7 źródeł na firmę, walidacja MX, deduplikacja i scoring — zero telemetrii, wszystko w Twojej bazie.

7źródeł / firmę
60firm / zapytanie
40filtrów śmieci
66domen freemail
10statusów jakości
Różnica

Dlaczego to nie jest zwykły scraper

Zwykły scraper bierze stronę główną, wyciąga regexem i wypluwa 30% śmieci. GM Lead Scraper jest zbudowany odwrotnie – od sita, nie od łyżki.

Zwykły scraperGM Lead Scraper
1 źródło: strona główna7 źródeł / firmę: home + /kontakt, /contact, /o-nas, /impressum, /cennik, /menu + kaskada przerywana gdy znajdzie adres w domenie. Mniej requestów, więcej trafień.
Ginie na fanpage’uModuł Facebooka: skanuje linki wychodzące z fanpage’a, pomija 14 domen (facebook, instagram, youtube, tiktok, linkedin…), bierze pierwszy prawdziwy link jako domenę firmy i przestawia podstrony.
/[a-z@.]+/ i koniecDeobfuskacja PRO: podwójne dekodowanie encji HTML (biuro@), 9 wzorców [at], (at), {at}, [małpa], (małpa), [dot], (dot), [kropka], (kropka) z tolerancją spacji, 3 metody: treść + data-email/data-mail + mailto:, obcinanie .,;:()"'
Wypluwa noreply@, *.png, example.com40 filtrów śmieci + 11 rozszerzeń + HEX ID: systemowe (noreply, postmaster, abuse), techniczne WP, przykładowe (example.com, twojadomena), narzędzia (sentry, shopify, cloudflare) + odrzut *.png, *.jpg, *.css, *.js, *.woff2 + ID szesnastkowe >16 znaków. Zanim sprawdzi DNS.
Wysyła na nieistniejące skrzynkiWalidacja DNS MX → A → AAAA + cache 12h: 3 stany (ma pocztę / ma tylko stronę / nie odpowiada), fallback gethostbyname, cache pod hashem domeny. Nie zgaduje.
Jedna lista, wszystko do wysyłkiScoring 100/80/70/40/20/10 + 66 freemail + 31 ról + literówki z bezpiecznikiem: ok_self (100) = domena firmy + MX, typo_fixed (80) tylko gdy oryginał bez MX i poprawiony ma MX, ok (70), freemail (40) – 66 domen PL/INT/DE/FR/IT/CZ/NL/BE/RU, nomx (20), invalid (10). Przy remisie wygrywa ROLA (biuro, kontakt, info, sekretariat…). Reszta w polu pomocniczym.
Duplikaty: Jan Kowalski i Jan KOWALSKI = 2 firmyDeduplikacja twarda: telefon sprowadzony do cyfr (różne formaty = 1 numer) + domena lower bez www, wyłączalne switchem. Lista wykluczeń (numery i domeny) sprawdzana 2x – przy zbieraniu i przy eksporcie, normalizacja przy dodawaniu, przeżywa czyszczenie bazy.
Eksport CSV z ID, bez polskich znaków4 eksporty respektujące filtry: CSV z telefonami, CSV z adresami (tylko wysyłalne), Tylko własna domena (ok_self + typo_fixed), Thunderbird (split local/domain). UTF-8 + BOM (Excel PL), średnik, 12 kolumn, nazwa pliku typ+data, prepared statements nawet przy 5000 wykluczeń.
Dane idą przez serwer sprzedawcy, limit fraz, brak testówZero telemetrii, 100% offline, 1748 linii PHP, 72 testy: własny klucz Google, darmowy limit + licznik + dzienny limit, 14 endpointów AJAX nonce + cap admin, $wpdb->prepare, createElement nie innerHTML, 30s abort, wykrywanie timeout PHP / 403 / fatal error. Licencja lokalna.
Test: 95 firm Warszawa38 adresów znalezionych, 24 to ok_self w domenie firmy = 63% trafia do właściciela, nie do pośrednika. Reszta scraperów ma tu 15-20%.
Dla kogo?Dla agencji i handlowców którzy wiedzą że lead to nie rekord w CSV tylko skrzynka która odpowiada. Bez owijania.
EfektMniej wysyłek, więcej odpowiedzi. Bo nie wysyłasz na noreply@ i martwe domeny.
01 Fundament

Instalacja i baza danych

Zero zależności. Czysty JS, style WP. Dwie tabele, zero śmieci w options. Dane zostają u Ciebie.

2 tabele • 18 kolumn • 6 indeksów

  • firmy: id, place_id, nazwa, email, wszystkie_emails, status, is_role, strona, domena, adres, telefon, telefon_norm, kategoria, miasto, query, ocena, opinie, data
  • wykluczenia: unique para typ + wartość + powód + data
  • Indeksy: unique place_id + status, miasto, kategoria, telefon_norm, domena
  • dbDelta z wersjonowaniem — aktualizacje dokładają kolumny bez utraty danych

Dlaczego to wyjątkowe?

  • Check schematu tylko przy zmianie wersji, nie przy każdym wejściu
  • uninstall.php czyści opcje i cache DNS, ale ZOSTAWIA firmy — kasowanie wymaga odkomentowania 2 linii
  • Daty wg strefy WP, nie serwera — licznik API zeruje się o północy WP
Safe by design
02 Sourcing

Zbieranie firm z Google

Oficjalne Places API v1 — places:searchText. Nie scrap HTML. Frazy x obszary = iloczyn. Jednym przebiegiem całe miasto.

Iloczyn zapytańFrazy i obszary — 1/linia. Kalkulator live: zapytania / firmy / wywołania API aktualizowany w trakcie pisania.
3 strony / 60 firmpageToken x3. Max 60 wyników / zapytanie. Trik: dziel na dzielnice by wyciągnąć więcej z miasta.
Maska pól warunkowaOceny i opinie doklejane tylko przy włączonym switchu — niższy próg rozliczeniowy Google.
  • Filtry wstępne: min/max opinii i oceny — auto-off gdy oceny OFF + info w UI
  • Etykiety miasta/kategorii + query źródłowe do eksportu
  • Check place_id — nigdy 2x. Liczniki: duplikaty / wykluczenia / filtry
  • Firmy bez strony też do bazy (BRAK) — zostaje telefon
  • Timeout 20s na request Google
Pro tip: Działa na Twoim własnym kluczu Google — korzystasz z darmowego limitu Google. Wtyczka liczy zużycie API i pozwala ustawić dzienny limit. Bez pośredników, bez limitu fraz w wtyczce.
03 Extraction

Silnik wyszukiwania adresów

7 źródeł na firmę. Kaskada przerywa się gdy znajdzie adres w domenie firmy — na łatwych nie pobiera podstron w ogóle.

7 źródeł

  1. Strona główna
  2. /kontakt, /contact, /o-nas, /impressum, /cennik, /menu
  • Timeout 8s / stronę, max 3 redirecty, header GM-Lead-Scraper/vX
  • HTTP 400+ pomijane, <400 bajtów = pusta (odsiew zaślepek hostingu)
  • Max 5 unikalnych / firmę, deduplikacja w obrębie strony

Deobfuskacja i parsing

  • Podwójne dekodowanie encji HTML: biuro@firma.pl → działa
  • 9 wzorców: [at] (at) {at} [małpa] (małpa) [dot] (dot) [kropka] (kropka) — spacje i case tolerowane
  • 3 metody: regex w treści + data-email/data-mail + mailto:
  • Obcinanie .,;:()”’ z końca, lowercasing, walidacja składni
04 Edge case

Moduł Facebooka

Gdy Google zwraca fanpage — sam odnajduje prawdziwą domenę firmy.

1. Skanuje wszystkie linki wychodzące z fanpage’a
2. Pomija 14 domen: facebook, instagram, fb.com, fbcdn, whatsapp, messenger, youtube, twitter, x, tiktok, google, apple, linkedin, pinterest
3. Pierwszy link poza listą = prawdziwa strona → pobiera i dokłada do materiału
4. Jeśli domena nieznana — ustala ją i przestawia bazę dla 6 podstron (nie sprawdza /kontakt na facebook.com)

05 Higiena

Odsiew śmieci

40 wzorców blacklist

  • Systemowe: noreply, no-reply, donotreply, nie-odpowiadaj, postmaster, abuse, hostmaster, mailer-daemon
  • Techniczne WP + przykładowe: example.com, domain.com, yourdomain, twojadomena, adres@, nazwa@, imie@, test@test, admin@admin
  • Domeny narzędzi w kodzie: sentry, wixpress, shopify, squarespace, godaddy, cloudflare, gravatar, jquery, bootstrapcdn, schema.org

Fałszywe maile

  • 11 rozszerzeń: png, jpg, jpeg, gif, svg, webp, css, js, woff, woff2, ico
  • HEX ID: część nazwy >16 znaków tylko [0-9a-f] = odrzut
noreply@example.com*.pnghex >16
06 Deliverability

Walidacja DNS

MX → A → AAAANajpierw MX, brak → A, brak → AAAA. Fallback gethostbyname gdy hosting blokuje checkdnsrr.
3 stanyma pocztę / ma tylko stronę / nie odpowiada. Cache 12h pod hashem domeny — nie pyta 2x.
CacheCzyszczony przy uninstall. W przebiegu oszczędza dziesiątki zapytań.
07 Klasyfikacja

Statusy i ranking

10 stanów. Ranking punktowy wybiera najlepszy z 5. Reszta w polu pomocniczym jako adres + status.

StatusZnaczeniePunkty
ok_selfAdres w tej samej domenie co firma, MX potwierdzony100
typo_fixedPoprawiona literówka z MX80
okInna domena firmowa, nie freemail70
freemailGmail, WP, O2, Onet itd.40
nomxDomena ma stronę, brak poczty20
invalidDomena nie istnieje10
found / to_process / bounced / no_emailfound = bez walidacji, bounced = ręcznie po odbiciu

Przy remisie wygrywa adres roli — bo to skrzynka faktycznie czytana.

08 Segmentacja

Freemail — 66 domen

Oddziela pośredników od właścicieli. Kluczowe dla eksportu „Tylko własna domena”.

wp.plo2.plonet.plop.plinteria.plgazeta.plgmail.comyahoo.*outlook.*hotmail.*icloud.comaol.comproton.metutanotazoho.comgmx.de/.comweb.det-online.deorange.frlibero.itseznam.czziggo.nlmail.ruyandex.ru

PL, INT, DE, FR, IT, CZ, NL, BE, RU — pełna lista w kodzie.

09 Rola

Adresy roli — 31 nazw

biurokontaktinfosekretariatrecepcjarezerwacjezamowieniasklepsprzedazhandlowybokkancelariaofficecontactsaleshellosupportadminreservationsanfragevertrieb

Dopasowanie dokładne lub z myślnikiem/kropką: biuro.gdynia@ i sales-eu@ też łapie. Flaga niezależna od statusu, nie obniża oceny. Etykieta ROLA w tabeli i eksporcie.

10 Korekta

Poprawianie literówek — 37 wpisów + 6 reguł

Mapa

  • Gmail: gamil, gmial, gmai, gmil, gmaill, gmail.con/.cm/.co/.pl
  • WP: wp.ol, wp.p, wp.pll, wp.lp + O2, Onet, Interia, Gazeta…
  • Reguły: .con→.com, .comm/.cim/.ocm→.com, .pl.pl→.pl, .ol→.pl

Bezpiecznik

Korekta tylko gdy oryginał nie ma MX i poprawiona ma MX. Bez tego nie zgaduje.

11 Unikalność

Deduplikacja i wykluczenia

  • Po telefon_norm (same cyfry) — różne formaty = jeden numer. Po domenie: lower + bez www. Wyłączalne jednym switchem.
  • Lista wykluczeń: numery i domeny, sprawdzana przy zbieraniu i eksporcie
  • Dodawanie pojedyncze + import masowy z auto-rozpoznaniem numer vs domena
  • Normalizacja przy dodawaniu, odporność na duplikaty, widok do 5000 z kasowaniem
  • Wykluczenia przeżywają czyszczenie bazy firm
12 Engine

Przebieg pracy

2 fazy: zbieranie firm → wyszukiwanie adresów. 1 zapytanie Google / wywołanie = 1 firma / wywołanie. Nigdy nie przekroczy limitu PHP na shared.
Stan po każdym kroku: przerwany przebieg wznawia się od miejsca stopu. Pasek: do 50% faza 1, powyżej faza 2.
4 liczniki livefaza, zapytania wykonane/wszystkie, liczba firm, zużycie API z limitem
Dziennik 6 kolorówwłasna domena zielono, inna jaśniej, freemail pomarańcz, brak szaro, błąd czerwono, info niebiesko + timestamp
Bezpieczne stopStop kończy po bieżącym kroku bez utraty danych. Start blokowany. 4 switche: głębokie, DNS, deduplikacja, wykluczenia.
13 Baza

Praca z wynikami

  • Filtr miasto i kategoria — listy z bazy, nie z configu. Filtr status (9 wartości) + min/max opinii
  • Wyszukiwanie live debounce 400ms po: nazwie, telefonie, domenie, emailu
  • 50/100/200 wierszy, sortowanie po opinii malejąco — największe na górze
  • 9 liczników nad tabelą z paskiem koloru: łącznie, z telefonem, z adresem, własna domena, inna domena, freemail, bez poczty, do przetworzenia — respektują filtry
  • ROLA etykieta, link do strony nowa karta + noopener, BOUNCE (oznacza i dodaje domenę do wykluczeń 1 klikiem) + usuń z confirmem
14 Export

Eksport

4 przyciski, każdy respektuje filtry i wykluczenia. Bez reloadu.

Zakresy

  • CSV z telefonami: wszystkie z numerem
  • CSV z adresami: ok_self, ok, typo_fixed, freemail, found
  • Tylko własna domena: ok_self + typo_fixed — najwęższa, najpewniejsza
  • Thunderbird: jak wyżej + split local/domain do książki

Format

  • UTF-8 + BOM — polskie znaki w Excelu
  • Separator średnik, 12 kolumn: nazwa, telefon, adres, status, rola, strona, domena, miasto, kategoria, query, opinie, ocena
  • Nazwa pliku: typ + data. Wykluczenia przez prepared statements
15 Maintenance

Narzędzia

  • Przeliczenie statusów wg obecnych reguł, partie 20, z progresem, zero zapytań Google. Odbudowuje kandydatów — może wybrać lepszy niż poprzednio
  • Naprawa danych: uzupełnia brakujące domeny i telefon_norm + mapowanie statusów ze starszych wersji
  • Zerowanie licznika API + czyszczenie bazy firm z zachowaniem wykluczeń + confirm + warning nieodwracalności
16 API Key

Klucz Google i błędy

Konfiguracja

  • Pole password + podgląd + placeholder początku klucza
  • 4 linki prosto do Google Cloud: projekt, włączenie Places API, limit, klucz — ponumerowane
  • Walidacja formatu przed requestem — literówka nie zjada limitu
  • Test połączenia zwraca liczbę wyników

6 tłumaczonych błędów Google

  • Usługa niewłączona / brak płatności / klucz ograniczony / nieprawidłowy / limit / brak uprawnień
  • + składnia zapytania i awaria Google
  • Każdy z przyciskiem gdzie naprawić + podpowiedzią
  • Oryginalna odpowiedź Google zawsze po rozwinięciu
  • Dzienny limit w panelu, zerowany o północy WP
17 Licencja

100% offline

  • Sprawdzanie lokalne, zero połączeń poza Google
  • Data RRRR-MM-DD lub bez limitu / unlimited / puste = bez limitu
  • Ważna do końca ostatniego dnia, licznik dni po datach (nie sekundach)
  • Przypomnienie 30 dni przed + notice WP, osobny komunikat w dniu wygaśnięcia

Co po wygaśnięciu?

  • Blokowany tylko Start — napis wprost na przycisku
  • Baza, filtry, wyszukiwanie, narzędzia, 4 eksporty — działają
  • 4 odznaki: zielona bez limitu, zielona z datą, pomarańczowa dni, czerwona po terminie
  • Zakładka licencji mówi wprost: brak telemetrii, brak wysyłki info
18 Hardening

Bezpieczeństwo

  • 14 endpointów AJAX — każdy nonce + cap admin. Panel osobno cap i die()
  • Formularz ustawień osobny nonce, wszystkie zapytania przez $wpdb->prepare
  • Input sanitized, output escaped, tabela przez createElement nie innerHTML, href jako property
  • Brak obniżania weryfikacji certyfikatu + komunikat jak naprawić
  • Klucz API nigdy nie wypisywany jawnie w DOM
19 UX

Odporność interfejsu

  • Żadne zapytanie nie wisi — po 30s abort z komunikatem
  • Wykrywanie pustej odpowiedzi (timeout PHP), nie-JSON z kodem HTTP, 403 jako możliwa blokada przez security plugin, fatal error PHP
  • Surowa odpowiedź po rozwinięciu, obcięta do rozsądnej długości
  • Przyciski blokowane na czas requestu, błędy nigdy jako [object Object]
20 Stack

Zgodność i wymagania

WP 5.8+ • PHP 7.4+Zalecane 8.2, ext: cURL, mbstring, json. Limit exec >=120s. RWD, style WP.
Vanilla JSBez jQuery. 1748 linii PHP, 72 testy w 3 zestawach. Dane tylko w bazie klienta.
Brak telemetriiNie wysyła nic poza Google. Licencja offline. Plik Twój, działa offline.
Test 95 firm z Warszawy: 24 z 38 adresów to skrzynki w domenie firmy — 63% trafia do właściciela, nie pośrednika.