Skip to main content
deleted 14 characters in body
Source Link
alecxe
  • 17.3k
  • 8
  • 51
  • 93
import requests
from lxml import html


class YellowPageScraper:
    base_url = "https://www.yellowpages.com/search?search_terms=pizza&geo_location_terms=Los+Angeles%2C+CA"
    url = "https://www.yellowpages.com"

    def __init__(self):
        self.vault = []
        self.session = requests.Session()

    def crawl(self):
        self.get_urls(self.base_url)
        self.process_links(self.base_url)

    def get_urls(self, link):
        """Going to the main page for collecting links leading to the target page."""
        response = self.session.get(link)
        tree = html.fromstring(response.text)

        for item in tree.xpath("//div[@class='info']"):
            item_links = item.xpath(".//a[@class='business-name'][not(@itemprop='name')]/@href")
            for page in item_links:
                self.target_page(self.url + page)

    def process_links(self, link):
        """Creating links leading to the next page."""
        response = self.session.get(link)
        tree = html.fromstring(response.text)
        
        next_urls = tree.xpath("//div[@class='pagination']//li/a/@href")
        for next_url in next_urls:
            self.get_urls(self.url + next_url)

    def target_page(self, urls):
        """Scraping required data reaching this target page."""
        response = self.session.get(urls)
        tree = html.fromstring(response.text)

        for post in tree.xpath("//*[@id='main-header']"):
            name = post.findtext(".//div[@class='sales-info']/h1/text()"h1")
            phone = post.findtext('.//p[@class="phone"]/text()'p[@class="phone"]')
            
            records = name, phone
            if records not in self.vault:
                self.vault.append(records)

    def __str__(self):
        return self.vault


if __name__ == '__main__':
    crawler = YellowPageScraper()
    crawler.crawl()
    for item in crawler.vault:
        print(item)
import requests
from lxml import html


class YellowPageScraper:
    base_url = "https://www.yellowpages.com/search?search_terms=pizza&geo_location_terms=Los+Angeles%2C+CA"
    url = "https://www.yellowpages.com"

    def __init__(self):
        self.vault = []
        self.session = requests.Session()

    def crawl(self):
        self.get_urls(self.base_url)
        self.process_links(self.base_url)

    def get_urls(self, link):
        """Going to the main page for collecting links leading to the target page."""
        response = self.session.get(link)
        tree = html.fromstring(response.text)

        for item in tree.xpath("//div[@class='info']"):
            item_links = item.xpath(".//a[@class='business-name'][not(@itemprop='name')]/@href")
            for page in item_links:
                self.target_page(self.url + page)

    def process_links(self, link):
        """Creating links leading to the next page."""
        response = self.session.get(link)
        tree = html.fromstring(response.text)
        
        next_urls = tree.xpath("//div[@class='pagination']//li/a/@href")
        for next_url in next_urls:
            self.get_urls(self.url + next_url)

    def target_page(self, urls):
        """Scraping required data reaching this target page."""
        response = self.session.get(urls)
        tree = html.fromstring(response.text)

        for post in tree.xpath("//*[@id='main-header']"):
            name = post.findtext(".//div[@class='sales-info']/h1/text()")
            phone = post.findtext('.//p[@class="phone"]/text()')
            
            records = name, phone
            if records not in self.vault:
                self.vault.append(records)

    def __str__(self):
        return self.vault


if __name__ == '__main__':
    crawler = YellowPageScraper()
    crawler.crawl()
    for item in crawler.vault:
        print(item)
import requests
from lxml import html


class YellowPageScraper:
    base_url = "https://www.yellowpages.com/search?search_terms=pizza&geo_location_terms=Los+Angeles%2C+CA"
    url = "https://www.yellowpages.com"

    def __init__(self):
        self.vault = []
        self.session = requests.Session()

    def crawl(self):
        self.get_urls(self.base_url)
        self.process_links(self.base_url)

    def get_urls(self, link):
        """Going to the main page for collecting links leading to the target page."""
        response = self.session.get(link)
        tree = html.fromstring(response.text)

        for item in tree.xpath("//div[@class='info']"):
            item_links = item.xpath(".//a[@class='business-name'][not(@itemprop='name')]/@href")
            for page in item_links:
                self.target_page(self.url + page)

    def process_links(self, link):
        """Creating links leading to the next page."""
        response = self.session.get(link)
        tree = html.fromstring(response.text)
        
        next_urls = tree.xpath("//div[@class='pagination']//li/a/@href")
        for next_url in next_urls:
            self.get_urls(self.url + next_url)

    def target_page(self, urls):
        """Scraping required data reaching this target page."""
        response = self.session.get(urls)
        tree = html.fromstring(response.text)

        for post in tree.xpath("//*[@id='main-header']"):
            name = post.findtext(".//div[@class='sales-info']/h1")
            phone = post.findtext('.//p[@class="phone"]')
            
            records = name, phone
            if records not in self.vault:
                self.vault.append(records)

    def __str__(self):
        return self.vault


if __name__ == '__main__':
    crawler = YellowPageScraper()
    crawler.crawl()
    for item in crawler.vault:
        print(item)
Source Link
alecxe
  • 17.3k
  • 8
  • 51
  • 93

In some sense, you are reinventing what Scrapy web-scraping framework provides from out-of-the-box. Take a look how Scrapy spiders are written and you may find something similar, but better organized with less boilerplate code. Since, you've been doing quite a lot of web-scraping, I would go ahead and give Scrapy a try here.

Some notes about the code:

  • naming. Remember: code is much often read than written. YelPage can be replaced with a more explicit YellowPageScraper; next_page actually means next_pages since you locate multiple of them - etc. (please refer to the code below for the other improved variable names)
  • as I've mentioned before, you can reuse a session by having a session instance as your instance variable
  • comments before each of the methods should be transformed to proper method documentation strings

Improved code:

import requests
from lxml import html


class YellowPageScraper:
    base_url = "https://www.yellowpages.com/search?search_terms=pizza&geo_location_terms=Los+Angeles%2C+CA"
    url = "https://www.yellowpages.com"

    def __init__(self):
        self.vault = []
        self.session = requests.Session()

    def crawl(self):
        self.get_urls(self.base_url)
        self.process_links(self.base_url)

    def get_urls(self, link):
        """Going to the main page for collecting links leading to the target page."""
        response = self.session.get(link)
        tree = html.fromstring(response.text)

        for item in tree.xpath("//div[@class='info']"):
            item_links = item.xpath(".//a[@class='business-name'][not(@itemprop='name')]/@href")
            for page in item_links:
                self.target_page(self.url + page)

    def process_links(self, link):
        """Creating links leading to the next page."""
        response = self.session.get(link)
        tree = html.fromstring(response.text)
        
        next_urls = tree.xpath("//div[@class='pagination']//li/a/@href")
        for next_url in next_urls:
            self.get_urls(self.url + next_url)

    def target_page(self, urls):
        """Scraping required data reaching this target page."""
        response = self.session.get(urls)
        tree = html.fromstring(response.text)

        for post in tree.xpath("//*[@id='main-header']"):
            name = post.findtext(".//div[@class='sales-info']/h1/text()")
            phone = post.findtext('.//p[@class="phone"]/text()')
            
            records = name, phone
            if records not in self.vault:
                self.vault.append(records)

    def __str__(self):
        return self.vault


if __name__ == '__main__':
    crawler = YellowPageScraper()
    crawler.crawl()
    for item in crawler.vault:
        print(item)