为啥我不能从动态网页中抓取表格
Posted
技术标签:
【中文标题】为啥我不能从动态网页中抓取表格【英文标题】:Why I can not scrape a table from a dynamic web page为什么我不能从动态网页中抓取表格 【发布时间】:2021-09-10 22:24:56 【问题描述】:import requests
from bs4 import BeautifulSoup
import pandas as pd
url = "https://ntr.tourism.government.bg/CategoryzationAll.nsf/mn.xsp"
page = requests.get(url)
soup = BeautifulSoup(page.text,'lxml')
print(soup)
data = []
table = soup.find('table', 'class':'table table-striped table-hover mnastaniavane dataTable no-footer')
table_body = table.find('tbody')
rows = table_body.find_all('tr')
for row in rows:
cols = row.find_all('td')
cols = [ele.text.strip() for ele in cols]
data.append([ele for ele in cols if ele])
这是网页:https://ntr.tourism.government.bg/CategoryzationAll.nsf/mn.xsp 我想为某个特定位置的大学项目搜索所有酒店(例如瓦尔纳 - 该位置使用西里尔语)。我找到了源代码并描述了确切的表格 - 但我无法从其中刮取任何行/元素等。 请问有什么推荐吗!? 虽然目前有很多信息我没有找到有用的代码来刮表
【问题讨论】:
【参考方案1】:数据来自 Ajax 请求,因此您只需执行 ajax 请求,不必渲染页面,这样更快。
例如这是页面 20 行中的前 4 列:
import requests
url = "https://ntr.tourism.government.bg/CategoryzationAll.nsf/api/data/collections/name/vRegistarMNValid?sortcolumn=CNumber&sortorder=ascending&ps=20&page=0&_=1624898715559"
rows = requests.get(url).json() # list of the 20 rows, rows are dict.
# Uncomment to see all the columns title.
# print(rows[0].keys())
for row in rows:
print(row["CNumber"], row["TOSubType1"], row["TOName"], row["TOCity"])
输出:
0000000012 Семеен хотел Семеен хотел "ХЕЛГА" Горна Митрополия
00001 Къща за гости "ЛИДИЯ" Батак
00001 Стаи за гости самостоятелни стаи к-с "Барите" Чернево
00001 Стаи за гости СТАИ ЗА ГОСТИ "ГОРХИМ" Рила
00001 Стаи за гости СТАИ ЗА ГОСТИ Брестовица
00001 Къща за гости Къща за гости - ловен и селски туризъм Хърсово
00001 Хотел Иглен Ъглен
00001 Къща за гости РЕЛАКС/RELAX/ Батак
00001 Къща за гости Батак
00001 Къща за гости ВИЛИ-ПЕТЯ № 1 Батак
00001 Къща за гости "Форест Лодж" Банско
00001 Къща за гости "ОМД" ООД Земен
00001 Стаи за гости Дунавска перла Попина
00001 Къща за гости КЪЩА ЗА ГОСТИ "БЛАГОВЕСТА" Илинденци
00001 Стаи за гости Георгиевата къща Генерал Кантарджиево
00001 Къща за гости "Дунковата къща" Падала
000011 Къща за гости Гостилица Гостилица
00002 Стаи за гости Стаи за гости Загражден
00002 Апартаменти за гости апартамент за гости №15 в жилищна сграда ,Мърфис Лодж" Банско
00002 Къща за гости ВИЛИ-ПЕТЯ № 2 Батак
【讨论】:
非常感谢您的快速响应,Dorian!我不敢相信。你能告诉我你是如何用 API 来打开这个 url 的:ntr.tourism.government.bg/CategoryzationAll.nsf/api/data/… 然后我可能可以自己从下拉菜单(城市、床位数等)中提取我需要的特定目的地的信息.) 使用您提供的算法,我将仅添加更多列再次尊重本课! | 不客气。一般来说,动态网页数据可以嵌入到脚本标签中,或者来自 ajax 请求 (XHR) 或 Websocket (WS),如果有双向通信。因此,您可以使用浏览器检查器查看网络活动并找到 api url。希望对您有所帮助。 我从开发者工具管理并从顶部的下拉菜单中选择了网络选项!剩下的就是将其保存在数据框中并导出为 csv!保持安全,多利安! 您能告诉我应该使用哪种方法将抓取的数据保存在 DataFrame 中吗?我尝试在 DataFrame 中转换数组,但无法创建准备保存在 csv 中的 DataFrame【参考方案2】:您可以使用selenium(python库)从动态生成数据的网页中抓取数据,您可以从here下载chrome驱动
from bs4 import BeautifulSoup
import pandas as pd
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
options.add_argument('--headless')
driver = webdriver.Chrome("path/to/chromedriver", options=options)
url = "https://ntr.tourism.government.bg/CategoryzationAll.nsf/mn.xsp"
driver.get(url)
table_confirm = WebDriverWait(driver, 20).until(
ec.presence_of_element_located((By.ID, "mnastaniavane"))
)
page_source = driver.page_source
soup = BeautifulSoup(page_source,'lxml')
print(soup)
data = []
table = soup.find('table', 'class':'table table-striped table-hover mnastaniavane dataTable no-footer')
table_body = table.find('tbody')
rows = table_body.find_all('tr')
for row in rows:
cols = row.find_all('td')
cols = [ele.text.strip() for ele in cols]
data.append([ele for ele in cols if ele])
【讨论】:
谢谢你 Ahmed 我相信它会对我有很大帮助 - 我稍后会安装 chrome 驱动程序,因为我需要更多时间并尝试你的方法 - 然后大概我可以抓取任何页面从带有所选标准的下拉菜单中指出!再次非常感谢你!以上是关于为啥我不能从动态网页中抓取表格的主要内容,如果未能解决你的问题,请参考以下文章
使用 Python 抓取网页动态内容(动态 HTML/Javascript 表格)