我正在尝试从“ https://data.lacity.org/A-Safe-City/Crime-Data-from-2010-to-Present/y8tr-7khq”抓取网页。具体来说,在div class =“ socrata-table Frozen-columns”下,所有数据列名称和数据列描述。但是,我编写的代码似乎不起作用(它不返回任何内容?)
import requests
from bs4 import BeautifulSoup
url = "https://data.lacity.org/A-Safe-City/Crime-Data-from-2010-to-Present/y8tr-7khq"
page = requests.get(url)
print(page.status_code)
soup=BeautifulSoup(page.content,'html.parser')
for col in soup.find_all("div", attrs={"class":"socrata-visualization-container loaded"})[0:1]:
for tr in col.find_all("div",attrs={"class":"socrata-table frozen-columns"}):
for data in tr.find_all("div",attrs={"class":"column-header-content"}):
print(data.text)
我的代码错误吗?
答案 0 :(得分:2)
页面是动态加载的,数据集是分页的,这意味着使用浏览器自动化来检索,这很慢。您可以使用一个API。它具有允许您批量返回结果的参数。
阅读API文档here。这将是一种更高效,更可靠的数据检索方式。
使用limit
确定一次检索的#条记录;使用offset
参数开始下一批新记录。示例调用在这里。
由于这是一个查询,您实际上可以像对SQL查询一样检索其他参数来检索所需的结果集。这也意味着您可能可以编写一个非常快速的初始查询来从数据库中返回记录计数,该记录可用于确定批处理请求的终点。
您可以编写基于类的脚本,该脚本使用多处理并更有效地抓取这些批处理。
import requests
import pandas as pd
from pandas.io.json import json_normalize
response = requests.get('https://data.lacity.org/api/id/y8tr-7khq.json?$select=`dr_no`,`date_rptd`,`date_occ`,`time_occ`,`area_id`,`area_name`,`rpt_dist_no`,`crm_cd`,`crm_cd_desc`,`mocodes`,`vict_age`,`vict_sex`,`vict_descent`,`premis_cd`,`premis_desc`,`weapon_used_cd`,`weapon_desc`,`status`,`status_desc`,`crm_cd_1`,`crm_cd_2`,`crm_cd_3`,`crm_cd_4`,`location`,`cross_street`,`location_1`&$order=`date_occ`+DESC&$limit=100&$offset=0')
data = response.json()
data = json_normalize(data)
df = pd.DataFrame(data)
print(df)
JSON响应中的示例记录:
答案 1 :(得分:0)
如果查看页面源代码(ctrl + U),您会发现没有<div class = "socrata-table frozen-columns">
这样的元素。这是因为您要剪贴的内容是动态添加到页面中的。查看以下问题:web scraping dynamic content with python或Web scraping a website with dynamic javascript content
答案 2 :(得分:0)