You need a cookie from the iframe loaded on the main page. You can get that by creating a requests session and ask for the main page, then the iframe app. That way you have the cookies and url needed to access the final leg of the road.
The following fetches the header and each row of the table:
import requests
from bs4 import BeautifulSoup
import json
with requests.Session() as sess:
# Get the data:
response = sess.get('http://www.wsj.com/mdc/public/npage/2_3023_creditdervs.html')
sess.get(BeautifulSoup(response.text, 'lxml').find('iframe').attrs['src'])
response = sess.post(
'https://web.apps.markit.com/AppsApi/GetIndexData',
data={'indexOrBond': 'bond', 'ClientCode': 'WSJ'}
)
table = BeautifulSoup(json.loads(response.text)['html'], 'lxml').find('table', {'id': 'BondIndexTable'})
header = [cell.text for cell in table.find('thead').find_all('tr')[-1].find_all('th')]
data = list()
for row in table.find_all('tr'):
row = [cell.text for cell in row.find_all('td')]
if len(row) > 2:
data.append(row)
# Do something with the data:
print(header)
for row in data:
print(row)
This produces:
['Bond Indexes', 'Daily', 'Monthly', 'YTD', '1Y', '3Y']
['Markit iBoxx USD Overall', '0.18%', '0.41%', '3.45%', '-0.60%', '8.98%']
['Markit iBoxx USD Treasuries', '0.20%', '0.46%', '2.60%', '-2.26%', '7.56%']
['Markit iBoxx USD Liquid Investment Grade Index', '0.17%', '0.47%', '5.62%', '1.54%', '14.07%']
['Markit iBoxx USD Liquid High Yield Index', '-0.07%', '0.00%', '5.55%', '9.85%', '14.23%']
['Markit iBoxx EUR Overall', '0.13%', '0.50%', '0.15%', '-2.25%', '8.67%']
['Markit iBoxx EUR Corporates', '0.09%', '0.40%', '1.79%', '0.67%', '8.79%']
['Markit iBoxx EUR Sovereigns', '0.15%', '0.60%', '-0.24%', '-3.29%', '9.68%']
['Markit iBoxx GBP Overall', '0.68%', '0.66%', '2.00%', '-0.80%', '23.18%']
['Markit iBoxx GBP Corporates', '0.55%', '0.57%', '4.13%', '2.95%', '24.88%']
['Markit iBoxx GBP Gilts', '0.74%', '0.72%', '1.36%', '-2.03%', '23.39%']
['Markit iBoxx Asia', '0.00%', '-0.02%', '2.23%', '-1.00%', '8.27%']
['Markit iBoxx Global Inflation-Linked Index All USD', '0.58%', '0.71%', '-0.45%', '-0.63%', '9.81%']
['Markit iBoxx GEMX USD', '0.06%', '0.10%', '2.70%', '1.44%', '6.92%']
['Markit iBoxx USD Corporates', '0.16%', '0.39%', '4.96%', '1.92%', '11.88%']
This can be used with pandas or some other tool for data manipulation:
import pandas as pd
df = pd.DataFrame(data, columns=header)
for col in df.columns:
if col != 'Bond Indexes':
df[col] = pd.to_numeric(df[col].replace(regex=True, to_replace='%', value=''))/100
print(df)