Python web scraping - 如何在页面通过JS加载内容时获取资源?
Python web scraping - how to get resources with beautiful soup when page loads contents via JS?
所以我尝试使用 BeautifulSoup 和 urllib 从特定网站抓取 table。我的目标是根据 table 中的所有数据创建一个列表。我尝试使用来自其他网站的 tables 使用相同的代码,并且工作正常。然而,在这个网站上尝试它时 table returns 一个 NoneType 对象。有人可以帮我弄这个吗?我试过在网上寻找其他答案,但运气不佳。
代码如下:
import requests
import urllib
from bs4 import BeautifulSoup
soup = BeautifulSoup(urllib.request.urlopen("http://www.teamrankings.com/ncaa-basketball/stat/free-throw-pct").read())
table = soup.find("table", attrs={'class':'sortable'})
data = []
rows = table.findAll("tr")
for tr in rows:
cols = tr.findAll("td")
for td in cols:
text = ''.join(td.find(text=True))
data.append(text)
print(data)
该网站上的 table 是通过 javascript 创建的,因此当您将源代码直接扔到 BeautifulSoup 时并不存在。
要么你需要开始使用你选择的网络检查器,找出 javascript 从哪里获取数据 - 或者你应该使用 selenium
到 运行 一个完整的浏览器实例。
看起来此数据是通过 ajax 调用加载的:
您应该将 url 作为目标:http://www.teamrankings.com/ajax/league/v3/stats_controller.php
import requests
import urllib
from bs4 import BeautifulSoup
params = {
"type":"team-detail",
"league":"ncb",
"stat_id":"3083",
"season_id":"312",
"cat_type":"2",
"view":"stats_v1",
"is_previous":"0",
"date":"04/06/2015"
}
content = urllib.request.urlopen("http://www.teamrankings.com/ajax/league/v3/stats_controller.php",data=urllib.parse.urlencode(params).encode('utf8')).read()
soup = BeautifulSoup(content)
table = soup.find("table", attrs={'class':'sortable'})
data = []
rows = table.findAll("tr")
for tr in rows:
cols = tr.findAll("td")
for td in cols:
text = ''.join(td.find(text=True))
data.append(text)
print(data)
使用网络检查器,您还可以查看随 POST 请求一起传递的参数。
通常,另一端的服务器会检查这些值,如果您没有这些值中的一部分或全部,则拒绝您的请求。上面的代码片段 运行 对我来说很好。我切换到 urllib2
因为我通常更喜欢使用那个库。
如果数据在您的浏览器中加载,则可以抓取它。您只需要模仿您的浏览器发送的请求。
由于 table 数据是动态加载的,由于网络延迟等多种原因,更新 table 数据时会出现一些延迟。因此,您可以通过延迟并读取数据来等待时间。
检查 table 数据,即长度是否为空,如果是,则在延迟一段时间后读取 table 数据。这会有所帮助。
查看了您用过的url。由于您正在为 table 使用 class 选择器。确保它出现在 HTML
中的其他位置
所以我尝试使用 BeautifulSoup 和 urllib 从特定网站抓取 table。我的目标是根据 table 中的所有数据创建一个列表。我尝试使用来自其他网站的 tables 使用相同的代码,并且工作正常。然而,在这个网站上尝试它时 table returns 一个 NoneType 对象。有人可以帮我弄这个吗?我试过在网上寻找其他答案,但运气不佳。
代码如下:
import requests
import urllib
from bs4 import BeautifulSoup
soup = BeautifulSoup(urllib.request.urlopen("http://www.teamrankings.com/ncaa-basketball/stat/free-throw-pct").read())
table = soup.find("table", attrs={'class':'sortable'})
data = []
rows = table.findAll("tr")
for tr in rows:
cols = tr.findAll("td")
for td in cols:
text = ''.join(td.find(text=True))
data.append(text)
print(data)
该网站上的 table 是通过 javascript 创建的,因此当您将源代码直接扔到 BeautifulSoup 时并不存在。
要么你需要开始使用你选择的网络检查器,找出 javascript 从哪里获取数据 - 或者你应该使用 selenium
到 运行 一个完整的浏览器实例。
看起来此数据是通过 ajax 调用加载的:
您应该将 url 作为目标:http://www.teamrankings.com/ajax/league/v3/stats_controller.php
import requests
import urllib
from bs4 import BeautifulSoup
params = {
"type":"team-detail",
"league":"ncb",
"stat_id":"3083",
"season_id":"312",
"cat_type":"2",
"view":"stats_v1",
"is_previous":"0",
"date":"04/06/2015"
}
content = urllib.request.urlopen("http://www.teamrankings.com/ajax/league/v3/stats_controller.php",data=urllib.parse.urlencode(params).encode('utf8')).read()
soup = BeautifulSoup(content)
table = soup.find("table", attrs={'class':'sortable'})
data = []
rows = table.findAll("tr")
for tr in rows:
cols = tr.findAll("td")
for td in cols:
text = ''.join(td.find(text=True))
data.append(text)
print(data)
使用网络检查器,您还可以查看随 POST 请求一起传递的参数。
通常,另一端的服务器会检查这些值,如果您没有这些值中的一部分或全部,则拒绝您的请求。上面的代码片段 运行 对我来说很好。我切换到 urllib2
因为我通常更喜欢使用那个库。
如果数据在您的浏览器中加载,则可以抓取它。您只需要模仿您的浏览器发送的请求。
由于 table 数据是动态加载的,由于网络延迟等多种原因,更新 table 数据时会出现一些延迟。因此,您可以通过延迟并读取数据来等待时间。 检查 table 数据,即长度是否为空,如果是,则在延迟一段时间后读取 table 数据。这会有所帮助。
查看了您用过的url。由于您正在为 table 使用 class 选择器。确保它出现在 HTML
中的其他位置