如何在具有多个表的网页上调用特定表

时间:2019-07-05 16:46:39

标签: python indexing web-scraping beautifulsoup

我正在尝试从该网站https://www.wsj.com/market-data上的特定表中提取信息。到目前为止,这是我的代码。我是python的新手,以防它不明显。我只想提取“债券”表中的信息。我可以为表建立索引,以便通过索引#调用特定的表吗?

from selenium import webdriver
from bs4 import BeautifulSoup
import requests
browser=webdriver.Chrome
chrome_path=r"C:\Users\ddai\AppData\Local\Programs\Python\Python37\chromedriver.exe"
driver=webdriver.Chrome(chrome_path)
url2="https://wsj.com/market-data"
driver.get(url2)
html=driver.execute_script("return document.documentElement.outerHTML")
sel_soup=BeautifulSoup(html,'html.parser') 
print(len(sel_soup.findAll("table"))) 

3 个答案:

答案 0 :(得分:1)

可以。您有几种解决方法。我想您发布的代码将获取页面的完整HTML,如果是这样,您可以使用它。在页面上,如果使用的是Chrome,请按F12 -可以查看完整的HTML(或仅使用Python进行打印并使用gander)。

选择1:以“债券”为名的抓斗桌

看看DOM的组织方式-名称“ Bonds”是表的表亲,使其与表关联起来有些棘手。大大简化的布局:

<div>
    <div>
        <h3><span>Bonds</span></h3>
    </div>
    <article></article>
    <div class="WSJTables--tableWrapper--2oPULowO WSJBase--card--3gQ6obvQ ">
        <table class="WSJTables--table--1SdkiG8p WSJTheme--table--2a-shks_ ">
            <thead class="WSJTables--table__head--hprNkLrs WSJTheme--table__head--3n6NRMJE ">

该表和名称“ Bonds”共享祖父母。您可以使用正则表达式来查找标题绑定(类似<h(?<hNum>[1-6]).*>.*Bonds.*</h\k<hNum>>),然后通过查找<table.*>的下一个实例或使用某些DOM映射工具来查找脚本中的下一个表这样您就可以上到祖父母那里,然后缩小到桌子旁。然后,您可以找到完整的,华丽的HTML表格形式的表格,然后从那里进行解析。这种方法也许是最可靠的,因为您搜索的名称可以更改为找到其他任何表。

或者,您也可以按表的类名搜索表,该表名看起来是唯一的,但不能保证如此,因此可以进行硬编码。


选项2:建立索引

在索引方法中,您可以找到所有<table.*>.*?</table>,循环遍历并将它们分配给数组。但是,您可能需要对所需的表索引进行硬编码:如果bond表是要索引的第五张表,则必须将其引用为table[5],这不理想。如果这是用于简单且临时的程序,或者页面将长时间保持相对静态,则此方法可以正常工作,并且相对简单。但是,如果页面的布局完全改变了,或者您的程序需要动态化,那么可能值得他努力构建更可靠的方法。

答案 1 :(得分:0)

一旦您选择了所需标题所在的容器的标题,其余的操作就很容易了。您还可以仅使用请求从脚本标签获取表,然后使用json()对内容进行后期处理。但是,请尝试下面的脚本以使用硒获取表格内容。

from selenium import webdriver
from bs4 import BeautifulSoup

with webdriver.Chrome() as driver:
    driver.get("https://wsj.com/market-data")
    sel_soup = BeautifulSoup(driver.page_source,'html.parser') 
    for items in sel_soup.select_one("[class*='card__header']:contains(Bonds)").find_parent().select("table tr"):
        data = [item.get_text(strip=True) for item in items.select("th,td")]
        print(data)

输出:

['Country', 'Yield(%)', 'Yield Chg']
['U.S. 10 Year', '2.040', '0.090']
['Germany 10 Year', '-0.362', '0.034']
['U.K. 10 Year', '0.739', '0.059']
['Japan 10 Year', '-0.163', '-0.008']
['Australia 10 Year', '1.293', '-0.010']
['China 10 Year', '3.176', '-0.012']

答案 2 :(得分:0)

您可以使用另一个端点,单击查看“绑定”页面时,可以在“网络”选项卡中找到该端点。返回的json可以被解析以检索表。这样返回的信息比您提供的url显示的信息略多,但包含您需要的信息。

import requests
from bs4 import BeautifulSoup as bs
import pandas as pd
import re

def get_bond_info(r):
    data = r['data']['instruments']
    results = []
    for item in data:
        results.append(
        {'Name': item['djLegalName'],
         'CPN (%)': item['couponPercent'],
         'LATEST SPREAD OVER TREASURY': item['spread'],
         'YLD (%)': item['yieldPercent'],
         'YLD CHG': item['yieldChange']
        }
        ) 
    df = pd.DataFrame(results, columns = ['Name', 'CPN (%)', 'Spread','YLD (%)','YLD CHG' ])
    return df

identifier = '''{"application":"WSJ",
                "bonds":[
                    {"symbol":"TMUBMUSD10Y","name":"U.S."},
                    {"symbol":"TMBMKDE-10Y","name":"Germany"},
                    {"symbol":"TMBMKGB-10Y","name":"U.K."},
                    {"symbol":"TMBMKJP-10Y","name":"Japan"},
                    {"symbol":"TMBMKAU-10Y","name":"Australia"},
                    {"symbol":"AMBMKRM-10Y","name":"China"},
                    {"symbol":"TMBMKNZ-10Y","name":"New Zealand"},
                    {"symbol":"TMBMKFR-10Y","name":"France"},
                    {"symbol":"TMBMKIT-10Y","name":"Italy"},
                    {"symbol":"TMBMKES-10Y","name":"Spain"}
                ]
             }'''


url = 'https://www.wsj.com/market-data/bonds?id=' + re.sub('\n\s+','',identifier) + '&type=mdc_governmentbonds'
r = requests.get(url).json()
print(get_bond_info(r))

如果您熟悉结构,则可以检索其他信息,例如不同的时间段

import requests
from bs4 import BeautifulSoup as bs
import pandas as pd

url = 'https://www.wsj.com/market-data/bonds?id={"application":"WSJ","instruments":[{"symbol":"BOND/BX//TMUBMUSD30Y","name":"30-Year Bond"},{"symbol":"BOND/BX//TMUBMUSD10Y","name":"10-Year Note"},{"symbol":"BOND/BX//TMUBMUSD07Y","name":"7-Year Note"},{"symbol":"BOND/BX//TMUBMUSD05Y","name":"5-Year Note"},{"symbol":"BOND/BX//TMUBMUSD03Y","name":"3-Year Note"},{"symbol":"BOND/BX//TMUBMUSD02Y","name":"2-Year Note"},{"symbol":"BOND/BX//TMUBMUSD01Y","name":"1-Year Bill"},{"symbol":"BOND/BX//TMUBMUSD06M","name":"6-Month Bill"},{"symbol":"BOND/BX//TMUBMUSD03M","name":"3-Month Bill"},{"symbol":"BOND/BX//TMUBMUSD01M","name":"1-Month Bill"}]}&type=mdc_quotes'
r = requests.get(url).json()
data = r['data']['instruments']
results = []
for item in data:
    results.append(
    {'Name': item['formattedName'],
     'CPN (%)': item['bond']['couponRate'],
     'PRC CHG': item['bond']['formattedTradePriceChange'],
     'YLD (%)': item['bond']['yield'],
     'YLD CHG': item['bond']['yieldChange']
    }
    )

df = pd.DataFrame(results, columns = ['Name', 'CPN (%)', 'PRC CHG','YLD (%)','YLD CHG' ])
print(df)