【问题标题】:How to scrape website tables with varying values depending on the selections如何根据选择抓取具有不同值的网站表
【发布时间】:2020-12-29 14:02:04
【问题描述】:

我正在尝试刮:

https://id.investing.com/commodities/gold-historical-data 

2010-2020 的表格,但问题是默认日期和我选择的日期之间的链接仍然相同。那么如何告诉 python 从 2010 年到 2020 年抓取数据呢?请帮助我,我正在使用 python 3。

这是我的代码:

import requests, bs4

url = 'https://id.investing.com/commodities/gold-historical-data'
headers = {"User-Agent":"Mozilla/5.0"}
response = requests.get(url, headers=headers)
soup = bs4.BeautifulSoup(response.text, 'lxml')
tables = soup.find_all('table')

print(soup)

with open('emasfile.csv','w') as csv:
    for row in tables[1].find_all('tr'):
        line = ""
        for td in row.find_all(['td', 'th']):
            line += '"' + td.text + '",'
        csv.write(line + '\n')

【问题讨论】:

  • 首先检查网络浏览器是如何工作的 - 在您更改日期时,在 Chrome/Firefox 中使用 DevTools(标签 Network)查看从浏览器到服务器的所有请求。也许它在 URL 中使用了额外的数据。或者它使用带有额外数据的 POST 请求。或者它使用带有 AJAX 的 JavaScript 来发送发送额外数据的请求
  • 您很可能需要使用 post.request 而不是 get。这些链接应该会有所帮助:stackoverflow.com/questions/16390257/…stackoverflow.com/questions/53890493/…

标签: python pandas beautifulsoup screen-scraping


【解决方案1】:

此页面使用JavaScriptAJAX 从中获取数据

https://id.investing.com/instruments/HistoricalDataAjax

它发送带有额外数据的 POST 请求 - 开始日期和结束日期("st_date""end_date"

您可以尝试使用01/01/201012/31/2020,但我使用for-loop 来分别获取每一年。

我从 Chrome/Firefox 中的 DevTool(标签“网络”)获取所有信息。

import requests
from bs4 import BeautifulSoup
import csv

url = 'https://id.investing.com/instruments/HistoricalDataAjax'

payload = {
    "curr_id": "8830",
    "smlID": "300004",
    "header": "Data+Historis+Emas+Berjangka",
    "st_date": "01/30/2020",
    "end_date": "12/31/2020",
    "interval_sec": "Daily",
    "sort_col": "date",
    "sort_ord": "DESC",
    "action":"historical_data"
}

headers = {
    #"Referer": "https://id.investing.com/commodities/gold-historical-data",
    "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:80.0) Gecko/20100101 Firefox/80.0",
    "X-Requested-With": "XMLHttpRequest"
}

fh = open('output.csv', 'w')
csv_writer = csv.writer(fh)

for year in range(2010, 2021):
    print('year:', year)
    
    payload["st_date"] = f"01/01/{year}"
    payload["end_date"] = f"12/31/{year}"
    
    r = requests.post(url, data=payload, headers=headers)
    #print(r.text)
    
    soup = BeautifulSoup(r.text, 'lxml')
    table = soup.find('table')
    for row in table.find_all('tr')[1:]: # [1:] to skip header
        row_data = [item.text for item in row.find_all('td')]
        print(row_data)
        csv_writer.writerow(row_data)
        
fh.close()        

【讨论】:

  • 非常感谢!请问在哪里可以找到“smlID”:“300004”,?我在开发工具选项卡网络中找不到它。
  • 在 Firefox 中的标签 network 当您单击链接 id.investing.com/instruments/HistoricalDataAjax 时,它会在右侧显示详细信息 - 标题、cookie、请求数据、响应数据等。在请求数据中我可以看到我在payload 中使用的所有值。在 Chrome 中,当您单击 DevTools 中的链接时,它还应该显示详细信息。
  • 如果您检查 HTML,那么您还可以找到 <script> window.histDataExcessInfo = { pairId: 8830, smlId: 300004 }</script>,它可能更有用,因为页面可能为不同的用户使用不同的 smlId
  • 好的,我明白了!谢谢你,还有一个问题,当我将它导入到 mysql 时,我可以去掉行 bcs 之间的空格吗?它会使行变为空。如果我有太多问题,我很抱歉......
  • 我在 Linux 上没有任何问题,但在 Windows 上你可能需要open(..., newline='')。见CSV in Python adding an extra carriage return, on Windows
猜你喜欢
  • 1970-01-01
  • 2022-11-30
  • 2019-09-23
  • 1970-01-01
  • 2020-03-02
  • 1970-01-01
  • 1970-01-01
  • 2019-09-22
  • 1970-01-01
相关资源
最近更新 更多