# py-lead-generation: pulling business contact data from Maps and Yelp

> py-lead-generation is a small Python package that drives a browser with Playwright to parse Google Maps and Yelp listings and export the results as CSV. The shipped feature set is narrower than the project's stated ambitions, and the README describes the package as a sort of abandoned update of an earlier script collection.

**Madi-S/Lead-Generation** — Python script, which empowers people with no programming background to generate robust leads on a mass scale. This repo will be compiled of various versatile techniques used in lead generation.

- Repository: https://github.com/Madi-S/Lead-Generation
- Website: https://pypi.org/project/py-lead-generation/
- Stars: 674 · Forks: 114
- Language: Python
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/madi-s-lead-generation

## Two engines, one async call each, one CSV at the end

The package exposes two engines, `GoogleMapsEngine` and `YelpEngine`, and the quickstart shows the whole usage pattern in about fifteen lines. You give an engine a query and a location, await its `run()` method, and then call `save_to_csv()`.

The Google Maps engine takes three arguments, the search query, the location, and a zoom level, while the Yelp engine takes a query and a location and lets you name the output file. The package is importable under the `py_lead_generation` name, and the whole flow is driven by `asyncio`, so the two engines are awaited inside an async main function rather than called synchronously.

What the engines produce is the thing the README names as its current functionality: parse Google Maps, parse Yelp, and export the collected data to a CSV file. The goal list expands on that, saying the project should parse those two sites for telephone number, email, address and other information by a given keyword, and export all parsed data to CSV or Excel.

So the mechanism is a browser automation pipeline rather than an API client. The dependencies in `setup.py` are `playwright`, `beautifulsoup4` and `geopy`, and the repository topics list chromedriver, playwright, parser and web-crawler. Playwright drives a real browser, Beautiful Soup pulls structure out of the resulting HTML, and geopy handles the location handling that the Maps engine needs.

## Installation from PyPI is the path the README recommends

The primary install is a single pip command, and the README marks the pip route as recommended:

```bash
pip install py-lead-generation
```

The package is published on PyPI under the name py-lead-generation, and the repository homepage points at the PyPI project page. The `setup.py` describes the distribution as `py_lead_generation` at version 1.0.1, with the licence declared as MIT, the author as Madi-S, and the packages found with `find_packages()`, so the import name and the install name differ in the usual way.

The source route is listed but explicitly not recommended. The clone plus edit plus run sequence is:

```bash
git clone https://github.com/Madi-S/Lead-Generation
cd Lead-Generation
# Edit run.py for your needs
python run.py
```

That `run.py` at the repository root is a script you edit, which tells you something about how the project expects to be used. Rather than a configuration file or a command line interface with flags, you open the script and change it.

There is a third path for the older code, and the README describes it as the previous archived version. The `archived/` directory at the top level of the repository holds it, with a google-maps subdirectory:

```bash
git clone https://github.com/Madi-S/Lead-Generation
cd Lead-Generation
cd archived
cd google-maps
python extractor.py
```

So the repository ships two generations of the same idea side by side, and the newer package is presented as the updated version of the older script collection.

## The quickstart is the entire API surface you can see

The quickstart in the README is worth reading closely because it is the whole documented interface, and it shows how much of the design is prompt-driven rather than configured.

Every run asks the operator three questions at the terminal. The search query defaults to Barbershop if you press enter on an empty line, the location defaults to Paris, and the zoom defaults to 12. The defaults are hardcoded in the example, which is fine for a demonstration and awkward for anything repeated.

```python
import asyncio
from py_lead_generation import GoogleMapsEngine, YelpEngine


async def main() -> None:
    q = input('Enter your search query: ').strip() or 'Barbershop'
    addr = input('Enter the location you would like to search in: ').strip() \
        or 'Paris'
    zoom = float(input('[Optional] Enter google maps zoom: ').strip() or 12)

    engine = GoogleMapsEngine(q, addr, zoom)
    await engine.run()
    engine.save_to_csv()

    engine = YelpEngine('Pizza', 'Mexico, Pampanga, Philippines')
    await engine.run()
    engine.save_to_csv('pizza_leads.csv')

if __name__ == '__main__':
    asyncio.run(main())
```

Note the `save_to_csv` call with a filename for the Yelp engine and without one for the Maps engine, which suggests the filename is optional and the engine has a default.

There is no mention in the README of a headless mode, a browser install step for Playwright, a proxy setting, a rate limit, a retry policy, or a way to schedule runs. A user who wants those has to read the engine source in the `py_lead_generation/` package directory.

## The stated ambitions run well past the shipped features

The README separates what the project does now from what it expects of itself, and the gap is large enough that a reader should treat the feature list carefully.

Under current functionality there are exactly three items: parse Google Maps, parse Yelp, and export collected data to a CSV file. Under expectations of this project there are five, and the last three are described in the future tense of intent rather than as shipped behavior.

The project wants to parse Google Maps and Yelp for telephone number, email, address and other information by a given keyword, which is a claim about the fields collected rather than about the sites. It wants to parse Google Search results for the same information using regex or other algorithms, and Google Search is not in the current functionality list at all. It wants to export to CSV or Excel, and only CSV appears under current functionality. It wants to send a message to parsed emails and an SMS to parsed telephone numbers, with both described as prevented from going to spam.

The email and SMS items are the ones to look at hardest. Nothing in the current functionality list covers sending, and describing spam prevention as a goal rather than a feature suggests the delivery side is not built. An outbound messaging layer bolted onto a scraper is also the part of such a system that carries the legal weight, since it turns collected contact details into unsolicited contact.

The packaging metadata is candid in a way the README is not. The development status classifier in `setup.py` reads `Development Status :: 1 - Planning`, which is a formal statement that the project is at planning stage, and the README's own framing calls the current package a sort of abandoned version of an older, outdated and clumsy script collection.

## Python 3.10, three dependencies, and a package that still says planning stage

The dependency set is genuinely small. `install_requires` lists `playwright`, `beautifulsoup4` and `geopy`, and `python_requires` is `>=3.10`. The classifiers list Python 3.10 as the supported version, and name Unix, MacOS and Windows as operating systems.

Two things follow from that. The first is that a Playwright install needs a browser binary that pip alone does not fetch, so a working installation takes more than the single command the README shows. The second is that the package is young enough that the 3.10 floor was a choice rather than a legacy constraint, and there is no stated support for 3.11 or 3.12 even though both were available well before the release.

The release history is thin. There is a single tagged release, 1.0.1, dated 2024-09-24, and the version in `setup.py` matches it. The last push was on 2026-09-23, so the repository is being touched without producing a new PyPI release, which means the code on GitHub and the code pip installs are not necessarily the same.

The licence is MIT, declared in `setup.py` and in the repository, and the repository also has a `LICENSE` file. That is the permissive end of the scale and there is nothing unusual to note about it beyond the standard obligations. The project is not archived.

What a reader should take away is the combination of a small surface, a single release from 2024, a planning-stage classifier, and a README that describes the package as a sort of abandoned update. Taken together they describe a useful reference implementation rather than a product to depend on.

## Compared with a hosted scraping API and with your own Playwright script

The realistic alternatives differ in where the work and the maintenance sit.

A hosted scraping service takes a URL or a search query and returns structured data over an API, with proxies, rotation, retries and anti-bot handling handled on their side. You pay for the abstraction and you give up control of what the request looks like. The difference in approach here is that py-lead-generation runs the browser on your own machine, so there is no per-request cost and no third party in the path, but the same anti-bot problems arrive unhandled, because the code you can see does not include proxying or throttling.

Writing your own Playwright script is the closer comparison. The package is essentially that script, packaged so it can be imported, and the practical difference is that you get two prebuilt engines for two specific sites and the CSV export already wired up. What you give up is the ability to change the parsing without forking or monkeypatching, since the site-specific extraction logic is inside the engine classes rather than behind a documented hook.

The third option is a browser extension or a desktop crawler with a visual interface, which is what many people actually want for lead work, since the operator can see what is being collected and adjust on the spot. py-lead-generation has no interface of that kind. The interaction is a terminal prompt, a browser window driven by Playwright, and a CSV file at the end.

None of these alternatives makes the underlying constraint go away. Collecting business contact details at volume from a search engine's result pages is governed by that site's terms of service, and running the same query from one machine in a tight loop is the pattern those terms exist to prevent. The package offers no delay setting, no rotation, and no scope restriction, so the operator carries that responsibility entirely.

## Conclusion

Adopt py-lead-generation if you need a small, readable Playwright script that turns a search term and a location into a CSV of business listings, and you are willing to read the engine source to see exactly what it collects. Do not adopt it if you need a maintained scraping platform, because the README calls the package a sort of abandoned rewrite and the last release on PyPI is 1.0.1 from 2024-09-24, while the last push was on 2026-09-23. Verify first that the two engines still match the current page markup of Google Maps and Yelp, and confirm that scraping those sites is permitted under their terms before you run it on any real volume.

## FAQ

### How do I install py-lead-generation?

The README recommends pip: `pip install py-lead-generation`. Installing from source is also documented but marked not recommended, and the README notes that the package is on PyPI as py-lead-generation while the import name is py_lead_generation.

### What does py-lead-generation actually collect?

Under current functionality the README lists parsing Google Maps, parsing Yelp, and exporting the data to CSV. The project's expectations extend further, to parsing Google Search as well and to exporting Excel files, and to sending email and SMS messages to the parsed contacts, but those are described as goals rather than shipped features.

### How do I use the Google Maps and Yelp engines?

Import `GoogleMapsEngine` and `YelpEngine` from `py_lead_generation`, construct one with a search query and a location, `await engine.run()`, then call `engine.save_to_csv()`, optionally with an output filename as the Yelp example shows.

### Is py-lead-generation still maintained?

The README calls the package a sort of abandoned version of an older script collection, the setup.py classifier reads Development Status :: 1 - Planning, and the only listed release is 1.0.1 from 2024-09-24. The repository itself is not archived and the last push was on 2026-09-23.

### What license is py-lead-generation under and what are its dependencies?

The package is MIT licensed, with the terms in the repository LICENSE file. The install_requires list in setup.py names playwright, beautifulsoup4 and geopy, and python_requires is 3.10 or newer.

## Sources

- [License: MIT](https://github.com/Madi-S/Lead-Generation/blob/main/LICENSE)
- [Madi-S/Lead-Generation on GitHub](https://github.com/Madi-S/Lead-Generation)
- [Project website](https://pypi.org/project/py-lead-generation/)
- [README](https://github.com/Madi-S/Lead-Generation/blob/main/README.md)
- [Releases](https://github.com/Madi-S/Lead-Generation/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/madi-s-lead-generation
