#python #web-scraping
#python #веб-очистка
Вопрос:
Я новичок в python. Только вчера началось. Я хочу очистить информацию с этого веб-сайта https://www.letudiant.fr/educpros/responsables-enseignement-superieur/critere-Responsable.html . Я хочу извлечь основную информацию о контактах, такую как полное имя, должность, телефон, электронная почта, компания.
Вот код, который я написал с помощью Beautifulsoup и запросов:
import requests
from bs4 import BeautifulSoup
for page in range(1, 1000): # Number of pages plus one
url = "https://www.letudiant.fr/educpros/responsables-enseignement-superieur/critere-directeur.html".format(page)
r = requests.get(url, headers={'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36'})
soup = BeautifulSoup(r.text, 'lxml')
for contenu in soup.find_all('div', class_='box-content2'):
for link in contenu.find_all('a'):
page = "https://www.letudiant"
data = page link.get('href')
contact = requests.get(data)
soup_bis = BeautifulSoup(contact.text, 'lmxl')
for full_name in soup_bis.find_all('box-content2'):
print(full_name)
Ответ №1:
Некоторые указатели:
1) вы переходите page
от числовой переменной цикла к строковому значению URL внутри цикла. Измените внутреннюю переменную на другое имя, например base
, и не забудьте добавить .fr
в конце. Затем вы можете получить все внутренние ссылки с помощью просто:
base = "https://www.letudiant.fr"
# other code
links = [base item['href'] for item in soup.select('.box-content2 a')]
2) Вы используете .format(page)
без заполнителя в строке url. Вы хотите:
url = "https://www.letudiant.fr/educpros/responsables-enseignement-superieur/critere-directeur/page-{}.html".format(page)
3) Учитывая количество запросов, которые вы делаете, рассмотрим requests.Session()
, например
4) Некоторые ссылки являются недействительными, поэтому рассмотрите возможность получения имени, должности и компании (они кажутся заполненными на первый взгляд) со страницы уровня url, а не на уровне ссылки.
Это не полностью протестировано, но структура может быть похожа:
import requests
from bs4 import BeautifulSoup
base = "https://www.letudiant.fr"
results = []
with requests.Session() as s:
for page in range(1, 2):
url = "https://www.letudiant.fr/educpros/responsables-enseignement-superieur/critere-directeur/page-{}.html".format(page)
headers = {'User-Agent': 'Mozilla/5', 'Referer' : url}
r = s.get(url, headers = headers)
soup = BeautifulSoup(r.text, 'lxml')
links = [base item['href'] for item in soup.select('.box-content2 a')]
temp_names = [item.text.strip() for item in soup.select('.box-content2 h3')]
temp_positions = [item.text.strip() for item in soup.select('.box-content2 h4')]
temp_companies = [re.sub('s{2,}', ' ',' '.join(item.text.split('n'))) for item in soup.select('.box-content2 .p1')]
i = 0
for link in links:
r = s.get(link)
soup = BeautifulSoup(r.text, 'lxml')
try:
data = soup.select_one('.box-content2')
name = getattr(data.find('h3'), 'text', 'N/A').strip()
position_company = getattr(data.find('h4'), 'text', 'N/A').strip()
if position_company:
position = position_company.split('n')[0].strip()
company = position_company.split('n')[2].strip()
address = re.sub('s{2,}', ' ', ' '.join(getattr(data.find('p'), 'text', 'N/A').split('n')).strip())
tel = data.select_one('[href^=tel]').text.strip() if data.select_one('[href^=tel]') else 'N/A'
# email - not scrapable
row = [name, position, company, address, tel]
except:
row = [temp_names[i], temp_positions[i], temp_companies[i], 'N/A', 'N/A']
results.append(row)
i =1
Ответ №2:
Вы можете использовать while
цикл для продолжения очистки, пока больше страниц не появится:
from bs4 import BeautifulSoup as soup
import requests, re
def get_person(_d):
new_d = soup(requests.get(f"https://www.letudiant.fr{_d.find('a')['href']}").text, 'html.parser')
b = new_d.find('div', {'class':'box-content2'})
return 'N/A' if not b else {'name':getattr(b.find('h3'), 'text', 'N/A'), 'position':b.find('h4').contents[0], 'company':b.find('h4').contents[-2].text, 'tel':getattr(new_d.find('a', {'href':re.compile('tel:d $')}), 'text', 'N/A')}
count, results = 1, []
d = soup(requests.get(f'https://www.letudiant.fr/educpros/responsables-enseignement-superieur/critere-Responsable/page-{count}.html').text, 'html.parser')
while any(str(count 1) in i['href'] for i in d.find_all('a', {'href':re.compile('page-d .html$')})):
results.append([get_person(i) for i in d.find_all('div', {'class':'box2 with-border theme-annuaire'})])
d = soup(requests.get(f'https://www.letudiant.fr/educpros/responsables-enseignement-superieur/critere-Responsable/page-{count 1}.html').text, 'html.parser')
count = 1
results.append([get_person(i) for i in d.find_all('div', {'class':'box2 with-border theme-annuaire'})])
clean_data = [[c if isinstance(c, str) else [{a:re.sub('^[rns] |[ns] $', '', b) for a, b in c.items()}] for c in i] for i in results]
Вывод (первые две страницы из-за ограничения символов SO):
[[[{'name': 'Aknin Nathalie', 'position': 'Responsable des relations internationales -', 'company': 'ENSA Nantes', 'tel': '02.40.16.02.41'}], [{'name': 'Ellenberger Eva', 'position': 'Responsable des relations internationales -', 'company': "Spéos l'école photo internationale Paris", 'tel': '01.40.09.18.58'}], [{'name': 'Claeys Jean-Luc', 'position': 'Responsable des classes préparatoires -', 'company': 'Lycée Saint-Rémi Roubaix', 'tel': '03.20.89.41.41'}], [{'name': 'Gadelii Karl', 'position': 'Responsable Erasmus (études nordiques) -', 'company': "UFR d'études germaniques et nordiques - faculté des lettres Paris (Sorbonne université)", 'tel': 'N/A'}], [{'name': 'Poulain Florence', 'position': 'Responsable de la communication -', 'company': 'ITII Bourgogne Auxerre (Dijon)', 'tel': '03.86.49.26.18'}], [{'name': 'Delapierre Anne', 'position': 'Responsable pédagogique -', 'company': 'ES2C Limoges', 'tel': '05.55.38.48.58'}], [{'name': 'Bondon Thierry', 'position': 'Responsable des classes préparatoires -', 'company': 'Lycée international de Valbonne', 'tel': '04.92.96.55.33'}], [{'name': 'Harrell Danielle', 'position': 'Responsable des relations internationales -', 'company': 'ArtFx Montpellier', 'tel': '04.99.77.01.42'}], [{'name': 'Doret Julie', 'position': 'Responsable de la communication -', 'company': 'Ionis-STM Ivry-sur-Seine', 'tel': '01.53.14.59.35'}], [{'name': 'Moreno Julie', 'position': 'Responsable de la communication -', 'company': 'Institut des éducateurs Paris', 'tel': '09.86.51.38.24'}], [{'name': 'Duris Marie-Françoise', 'position': 'Responsable des relations entreprises -', 'company': 'Lycée Notre-Dame Castres', 'tel': '05.63.62.58.00'}], [{'name': 'Torrente Pierre', 'position': 'Directeur adjoint, responsable du site de Foix -', 'company': 'ISTHIA Foix (Toulouse Jean-Jaurès)', 'tel': '05.61.02.19.74'}], [{'name': 'Vasseur Claudine', 'position': 'Responsable des relations extérieures -', 'company': 'Lycée Sophie-Berthelot Calais', 'tel': '03.21.19.77.77'}], [{'name': 'Lamkhioued Bouchaïb', 'position': 'Responsable des relations internationales -', 'company': 'UFR de pharmacie (Reims)', 'tel': '03.26.91.81.45'}], 'N/A', [{'name': 'Zouhdi Saïd', 'position': 'Responsable des relations internationales -', 'company': 'Polytech Paris-Sud Orsay (Paris-Sud)', 'tel': '01.69.33.86.00'}], [{'name': 'Sourlier Patricia', 'position': 'Responsable des relations internationales -', 'company': 'ITII PACA Istres', 'tel': '04.42.11.44.68'}], [{'name': 'Guyot Nicolas', 'position': "Responsable de l'alternance -", 'company': 'MFR Beaupréau-en-Mauges', 'tel': '02.41.63.02.04'}], [{'name': 'Grandidier Jean-Claude', 'position': 'Responsable de la recherche -', 'company': 'ISAE-ENSMA Chasseneuil-du-Poitou', 'tel': '05.49.49.83.41'}], [{'name': 'Onde Jean-Claude', 'position': 'Responsable des BTS -', 'company': 'Lycée Félix-Esclangon Manosque', 'tel': '04.92.70.54.70'}]], [[{'name': 'Chancerelle Marie-Alix', 'position': 'Responsable des relations entreprises -', 'company': 'IPAG Business School, campus de Paris', 'tel': '01.53.63.36.30'}], [{'name': 'Junek Françoise', 'position': 'Responsable de la communication -', 'company': 'IUT Valence (Grenoble Alpes)', 'tel': '04.75.41.88.69'}], [{'name': "Prud'homme Brigitte", 'position': 'Responsable pédagogique -', 'company': 'IFMEM Reims', 'tel': '03.26.78.74.67'}], [{'name': 'Canti Aldo', 'position': 'Responsable pédagogique -', 'company': 'CREPS Saint-Raphaël', 'tel': '04.94.40.27.40'}], [{'name': 'Cueille Arnaud', 'position': 'Responsable pédagogique -', 'company': 'EPSI Bordeaux', 'tel': '05.56.43.13.13'}], [{'name': 'Beaud Stéphane', 'position': 'Responsable des BTS -', 'company': 'Lycée Saint-Michel Annecy', 'tel': '04.50.45.05.20'}], [{'name': 'Faveret Laurence', 'position': 'Responsable pédagogique -', 'company': 'IRFSS CRF Besançon', 'tel': '03.81.83.19.17'}], [{'name': 'de Chantal François', 'position': 'Responsable de la communication (masters) -', 'company': 'UFR études anglophones (Paris 7)', 'tel': '01.57.27.58.00'}], [{'name': 'Loyer Sébastien', 'position': 'Responsable de la communication -', 'company': 'Lycée Saint-Paul Vannes', 'tel': '02.97.46.61.37'}], [{'name': 'Baran Oliwia', 'position': 'Responsable de la communication -', 'company': 'ESPOL (Université catholique de Lille)', 'tel': '03.59.56.79.76'}], [{'name': 'Lebret Thierry', 'position': 'Responsable des relations internationales -', 'company': 'UFR des sciences de la santé Simone Veil Montigny-le-Bretonneux (Versailles)', 'tel': '01.70.42.95.15'}], [{'name': 'Cazals Nicolas', 'position': 'Responsable des relations entreprises -', 'company': "Institut supérieur de l'environnement Versailles", 'tel': '01.30.68.09.10'}], [{'name': 'Rochery Laurence', 'position': 'Responsable des relations entreprises -', 'company': 'ESCEM école de management, campus de Tours', 'tel': '02.47.22.41.78'}], [{'name': 'Gautier Eric', 'position': 'Responsable des relations internationales -', 'company': 'UFR études arabes et hébraïques - faculté des lettres Paris (Sorbonne université)', 'tel': '01.40.46.25.15'}], [{'name': 'Boutroy Peggy', 'position': 'Responsable des relations internationales -', 'company': 'Lycée Baudimont-Saint-Charles Arras', 'tel': '03.21.16.18.00'}], [{'name': 'Gomme Isabelle', 'position': 'Responsable des relations entreprises -', 'company': 'Polytech Paris-Sud Orsay (Paris-Sud)', 'tel': '01.69.33.86.00'}], [{'name': 'Colas Jean-Marie', 'position': 'Responsable de la communication -', 'company': 'Supcréa Grenoble', 'tel': '04.76.87.74.75'}], [{'name': 'Aubrun Philippe', 'position': 'Responsable des relations entreprises -', 'company': 'Lycée Duplessis-Mornay Saumur', 'tel': '02.41.53.05.30'}], 'N/A', [{'name': 'Maunier Michel', 'position': 'Responsable de la communication -', 'company': 'ENSA Nice', 'tel': '04.92.07.73.91'}]]]
>>>len(clean_data)
50