【问题标题】:Scraping table data with BeautifulSoup or Pandas使用 BeautifulSoup 或 Pandas 抓取表数据
【发布时间】:2021-02-28 07:23:52
【问题描述】:

我对使用 python 有点陌生,我被分配了一项需要从表中抓取数据的任务。我也不太了解html。我以前从未这样做过,并且花了几天时间研究各种刮桌子的方法。不幸的是,所有的例子似乎都是一个比我正在处理的更简单的网页布局。我尝试了很多不同的方法,但都没有让我选择我需要的表格数据。

如何在以下网页底部的“每日水位”标签下抓取表格?

网址 = https://apps.wrd.state.or.us/apps/gw/gw_info/gw_hydrograph/Hydrograph.aspx?gw_logid=HARN0052657

我已尝试使用以下链接中的方法,其他未在此处显示:

Beautiful Soup Scraping table

Scrape table with BeautifulSoup

Web scraping with BeautifulSoup

我尝试过的一些脚本:

from bs4 import BeautifulSoup
import requests

html = requests.get(url).text
soup = BeautifulSoup(html, "html.parser")
data = soup.find_all("table")  # {"class": "xxxx"})  

我也尝试过使用 pandas,但我不知道如何选择我需要的表格,而不是网页上具有基本井信息的第一个表格:

import pandas as pd
df_list = pd.read_html(url)
df_list

不幸的是,当我运行这个脚本时,我需要的数据甚至没有显示出来,而且我试图选择的表没有一个类,我可以用它来只选择那个表而不是基本的表信息。我检查了网页,但似乎找不到找到正确餐桌的方法。

就最终结果而言,我需要将其导出为 csv 或 pandas 数据框,以便我可以将其与建模的地下水数据绘制成图表以进行比较。任何建议将不胜感激!

【问题讨论】:

  • 我不会刮这个,我会寻找源数据库
  • 你想只废弃每日水位标签吗?
  • @anon01 虽然您的评论并没有那么有帮助,但它确实证实了我对这项任务的感受,并且老实说让我感觉更好,为什么我在努力取得任何进展,哈哈!

标签: python-3.x pandas web-scraping beautifulsoup


【解决方案1】:

尝试以下使用 python 的方法 - requests 简单、直接、可靠、快速且在处理请求时需要更少的代码。在检查了谷歌浏览器的网络部分后,我从网站本身获取了 API URL。

下面的脚本到底在做什么:

  1. 首先,它将获取 API URL 并使用动态参数(大写字母)执行 GET 请求,您可以更改 Well No、Start 和 end date 的值以获得所需的结果。

  2. 获取数据后脚本会使用json.loads库解析JSON数据。

  3. 它将遍历每日水位数据列表并创建所有数据点的列表,以便可用于创建 CSV 文件,例如:- GW Login Id、GW Site ID、Land Surface Elevation , 记录日期等。

  4. 最后它会将所有标题和数据写入 CSV 文件。 (!重要的是请确保在file_path变量中输入文件路径)

     import json
     import requests
     from urllib3.exceptions import InsecureRequestWarning
     requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
     import csv
    
     def scrap_daily_water_level():
    
     file_path = '' #Input File path here
     file_name = 'daily_water_level_data.csv' #File name
    
     #CSV headers
     csv_headers = ['Line #','GW Log Id','GW Site Id', 'Land Surface Elevation', 'Record Date','Restrict to OWRD only', 'Reviewed Status', 'Reviewed Status Description', 'Water level ft above mean sea level', 'Water level ft below land surface'] 
     list_of_water_readings = []
    
     #Dynamic Params
     WELL_NO = 'HARN0052657'
     START_DATE = '1/1/1905'
     END_DATE = '12/30/2050'
    
     #API URL
     URL = 'https://apps.wrd.state.or.us/apps/gw/gw_data_rws/api/' + WELL_NO + '/gw_recorder_water_level_daily_mean_public/?start_date=' + START_DATE + '&end_date=' + END_DATE + '&reviewed_status=&restrict_to_owrd_only=n'
    
     response = requests.get(URL,verify=False) #GET API call
     json_result = json.loads(response.text) #JSON loads to parse JSON data
    
     print('Daily water level data count ',json_result['feature_count']) # Prints no. of data counts
     extracted_data = json_result['feature_list'] #Extracted data in JSON form
    
     for idx, item in enumerate(extracted_data): #Iterate over the list of extracted data
         list_of_water_readings.append({ #append and create list of data with headers for further usage
                                     'Line #': idx + 1, 
                                     'GW Log Id' : item['gw_logid'],
                                     'GW Site Id': item['gw_site_id'],
                                     'Land Surface Elevation': item['land_surface_elevation'], 
                                     'Record Date': item['record_date'],
                                     'Restrict to OWRD only': item['restrict_to_owrd_only'],
                                     'Reviewed Status':item['reviewed_status'],
                                     'Reviewed Status Description': item['reviewed_status_description'],
                                     'Water level ft above mean sea level': item['waterlevel_ft_above_mean_sea_level'],
                                     'Water level ft below land surface': item['waterlevel_ft_below_land_surface']
                                     })
     #Create CSV and write data in to it.
     with open(file_path + file_name ,'a+') as daily_water_level_data_CSV: #Open file in a+ mode 
         csvwriter = csv.DictWriter(daily_water_level_data_CSV, delimiter=',', lineterminator='\n',fieldnames=csv_headers)
         print('Writing CSV header now...')
         csvwriter.writeheader() #Write headers in CSV file
         for item in list_of_water_readings: #iterate over the appended data and save them in to the CSV file.
             print('Writing data rows now..')
             print(item)            
             csvwriter.writerow(item)
    
     scrap_daily_water_level()
    

【讨论】:

  • 嗨@Vin,感谢您抽出宝贵时间提供这个深入的答案!!!难怪我为什么很难取得任何进展。一切都按预期工作。我也非常喜欢您添加变量的方式,这将允许我通过更改 GW 日志 ID 来选择其他井来提取类似数据。杰出的!一个快速的问题,重新格式化日期列以使其不包含时间戳 (2017-08-04T00:00:00) 的最佳方法是什么?
猜你喜欢
  • 2021-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多