首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Webscraping -尝试提取一些数据,但在最后一关卡住了

Webscraping -尝试提取一些数据,但在最后一关卡住了
EN

Stack Overflow用户
提问于 2021-06-18 23:43:42
回答 3查看 129关注 0票数 4

我已经设法公开了正确的数据(其中一些数据是在页面中动态计算的,所以比我想象的要复杂一些),但现在我需要将其放入JSON字符串中,尽管尝试了很多次,我还是卡住了!

Python脚本如下所示(使用Selenium和BeautifulSoup):

代码语言:javascript
复制
from bs4 import BeautifulSoup
from selenium import webdriver
import datetime
from dateutil import parser
import requests
import json

url = 'https://www.braintree.gov.uk/bins-waste-recycling/route-3-collection-dates/1'

browser = webdriver.Chrome(executable_path = r'C:/Users/user/Downloads/chromedriver.exe')
browser.get(url)


html = browser.execute_script("return document.getElementsByTagName('html')[0].innerHTML")
soup = BeautifulSoup(html, "html.parser")

data=soup.find_all("div", {"class":"date_display"})
#print(data)
#out = {}


for data in data:
    bin_colour = data.find('h3').text
    bin_date = parser.parse(data.find('p').text).strftime('%Y-%m-%d')
    print(bin_colour)
    print(bin_date)
    print()

browser.quit()

这将导致:

代码语言:javascript
复制
Grey Bin 

2021-06-30
   
Green Bin

2021-06-23
   
Clear Sack

2021-06-23

Food Bin

2021-06-23

这可能(可能)不是最好的代码/方法,所以我对您的建议持开放态度。我们的主要目标是:

代码语言:javascript
复制
{"Grey Bin": "2021-06-30", "Green Bin": "2021-06-23", "Clear Sack": "2021-06-23", "Food Bin": "2021-06-23"}

希望这是有意义的,我已经尝试了各种方法将数据转换为正确的格式,但似乎在尝试了很多小时后都失去了一切,希望你们能提供帮助。

更新:MendelG的两个解决方案都工作得很好。Vitalis的解决方案提供了四个输出,最后一个是所需的输出-所以感谢你们提供了非常快速和有效的解决方案-我接近了,但看不到树的木头!

EN

回答 3

Stack Overflow用户

发布于 2021-06-19 00:20:30

要获取字典格式的数据,您可以尝试:

代码语言:javascript
复制
out = {}
for data in tag:
    out[data.find("h3").text] = parser.parse(data.find("p").text).strftime("%Y-%m-%d")

print(out)

或者,使用字典理解:

代码语言:javascript
复制
print(
    {
        data.find("h3").text: parser.parse(data.find("p").text).strftime("%Y-%m-%d")
        for data in tag
    }
)

输出:

代码语言:javascript
复制
{'Grey Bin': '2021-06-30', 'Green Bin': '2021-06-23', 'Clear Sack': '2021-06-23', 'Food Bin': '2021-06-23'}
票数 2
EN

Stack Overflow用户

发布于 2021-06-19 00:27:22

您可以创建一个空字典,在其中添加值并打印它。

解决方案

代码语言:javascript
复制
from bs4 import BeautifulSoup
from selenium import webdriver
import datetime
from dateutil import parser
import requests
import json

url = 'https://www.braintree.gov.uk/bins-waste-recycling/route-3-collection-dates/1'

browser = webdriver.Chrome(executable_path='/snap/bin/chromium.chromedriver')
browser.get(url)


html = browser.execute_script("return document.getElementsByTagName('html')[0].innerHTML")
soup = BeautifulSoup(html, "html.parser")

data = soup.find_all("div", {"class":"date_display"})

result = {}

for item in data:
    bin_colour = item.find('h3').text
    bin_date = parser.parse(item.find('p').text).strftime('%Y-%m-%d')
    result[bin_colour]=bin_date

print(result)

输出

代码语言:javascript
复制
{'Grey Bin': '2021-06-30', 'Green Bin': '2021-06-23', 'Clear Sack': '2021-06-23', 'Food Bin': '2021-06-23'}

如果需要list格式的输出,也可以采用类似的方法,但需要对值进行.append操作,就像我在这里使用Trouble retrieving elements and looping pages using next page button一样

如果需要双引号,请使用下面的打印命令:

代码语言:javascript
复制
print(json.dumps(result))

它将打印:

代码语言:javascript
复制
{"Grey Bin": "2021-06-30", "Green Bin": "2021-06-23", "Clear Sack": "2021-06-23", "Food Bin": "2021-06-23"}
票数 1
EN

Stack Overflow用户

发布于 2021-06-19 01:33:40

您可以使用requestsre收集所有列出的日期。您可以对包含每种集合类型日期的各种JavaScript对象进行正则表达式。然后,您需要将每个月的值加1,才能得到1-12范围内的月份;这可以通过regex命名组来完成。可以将这些日期转换为实际日期,以便以后进行筛选。

最初将所有日期存储在字典中,集合类型为key,收集日期列表为values,您可以使用zip_longest创建一个DataFrame。然后,您可以使用筛选来查找给定集合的下一个集合日期。

我使用了几个助手函数来实现这一点。

代码语言:javascript
复制
import requests
from dateutil import parser
from datetime import datetime
from pandas import to_datetime, DataFrame
from itertools import zip_longest

def get_dates(dates):
    dates = [re.sub(r'(?P<g1>\d+),(?P<g2>\d+),(?P<g3>\d+)$', lambda d: parser.parse('-'.join([d.group('g1'), str(int(d.group('g2')) + 1), d.group('g3')])).strftime('%Y-%m-%d'), i) 
             for i in re.findall(r'Date\((\d{4},\d{1,2},\d{1,2}),', dates)] 
    dates = [datetime.strptime(i, '%Y-%m-%d').date() for i in dates]
    return dates

def get_next_collection(collection, df):
    return df[df[collection] >= to_datetime('today')][collection].iloc[0]
    
collection_types = ['grey', 'green', 'clear', 'food']
r = requests.get('https://www.braintree.gov.uk/bins-waste-recycling/route-3-collection-dates/1')
collections = {}

for collection in collection_types:   
    dates = re.search(r'var {0}(?:(?:bin)|(?:sack)) = (\[.*?\])'.format(collection), r.text, re.S).group(1)
    collections[collection] = get_dates(dates) 

df = DataFrame(zip_longest(collections['grey'], collections['green'], 
                           collections['clear'], collections['food']),
               columns = collection_types)

get_next_collection('grey', df)

您还可以使用生成器和@Martijn Pieters 详细介绍的islice来直接处理字典条目(保存收集日期),并限制您感兴趣的未来日期,例如

代码语言:javascript
复制
filtered = (i for i in collections['grey'] if i >= date.today())
list(islice(filtered, 3))

修改后的导入行包括:

代码语言:javascript
复制
from itertools import zip_longest, islice
from datetime import datetime, date

这样您就不需要导入pandas或创建DataFrame了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68038019

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档