【问题标题】:Incomplete data after scraping a website for Data抓取网站数据后数据不完整
【发布时间】:2018-08-15 06:08:58
【问题描述】:

我正在使用 Python 进行一些网络抓取,但在提取表值时遇到了一些问题。例如,我有兴趣从http://www.etf.com/etfanalytics/etf-finder 中抓取 ETF 值。下面是我试图从中删除值的表的快照。

这是我试图在抓取中使用的代码。

#Import packages
import pandas as pd
import requests

#Get website url and get request
etf_list = "http://www.etf.com/etfanalytics/etf-finder"
etf_df = pd.read_html(requests.get(etf_list, headers={'User-agent': 
'Mozilla/5.0'}).text)


#printing the scraped data to screen 
print(etf_df)

# Output the read data into dataframes
for i in range(0,len(etf_df)):
    frame[i] = pd.DataFrame(etf_df[i])
    print(frame[i])

我有几个问题。

  • 表格仅包含 20 个条目,而网站上每个表格的总条目应为 2166 个条目。如何修改代码以提取所有值?
  • 从站点抓取后,某些数据帧无法正确分配。例如,frame[0] 的输出不是数据帧格式,当尝试在 Python 控制台下查看为 DataFrame 时,没有看到 frame[0] 的任何内容。但是,打印到屏幕时似乎很好。如果我使用 beautifulSoup 来分阶段 HTML 会更好吗?

【问题讨论】:

  • 忘记添加了。这是在pycharm IDE下用python 3.6编写的。

标签: python html web-scraping


【解决方案1】:

您只会得到 20 行表格,因为默认情况下 html 页面上只有 20 行。查看页面的源代码,您正在尝试解析。可能有一个可能的解决方案来遍历分页直到结束,但是分页是用 JS 实现的,它没有反映在 URL 中,所以我看不到,如何直接访问表格的下一页。

好像有请求

http://www.etf.com/etf-finder-funds-api//-aum/100/100/1

在该页面上,当我尝试加载第二组 100 行时。但是,如果可能的话,访问该 URL 可能会非常棘手。也许对于这个特定的站点,您应该使用一些东西,例如 C# 中的 WebBrowser(我不知道它在 python 中会是什么,但我确信 python 可以做任何事情)。您将能够模仿浏览器并执行javascript。

编辑:我已尝试在您提供的页面控制台中运行下一个 JS 代码。

jQuery.ajax({
  url: "http://www.etf.com/etf-finder-funds-api//-aum/0/3000/1", 
  success: function(data) {
    console.log(JSON.parse(data));
  }
});

它记录了一个包含所有 2166 个对象的数组,代表您正在查找的表行。自己试试看结果。看起来在请求 url 中“0”是一个起始索引,“3000”是一个限制。

但是,如果您从其他域尝试此操作,您将得到 403 Forbidden。这是因为他们有一个Referer 标头检查。

再次编辑 正如@stranac 所提到的,设置该标题很容易。只需将其设置为 http://www.etf.com/etfanalytics/etf-finder 即可享受。

【讨论】:

  • 似乎比预期的要复杂。我可以在 Python 中使用 Java 包装器来进行查询吗?但我不知道如何编写代码。
  • 我已经稍微编辑了我的答案。不幸的是,我没有使用 python 或 java 的经验,所以我无法回答有关 Java 包装器的问题。我希望经过编辑的信息会有所帮助。
  • 我的错,我在尝试设置Referer时做错了,所以它不起作用。查看@stranac 的回答
【解决方案2】:

正如 Alex 所指出的,该网站从 http://www.etf.com/etf-finder-funds-api//-aum/0/3000/1 请求数据,它会检查 Referer 标头以查看是否允许您查看。

但是,Alex 说您无法更改标题是错误的。
事实上,使用requests 发送自定义标头非常容易:

>>> r = requests.get('http://www.etf.com/etf-finder-funds-api//-aum/0/3000/1', headers={'Referer': 'http://www.etf.com/etfanalytics/etf-finder'})
>>> data = r.json()
>>> len(data)
2166

此时,data 是一个包含您需要的所有数据的 dict,pandas 可能有一种将其加载到数据框中的简单方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-18
    • 1970-01-01
    • 2014-07-06
    • 2021-10-26
    • 2018-07-01
    • 1970-01-01
    相关资源
    最近更新 更多