-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcli.py
More file actions
99 lines (86 loc) · 3.84 KB
/
cli.py
File metadata and controls
99 lines (86 loc) · 3.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#!/usr/bin/env python3
import argparse
import csv
import json
import os
import sys
from dotenv import load_dotenv
load_dotenv(os.path.join(os.path.dirname(os.path.abspath(__file__)), ".env"))
from maps_scraper import scrape, no_website
from maps_scraper.core import configure_logging
def main():
parser = argparse.ArgumentParser(description="Google Maps Business Scraper")
parser.add_argument("--type", help="Business type (e.g. restaurant)")
parser.add_argument("--types", help="Comma-separated business types")
parser.add_argument("--location", required=True, help="Location to search")
parser.add_argument("--limit", type=int, default=100, help="Max results")
parser.add_argument("--radius-km", type=float, help="Radius for area sweep (no-type mode)")
parser.add_argument("--no-website", action="store_true", dest="no_website", help="Leads: businesses with no website")
parser.add_argument("--min-rating", type=float, help="Min rating filter (for --no-website)")
parser.add_argument("--export", choices=["csv", "json"], help="Export format")
parser.add_argument("--output", help="Output file path")
parser.add_argument("--verbose", "-v", action="store_true", help="Print live progress + full details per result")
args = parser.parse_args()
configure_logging(verbose=args.verbose)
if args.no_website:
results = no_website(
location=args.location,
type=args.type,
limit=args.limit,
min_rating=args.min_rating,
verbose=args.verbose,
)
else:
types_list = [t.strip() for t in args.types.split(",")] if args.types else None
results = scrape(
location=args.location,
type=args.type,
types=types_list,
limit=args.limit,
radius_km=args.radius_km,
verbose=args.verbose,
)
if not results:
print("No results.", file=sys.stderr)
return
if args.export == "csv":
def _csv_val(v):
if isinstance(v, (list, dict)):
return json.dumps(v, ensure_ascii=False)
return v
out = open(args.output, "w", newline="", encoding="utf-8") if args.output else sys.stdout
writer = csv.DictWriter(out, fieldnames=results[0].keys())
writer.writeheader()
writer.writerows([{k: _csv_val(v) for k, v in r.items()} for r in results])
if args.output:
out.close()
print(f"Saved {len(results)} rows to {args.output}")
elif args.export == "json":
out_str = json.dumps(results, indent=2, default=str)
if args.output:
with open(args.output, "w", encoding="utf-8") as f:
f.write(out_str)
print(f"Saved {len(results)} records to {args.output}")
else:
print(out_str)
else:
print(f"\n{'#':<4} {'Name':<35} {'Rating':<8} {'Phone':<18} {'Website'}")
print("-" * 100)
for i, r in enumerate(results, 1):
rating = f"{r.get('rating')}★" if r.get("rating") else "-"
phone = r.get("phone") or "-"
website = r.get("website") or "-"
name = (r.get("name") or "")[:34]
print(f"{i:<4} {name:<35} {rating:<8} {phone:<18} {website}")
if args.verbose:
addr = r.get("address") or ""
tags = ", ".join(r.get("category_tags") or [])
reviews = r.get("review_count") or 0
open_now = "open" if r.get("is_open_now") else ("closed" if r.get("is_open_now") is False else "?")
print(f" Address : {addr}")
print(f" Reviews : {reviews} | Tags: {tags} | {open_now}")
print(f" URL : {r.get('source_url') or ''}")
print("-" * 100)
print(f"Total: {len(results)}")
if __name__ == "__main__":
main()