Я написал некоторый код, который добавляет списки релевантных 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)
Я не совсем уверен, что я делаю неправильно, но я знаю, что должен быть лучший способ сделать это.Пожалуйста, скажите мне, что я делаю не так.