Proyecto Extractor de ID de correo electrónico de sitios en Scrapy Python

Scrapy es un marco de rastreo web de código abierto escrito en Python que se utiliza para el raspado web, también se puede usar para extraer datos para fines generales. Primero, todos los enlaces de las subpáginas se toman de la página principal y luego la identificación del correo electrónico se extrae de estas subpáginas usando expresiones regulares. 

Este artículo muestra la extracción de ID de correo electrónico del sitio geeksforgeeks como referencia.

ID de correo electrónico que se extraerán del sitio de geeksforgeeks: [‘feedback@geeksforgeeks.org’, ‘classes@geeksforgeeks.org’, ‘complaints@geeksforgeeks.org’, ‘review-team@geeksforgeeks.org’]

¿Cómo crear un proyecto de extracción de ID de correo electrónico usando Scrapy?

1. Instalación de paquetes : ejecute el siguiente comando desde la terminal 

pip install scrapy 
pip install scrapy-selenium

2. Crear proyecto – 

scrapy startproject projectname (Here projectname is geeksemailtrack) 
cd projectname 
scrapy genspider spidername (Here spidername is emails)

3) Agregue código en el archivo settings.py para usar scrapy-selenium

from shutil import which 
SELENIUM_DRIVER_NAME = 'chrome' 
SELENIUM_DRIVER_EXECUTABLE_PATH = which('chromedriver') 
SELENIUM_DRIVER_ARGUMENTS=[]
DOWNLOADER_MIDDLEWARES = { 
'scrapy_selenium.SeleniumMiddleware': 800 
}

4) Ahora descargue el controlador de cromo para su cromo y colóquelo cerca de su archivo chrome scrapy.cfg. Para descargar el controlador de Chrome, consulte este sitio: para descargar el controlador de Chrome

Estructura de directorios – 

Código paso a paso – 

1. Importe todas las bibliotecas necesarias: 

Python3

# web scraping framework
import scrapy
 
# for regular expression
import re
 
# for selenium request
from scrapy_selenium import SeleniumRequest
 
# for link extraction
from scrapy.linkextractors.lxmlhtml import LxmlLinkExtractor

2. Cree la función start_requests para visitar el sitio desde Selenium. Puede agregar su propia URL. 
 

Python3

def start_requests(self):
    yield SeleniumRequest(
        url="https://www.geeksforgeeks.org/",
        wait_time=3,
        screenshot=True,
        callback=self.parse,
        dont_filter=True
    )

3. Crear función de análisis
 

Python3

def parse(self, response):
        # this helps to get all links from source code
        links = LxmlLinkExtractor(allow=()).extract_links(response)
 
        # Finallinks contains links urk
        Finallinks = [str(link.url) for link in links]
 
        # links list for url that may have email ids
        links = []
 
        # filtering and storing only needed url in links list
        # pages that are about us and contact us are the ones that have email ids
        for link in Finallinks:
            if ('Contact' in link or 'contact' in link or 'About' in link or 'about' in link or 'CONTACT' in link or 'ABOUT' in link):
                links.append(link)
 
        # current page url also added because few sites have email ids on there main page
        links.append(str(response.url))
 
 
 
        # parse_link function is called for extracting email ids
        l = links[0]
        links.pop(0)
 
        # meta helps to transfer links list from parse to parse_link
        yield SeleniumRequest(
            url=l,
            wait_time=3,
            screenshot=True,
            callback=self.parse_link,
            dont_filter=True,
            meta={'links': links}
        )

Explicación de la función de análisis – 

  • En las siguientes líneas, todos los enlaces se extraen de https://www.geeksforgeeks.org/response.
links = LxmlLinkExtractor(allow=()).extract_links(response) 
Finallinks = [str(link.url) for link in links] 
  • Finallinks es una lista que contiene todos los enlaces.
  • Para evitar enlaces innecesarios, colocamos un filtro que, si los enlaces pertenecen al contacto y a la página, solo extraemos los detalles de esa página.
for link in Finallinks: 
if ('Contact' in link or 'contact' in link or 'About' in link or 'about' in link or 
or 'CONTACT' in link or 'ABOUT' in 
link): 
links.append(link) 
  • Este filtro anterior no es necesario, pero los sitios tienen muchas etiquetas (enlaces) y, debido a esto, si el sitio tiene 50 subpáginas en el sitio, extraerá el correo electrónico de estas 50 sub URL. se supone que los correos electrónicos se encuentran principalmente en la página de inicio, la página de contacto y la página de información, por lo que este filtro ayuda a reducir la pérdida de tiempo al eliminar esas URL que pueden no tener identificaciones de correo electrónico.
  • Los enlaces de las páginas que pueden tener identificadores de correo electrónico se solicitan uno por uno y los identificadores de correo electrónico se extraen utilizando expresiones regulares.

4. Cree el código de función  parse_link :

Python3

def parse_link(self, response):
    # response.meta['links'] this helps to get links list
    links = response.meta['links']
    flag = 0
 
    # links that contains following bad words are discarded
    bad_words = ['facebook', 'instagram', 'youtube', 'twitter', 'wiki', 'linkedin']
 
    for word in bad_words:
        # if any bad word is found in the current page url
        # flag is assigned to 1
        if word in str(response.url):
            flag = 1
            break
 
    # if flag is 1 then no need to get email from
    # that url/page
    if (flag != 1):
        html_text = str(response.text)
        # regular expression used for email id
        email_list = re.findall('\w+@\w+\.{1}\w+', html_text)
        # set of email_list to get unique
        email_list = set(email_list)
        if (len(email_list) != 0):
            for i in email_list:
                # adding email ids to final uniqueemail
                self.uniqueemail.add(i)
 
    # parse_link function is called till
    # if condition satisfy
    # else move to parsed function
    if (len(links) > 0):
        l = links[0]
        links.pop(0)
        yield SeleniumRequest(
            url=l,
            callback=self.parse_link,
            dont_filter=True,
            meta={'links': links}
        )
    else:
        yield SeleniumRequest(
            url=response.url,
            callback=self.parsed,
            dont_filter=True
        )

Explicación de la función parse_link: 
Mediante response.text obtenemos todo el código fuente de la URL solicitada. La expresión regular ‘\w+@\w+\.{1}\w+’ que se usa aquí podría traducirse a algo como esto Busque cada fragmento de string que comience con una o más letras, seguidas de un signo de arroba (‘@’) , seguido de una o más letras con un punto al final. 
Después de eso, debería volver a tener una o más letras. Es una expresión regular utilizada para obtener la identificación del correo electrónico.

5. Crear función analizada
 

Python3

def parsed(self, response):
    # emails list of uniqueemail set
    emails = list(self.uniqueemail)
    finalemail = []
 
    for email in emails:
        # avoid garbage value by using '.in' and '.com'
        # and append email ids to finalemail
        if ('.in' in email or '.com' in email or 'info' in email or 'org' in email):
 
            finalemail.append(email)
 
    # final unique email ids from geeksforgeeks site
    print('\n'*2)
    print("Emails scraped", finalemail)
    print('\n'*2)

Explicación de la función analizada: 
la expresión regular anterior también conduce a valores basura como select@1.13 en esta identificación de correo electrónico de geeksforgeeks, sabemos que select@1.13 no es una identificación de correo electrónico. El filtro de función analizada aplica un filtro que solo acepta correos electrónicos que contienen ‘.com’ y “.in”.
 

Ejecute la araña usando el siguiente comando: 

scrapy crawl spidername (spidername is name of spider)

Valor basura en correos electrónicos raspados: 

Correos electrónicos raspados finales: 
 

Python

# web scraping framework
import scrapy
 
# for regular expression
import re
 
# for selenium request
from scrapy_selenium import SeleniumRequest
 
# for link extraction
from scrapy.linkextractors.lxmlhtml import LxmlLinkExtractor
 
class EmailtrackSpider(scrapy.Spider):
    # name of spider
    name = 'emailtrack'
 
    # to have unique email ids
    uniqueemail = set()
 
    # start_requests sends request to given https://www.geeksforgeeks.org/
    # and parse function is called
    def start_requests(self):
        yield SeleniumRequest(
            url="https://www.geeksforgeeks.org/",
            wait_time=3,
            screenshot=True,
            callback=self.parse,
            dont_filter=True
        )
 
    def parse(self, response):
            # this helps to get all links from source code
            links = LxmlLinkExtractor(allow=()).extract_links(response)
 
            # Finallinks contains links urk
            Finallinks = [str(link.url) for link in links]
 
            # links list for url that may have email ids
            links = []
 
            # filtering and storing only needed url in links list
            # pages that are about us and contact us are the ones that have email ids
            for link in Finallinks:
                if ('Contact' in link or 'contact' in link or 'About' in link or 'about' in link or 'CONTACT' in link or 'ABOUT' in link):
                    links.append(link)
 
            # current page url also added because few sites have email ids on there main page
            links.append(str(response.url))
 
 
 
            # parse_link function is called for extracting email ids
            l = links[0]
            links.pop(0)
 
            # meta helps to transfer links list from parse to parse_link
            yield SeleniumRequest(
                url=l,
                wait_time=3,
                screenshot=True,
                callback=self.parse_link,
                dont_filter=True,
                meta={'links': links}
            )
 
 
    def parse_link(self, response):
 
        # response.meta['links'] this helps to get links list
        links = response.meta['links']
        flag = 0
 
        # links that contains following bad words are discarded
        bad_words = ['facebook', 'instagram', 'youtube', 'twitter', 'wiki', 'linkedin']
 
        for word in bad_words:
            # if any bad word is found in the current page url
            # flag is assigned to 1
            if word in str(response.url):
                flag = 1
                break
 
        # if flag is 1 then no need to get email from
        # that url/page
        if (flag != 1):
            html_text = str(response.text)
            # regular expression used for email id
            email_list = re.findall('\w+@\w+\.{1}\w+', html_text)
            # set of email_list to get unique
            email_list = set(email_list)
            if (len(email_list) != 0):
                for i in email_list:
                    # adding email ids to final uniqueemail
                    self.uniqueemail.add(i)
 
        # parse_link function is called till
        # if condition satisfy
        # else move to parsed function
        if (len(links) > 0):
            l = links[0]
            links.pop(0)
            yield SeleniumRequest(
                url=l,
                callback=self.parse_link,
                dont_filter=True,
                meta={'links': links}
            )
        else:
            yield SeleniumRequest(
                url=response.url,
                callback=self.parsed,
                dont_filter=True
            )
 
    def parsed(self, response):
        # emails list of uniqueemail set
        emails = list(self.uniqueemail)
        finalemail = []
 
        for email in emails:
            # avoid garbage value by using '.in' and '.com'
            # and append email ids to finalemail
            if ('.in' in email or '.com' in email or 'info' in email or 'org' in email):
 
                finalemail.append(email)
 
        # final unique email ids from geeksforgeeks site
        print('\n'*2)
        print("Emails scraped", finalemail)
        print('\n'*2)

Video de trabajo del código anterior –

Referencia – extractores de enlaces 
 

Publicación traducida automáticamente

Artículo escrito por Versus y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *