I want to clean up scraped text from <dd>
and <dt>
, output looks like this:
Įrengimas:': 'Dalinė apdailaNAUDINGA:Interjero dizaineriai', 'Ypatybės:': 'Nauja kanalizacijaNauja elektros instaliacija',
My desired outputd:
Įrengimas:': 'Dalinė apdaila, 'Ypatybės:': 'Nauja kanalizacija, Nauja elektros instaliacija',
My code block, to get that text:
def get_dl(soup):
d_list = {}
for dl in soup.findAll("dl", {"class": "obj-details"}):
for el in dl.find_all(["dt", "dd"]):
if el.name == 'dt':
key = el.get_text(strip=True)
elif key in ['Plotas:', 'Buto numeris:', 'Metai:', 'Namo numeris:', 'Kambarių sk.:', 'Aukštas:', 'Aukštų sk.:', 'Pastato tipas:', 'Šildymas:', 'Įrengimas:', 'Pastato energijos suvartojimo klasė:', 'Ypatybės:', 'Papildomos patalpos:', 'Papildoma įranga:', 'Apsauga:']:
d_list[key] = el.get_text(strip=True)
return d_list
So, what is best practice to fix text in this situation ?
Adding full code, to see whole picture:
from selenium import webdriver
from bs4 import BeautifulSoup
import re
import csv
PATH = 'C:\Program Files (x86)\chromedriver.exe'
driver = webdriver.Chrome(PATH)
data = []
def get_dl(soup):
d_list = {}
for dl in soup.findAll("dl", {"class": "obj-details"}):
for el in dl.find_all(["dt", "dd"]):
if el.name == 'dt':
key = el.get_text(strip=True)
elif key in ['Plotas:', 'Buto numeris:', 'Metai:', 'Namo numeris:', 'Kambarių sk.:', 'Aukštas:', 'Aukštų sk.:', 'Pastato tipas:', 'Šildymas:', 'Įrengimas:', 'Pastato energijos suvartojimo klasė:', 'Ypatybės:', 'Papildomos patalpos:', 'Papildoma įranga:', 'Apsauga:']:
d_list[key] = el.get_text(strip=True)
return d_list
for puslapis in range(2, 3):
driver.get(f'https://www.aruodas.lt/butai/vilniuje/puslapis/{puslapis}')
response = driver.page_source
soup = BeautifulSoup(response, 'html.parser')
blocks = soup.find_all('tr', class_='list-row')
stored_urls = []
for url in blocks:
try:
stored_urls.append(url.a['href'])
except:
pass
for link in stored_urls:
driver.get(link)
response = driver.page_source
soup = BeautifulSoup(response, 'html.parser')
h1 = soup.find('h1', 'obj-header-text')
price = soup.find('div', class_ = 'price-left')
try:
address1 = h1.get_text(strip=True)
address2 = re.findall(r'(.*),[^,]*$', address1)
address = ''.join(address2)
city, district, street = address.split(',')
except:
address = 'NaN'
try:
full_price = price.find('span', class_ = 'price-eur').text.strip()
except:
full_price = 'NaN'
try:
price_sq_m = price.find('span', class_ = 'price-per').text.strip()
except:
price_sq_m = 'NaN'
try:
price_change = price.find('div', class_ = 'price-change').text.strip()
except:
price_change = 'NaN'
data.append({'city': city, 'district': district, 'street': street, 'full_price': full_price, 'price_sq_m': price_sq_m, 'price_change:': price_change, **get_dl(soup)})
for entry in data:
print(entry)
driver.quit()
CodePudding user response:
Labas. Is the "Naudinga" part the main issue, are there any other words/phrases that can occur? If not, try this.
#Replace your line code:
d_list[key] = el.get_text(strip=True)
#With this mess:
d_list[key] = ' '.join(el.text.strip().replace("\n", ", ").split('NAUDINGA')[0].split())
CodePudding user response:
If there is only a single string to replace()
shortest approach would be to go with get_text()
and its parameters to strip and join
/ separate bits by whitespace:
d_list[key] = el.get_text(' ', strip=True).replace(' NAUDINGA: Interjero dizaineriai','')
If there are multiple strings I would recommend to use stripped_strings
, what would nearly the same, and a list comprehension
to check / exclude unwanted strings:
d_list[key] = ' '.join([e for e in list(el.stripped_strings) if e not in ['NAUDINGA:','Interjero dizaineriai']])
Example based on your function
def get_dl(soup):
d_list = {}
for dl in soup.find_all("dl", {"class": "obj-details"}):
for el in dl.find_all(["dt", "dd"]):
if el.name == 'dt':
key = el.get_text(strip=True)
elif key in ['Plotas:', 'Buto numeris:', 'Metai:', 'Namo numeris:', 'Kambarių sk.:', 'Aukštas:', 'Aukštų sk.:', 'Pastato tipas:', 'Šildymas:', 'Įrengimas:', 'Pastato energijos suvartojimo klasė:', 'Ypatybės:', 'Papildomos patalpos:', 'Papildoma įranga:', 'Apsauga:']:
d_list[key] = ' '.join([e for e in list(el.stripped_strings) if e not in ['NAUDINGA:','Interjero dizaineriai']])
return d_list
Sample output:
{'Namo numeris:': '10', 'Plotas:': '35,08 m²', 'Kambarių sk.:': '2', 'Aukštas:': '1', 'Aukštų sk.:': '5', 'Metai:': '2022', 'Pastato tipas:': 'Mūrinis', 'Šildymas:': 'Centrinis kolektorinis', 'Įrengimas:': 'Dalinė apdaila', 'Pastato energijos suvartojimo klasė:': 'A ', 'Apsauga:': 'Šarvuotos durys Kodinė laiptinės spyna Vaizdo kameros'}
{'Namo numeris:': '10', 'Plotas:': '50,97 m²', 'Kambarių sk.:': '2', 'Aukštas:': '5', 'Aukštų sk.:': '5', 'Metai:': '2022', 'Pastato tipas:': 'Mūrinis', 'Šildymas:': 'Centrinis kolektorinis', 'Įrengimas:': 'Dalinė apdaila', 'Pastato energijos suvartojimo klasė:': 'A ', 'Papildomos patalpos:': 'Balkonas', 'Apsauga:': 'Šarvuotos durys Kodinė laiptinės spyna Vaizdo kameros'}
{'Namo numeris:': '10', 'Plotas:': '47,25 m²', 'Kambarių sk.:': '2', 'Aukštas:': '4', 'Aukštų sk.:': '5', 'Metai:': '2022', 'Pastato tipas:': 'Mūrinis', 'Šildymas:': 'Centrinis kolektorinis', 'Įrengimas:': 'Dalinė apdaila', 'Pastato energijos suvartojimo klasė:': 'A ', 'Papildomos patalpos:': 'Balkonas', 'Apsauga:': 'Šarvuotos durys Kodinė laiptinės spyna Vaizdo kameros'}
{'Namo numeris:': '55', 'Plotas:': '34,8 m²', 'Kambarių sk.:': '1', 'Aukštas:': '8', 'Aukštų sk.:': '9', 'Metai:': '1988', 'Pastato tipas:': 'Mūrinis', 'Šildymas:': 'Centrinis', 'Įrengimas:': 'Įrengtas', 'Ypatybės:': 'Nauja kanalizacija Nauja elektros instaliacija Internetas', 'Papildomos patalpos:': 'Sandėliukas Balkonas Drabužinė', 'Papildoma įranga:': 'Skalbimo mašina Su baldais Šaldytuvas Virtuvės komplektas Viryklė Plastikiniai vamzdžiai Indaplovė Dušo kabina', 'Apsauga:': 'Šarvuotos durys Signalizacija Kodinė laiptinės spyna'}
Just in case, you also can go with css selectors
to select your elements more specific:
def get_dl(soup):
d_list = {}
for el in soup.select('dl.obj-details dt:has( dd)'):
key = el.get_text(strip=True)
if key in ['Plotas:', 'Buto numeris:', 'Metai:', 'Namo numeris:', 'Kambarių sk.:', 'Aukštas:', 'Aukštų sk.:', 'Pastato tipas:', 'Šildymas:', 'Įrengimas:', 'Pastato energijos suvartojimo klasė:', 'Ypatybės:', 'Papildomos patalpos:', 'Papildoma įranga:', 'Apsauga:']:
d_list[key] = ' '.join([e for e in list(el.find_next('dd').stripped_strings) if e not in ['NAUDINGA:','Interjero dizaineriai']])
return d_list