Попытка перебрать строки в пандас-фрейме данных, получить список URL-адресов в каждой строке и извлечь электронные письма, используя scrapy - PullRequest
0 голосов
/ 14 февраля 2019

Я написал некоторый код, который добавляет списки релевантных URL-адресов в строку в кадре данных pandas.Теперь я пытаюсь перебрать эти списки и найти в каждом из них адреса электронной почты.Вот что у меня есть:

import requests, random, traceback, logging, os, re
from lxml.html import fromstring
from itertools import cycle
import pandas as pd
from googlesearch import search
import scrapy
from scrapy.crawler import CrawlerProcess
from scrapy.linkextractors.lxmlhtml import LxmlLinkExtractor

# # FOR JUPYTER NOTEBOOKS:
logging.getLogger('scrapy').propagate = False


# PULL IN A LIST:
df = pd.read_csv('example.csv')
df = df.drop_duplicates()

# GET URLS FROM LIST:
def get_urls(tag, n, language):
    urls = [url for url in search(tag, stop=n, lang=language)][:n]
    return urls

# SCRAPE URLS FROM LIST
scrape_urls = lambda x: [get_urls(x, 10, 'en') for x in df.Names]
df['urls'] = df.apply(scrape_urls)

Что возвращает:

   Names           urls
0  Turner Construction [https://www.turnerconstruction.com/, http://w...
1  McCarthy Holdings   [https://www.mccarthy.com/, https://www.mccart...
2  Brasfield & Gorrie  [https://en.wikipedia.org/wiki/Brasfield_%26_G...
3  Skanska USA         [https://www.usa.skanska.com/, https://www.usa...
4  DPR Construction    [https://en.wikipedia.org/wiki/DPR_Constructio...

Запуск df.urls[0] показывает данные немного лучше:

['https://www.turnerconstruction.com/',
 'http://www.turnerconstruction.com/careers',
 'http://www.turnerconstruction.com/about-us',
 'http://www.turnerconstruction.com/office-network',
 'http://www.turnerconstruction.com/office-network/new-york',
 'http://www.turnerconstruction.com/careers/jobs',
 'http://www.turnerconstruction.com/careers/experienced',
 'https://en.wikipedia.org/wiki/Turner_Construction',
 'https://en.wikipedia.org/wiki/Turner_Construction#History',
 'https://en.wikipedia.org/wiki/Turner_Construction#Early_years']

Естьсписок из 10 URL-адресов для каждого имени в Именах.

Теперь я пытаюсь запустить паука-скрапа, который ищет в этих URL-адресах электронные письма, обеспечивая также поиск дополнительных ссылок внутри «URL-адресов»:

# CRATE A SCRAPY SPIDER THAT SEARCHES URLS FOR LINKS AND GOES THROUGH THEM FOR EMAILS
class MailSpider(scrapy.Spider):

    name = 'email'

    def parse(self, response):
#         check for new URLs inside a source
        links = LxmlLinkExtractor(allow=()).extract_links(response)
        links = [str(link.url) for link in links]
        links.append(str(response.url))

        for link in links:
#             send links from one parse method to another
            yield scrapy.Request(url=link, callback=self.parse_link) 

    def parse_link(self, response):

        for word in self.reject:
            if word in str(response.url):
                return

        html_text = str(response.text)
#         regex expression to search for emails
        mail_list = re.findall('\w+@\w+\.{1}\w+', html_text)

        dic = {'name': name, 'link': str(response.url), 'email': mail_list}
        df2 = pd.DataFrame(dic)

        df2.to_csv(self.path, mode='a', header=False)
        df2.to_csv(self.path, mode='a', header=False)

Затем я определяю функции, которые должны получать электронные письма (get_info), спрашиваю пользователя, хотят ли они создать файл с добавленными электронными письмами (ask_user), а затемсоздайте этот файл (create_file):

def ask_user(question):
    response = input(question + ' y/n' + '\n')
    if response == 'y':
        return True
    else:
        return False

def create_file(path):
    response = False
    if os.path.exists(path):
        response = ask_user('File already exists, replace?')
        if response == False: return 

    with open(path, 'wb') as file: 
        file.close()

def get_info(tag, path, reject=[]):

    create_file(path)
    df2 = pd.DataFrame(columns=['name', 'urls', 'email'], index=[0])
    df2.to_csv(path, mode='w', header=True)

    print('Collecting urls...')
    url_lists = df['urls']

    print('Searching for emails...')
    process = CrawlerProcess({'USER_AGENT': 'Mozilla/5.0'})
    process.crawl(MailSpider, start_urls=url_lists, path=path, reject=reject)
    process.start()

    print('Cleaning emails...')
    df2 = pd.read_csv(path, index_col=0)
    df2.columns = ['name', 'links', 'email']
    df2 = df.drop_duplicates(subset='email')
    df2 = df.reset_index(drop=True)
    df2.to_csv(path, mode='w', header=True)

    return df2

Наконец, я вызываю все это, определяя список bad_words для исключения из поиска, затем вызывая get_info:

bad_words = ['facebook', 'instagram', 'youtube', 'twitter', 'wiki']
df = get_info(df['urls'], 'company_info.csv', reject=bad_words)

Я не совсем уверен, что я делаю неправильно, но я знаю, что должен быть лучший способ сделать это.Пожалуйста, скажите мне, что я делаю не так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...