I need to build a web-scraping tool for this page: https://www.valchov.cz/sluzby/specialni-sluzby-/
I already figured out how to get the "Vyvěšeno"
and "Sejmuto"
by using previous_sibling
, but now I need to get all the divs(into one variable). I think some if statement would help.
There are sometimes 1 and sometimes up to 3 divs above.
Sample from my current array:
['11.\xa0veřejné zasedání zastupitelstva obce se uskuteční 21.\xa012.\xa02011 v\xa019.30\xa0v\xa0budově obecního\xa0úřadu.', 'Vyvěšeno: 13. 12. 2011', 'Sejmuto: 21. 12. 2011']
Code:
from bs4 import BeautifulSoup
import requests
import re
from csv import writer
url= "https://www.valchov.cz/sluzby/specialni-sluzby-/"
page = requests.get(url)
soup = BeautifulSoup(page.content, "html.parser")
sejmuto = soup.find_all("p", string=re.compile("Sejmuto:"))
with open("listings.csv", "w", encoding="utf8") as f:
thewriter = writer(f)
header= ["Name", "Name bezdiakritikyamezer" , "URL", "Zveřejněno", "Sejmuto"]
thewriter.writerow(header)
for hhh in sejmuto:
item1 = hhh.previous_sibling.previous_sibling.text
itemz = hhh.previous_sibling.previous_sibling.previous_sibling.previous_sibling.text
item2 = (hhh.text)
item = [itemz, item1, item2]
print(item)
CodePudding user response:
To do that you can use pandas DataFrame
from bs4 import BeautifulSoup
import requests
import re
import pandas as pd
#from csv import writer
url= "https://www.valchov.cz/sluzby/specialni-sluzby-/"
page = requests.get(url)
soup = BeautifulSoup(page.content, "html.parser")
sejmuto = soup.find_all("p", string=re.compile("Sejmuto:"))
# with open("listings.csv", "w", encoding="utf8") as f:
# thewriter = writer(f)
# header= ["Name", "Name bezdiakritikyamezer" , "URL", "Zveřejněno", "Sejmuto"]
# thewriter.writerow(header)
items=[]
for hhh in sejmuto:
item1 = hhh.previous_sibling.previous_sibling.text.replace('\xa0','')
itemz = hhh.previous_sibling.previous_sibling.previous_sibling.previous_sibling.text.strip()
item2 = (hhh.text)
items.append({
"itemz":itemz,
"item1":item1,
"item2":item2})
df = pd.DataFrame(items)
#df.to_csv('data.csv',index=False)
print(df)
Output:
itemz ... item2
0 Zpráva o výsledku přezkumu hospodaření Svazku ... ... Sejmuto:
1 \nZpráva z přezkumu hospodaření za rok 2021 DS... ... Sejmuto:
2 Příloha č. 8 - Výkaz pro hodnocení plnění rozp... ... Sejmuto: 30. 6. 2022
3 Veřejná vyhláška - usnesení o stanovení lhůty ... ... Sejmuto: 25. 5. 2022
4 Porovnání všech položek výpočtu ceny podle cen... ... Sejmuto: 30. 5. 2022
.. ... ... ...
340 Návrh závěrečného účtu obce 2011 ... Sejmuto: 2. 4. 2012
341 Příloha návrhu závěrečného účtu obce 2011, Pří... ... Sejmuto: 2. 4. 2012
342 Záměr prodeje pozemku ... Sejmuto: 25. 3. 2012
343 12. veřejné zasedání ZO Valchov se uskuteční v... ... Sejmuto: 20. 2. 2012
344 11. veřejné zasedání zastupitelstva obce se us... ... Sejmuto: 21. 12. 2011
[345 rows x 3 columns]
CodePudding user response:
Question and expected output is not that clear but assuming, that your goal is to get all the links and apply corresponding dates I would reccomend to adjust your script that way:
You do not need extra
re
modul instead usecss selectors
:soup.select('p:-soup-contains("Sejmuto")')
Select and iterate all
find_previous_siblings()
, check if it contains a<a>
and write your row to csv else break the for loop and continue:for ps in e.find_previous('p').find_previous_siblings(): if ps.a: name = ps.a.text url = ps.a.get('href') zve = e.find_previous('p').text.split(':')[-1] sej = e.text.split('Sejmuto')[-1].strip('.:') item = [name, url, zve, sej] thewriter.writerow(item) elif 'Přílohy' in ps.text: continue else: break
Note There are some irregular and incorrect spellings / punctuation (":","." or no of these)
Example
from bs4 import BeautifulSoup
import requests
from csv import writer
url= "https://www.valchov.cz/sluzby/specialni-sluzby-/"
page = requests.get(url)
soup = BeautifulSoup(page.content, "html.parser")
with open("listings.csv", "w", encoding="utf8") as f:
thewriter = writer(f)
header= ["Name", "URL", "Zveřejněno", "Sejmuto"]
thewriter.writerow(header)
for e in soup.select('p:-soup-contains("Sejmuto")'):
for ps in e.find_previous('p').find_previous_siblings():
if ps.a:
name = ps.a.text
url = ps.a.get('href')
zve = e.find_previous('p').text.split(':')[-1]
sej = e.text.split('Sejmuto')[-1].strip('.:')
item = [name, url, zve, sej]
thewriter.writerow(item)
elif 'Přílohy' in ps.text:
continue
else:
break
Output
...