<div class="maxi calendar_month"> 包含一个 HTML <table>,该表包含行 (<tr>),每行包含列 (td)。每列包含两个相邻的 div,第一个仅包含表示月份中的日期的数字,第二个 div 看起来像这样:<div class="a_collection"> 或 <div class="two_collection">,具体取决于给定中是否有一行或多行据我所知,细胞。第二个 div 出现在所有单元格中,即使是那些没有任何内容的单元格,例如“垃圾”或“花园垃圾”。但是,如果存在此类内容,则此 div 包含其他一些 div,并且您要查找的文本位于其中一个中。这是我想出的:
def main():
from bs4 import BeautifulSoup
import requests
url = "https://shropshire.gov.uk/waste/binday/index.jsc?p=0&go=Go&designation=3&postcode=sy3+9jt&gobutton=Go"
response = requests.get(url)
response.raise_for_status()
soup = BeautifulSoup(response.content, "html.parser")
def get_table_as_dict(table):
date_div = table.select_one("tr.month")
month = date_div.select_one("th").find(text=True).strip().lower()
year = date_div.select_one("span.year").get_text(strip=True)
yield "month", month
yield "year", year
def get_days():
for cell in table.select("td:not(.empty)"):
day_number = cell.select_one("div:nth-child(1)").get_text(strip=True)
content_divs = cell.select_one("div:nth-child(2) ").select("div:not([class*=\"print\"])")
if content_divs:
content = ", ".join(text for text in [content_div.find(text=True).strip() for content_div in content_divs])
else:
content = ""
yield day_number, content
yield "days", dict(get_days())
for table in soup.findAll("table"):
print(dict(get_table_as_dict(table)))
return 0
if __name__ == "__main__":
import sys
sys.exit(main())
输出:
{'month': 'june', 'year': '2020', 'days': {'1': '', '2': '', '3': '', '4': 'Rubbish', '5': '', '6': '', '7': '', '8': '', '9': '', '10': '', '11': 'Garden waste, Recycling boxes', '12': '', '13': '', '14': '', '15': '', '16': '', '17': '', '18': 'Rubbish', '19': '', '20': '', '21': '', '22': '', '23': '', '24': '', '25': 'Garden waste, Recycling boxes', '26': '', '27': '', '28': '', '29': '', '30': ''}}
{'month': 'july', 'year': '2020', 'days': {'2': 'Rubbish', '9': 'Garden waste, Recycling boxes', '16': 'Rubbish', '23': 'Garden waste, Recycling boxes', '30': 'Rubbish'}}
{'month': 'august', 'year': '2020', 'days': {'6': 'Garden waste, Recycling boxes', '13': 'Rubbish', '20': 'Garden waste, Recycling boxes', '27': 'Rubbish'}}
>>>
get_table_as_dict 是一个生成键值对的生成器,以便稍后您可以使用并折叠生成器以创建整个字典。我们在一个循环中执行此操作,该循环遍历 HTML 中的所有表,因此最后我们有三个字典,一个用于页面上的每个日历表/月。
get_days 也是一个生成键值对的生成器。它在get_table_as_dict 的第三个也是最后一个收益中产生其所有内容。基本上,我们使用 CSS 选择器遍历当前表中的所有单元格 - 遍历所有类不是“空”的 td 元素(表有时有 tds 和 class="empty" 来填充表在一个月的最后一天之后有更多的单元格,而这些单元格是我们不想要的。我们没有指定我们想要的单元格,而是指定我们不想要的单元格,因为我们想要的是那些在工作日登陆的单元格,没有课,周末登陆的单元格有class="weekend")。
一旦我们有了当前的有效单元格,我们就会得到第一个直接子 div,并且只获取它包含的直接文本,然后将其剥离 - 这是作为字符串的日期编号。
然后,我们创建一个content_divs 列表。这些代表了单元格中可能存在的潜在 div。有些单元格没有内容,有些单元格中有一个相关项(例如,“垃圾”),有些 div 中甚至有两个相关项(“花园垃圾”和“回收箱”)。我们通过选择当前单元格的第二个 div 子项来获取这些 div,并从该 div 中选择所有其类不包含子字符串“print”的子 div(无论出于何种原因,这些烦人的冗余 div 都存在,但我们没有对它们感兴趣)。