Python 如何从HTML中获取特定表

Python 如何从HTML中获取特定表,python,html,web-scraping,Python,Html,Web Scraping,我们有几家公司的10-k表格。我们想从HTML中获取收益表(第6项)。公司的形式结构发生了变化 例如 url1= 'https://www.sec.gov/Archives/edgar/data/794367/000079436719000038/m-0202201910xk.htm' url2='https://www.sec.gov/Archives/edgar/data/885639/000156459019009005/kss-10k_20190202.htm' 我们需要得到第6项合

我们有几家公司的10-k表格。我们想从HTML中获取收益表(第6项)。公司的形式结构发生了变化

例如

url1= 'https://www.sec.gov/Archives/edgar/data/794367/000079436719000038/m-0202201910xk.htm' 
url2='https://www.sec.gov/Archives/edgar/data/885639/000156459019009005/kss-10k_20190202.htm'
我们需要得到第6项合并财务数据中的表格

我们尝试的一种方法是基于对项目6的字符串搜索,获取从项目6到项目7的所有文本,然后获取如下表格:

doc10K=requests.get(url2)
st6=doc10K.text.lower().find(“第6项”)
end6=doc10K.text.lower().find(“第7项”)
#获取项目6的文本并删除货币符号
item6=doc10K.text[st6:end6]。替换(“$”,“”)
Tsoup=bs.beautifulsou(第6项“lxml”)
#从响应中提取所有表
html\u tables=Tsoup.find\u all('table'))

这种方法并不适用于所有形式。例如,对于KSS,我们无法找到字符串“Item6”。理想的输出是第6项中给出的表格。

字符串
第6项
似乎包含空格或不间断空格

请尝试以下代码:

import requests
from bs4 import BeautifulSoup

url1= 'https://www.sec.gov/Archives/edgar/data/794367/000079436719000038/m-0202201910xk.htm' 
url2='https://www.sec.gov/Archives/edgar/data/885639/000156459019009005/kss-10k_20190202.htm'

doc10K = requests.get(url2)

st6 = doc10K.text.lower().find("item 6")

# found "item 6"? if not search search with underscore
if st6 == -1:
    st6 = doc10K.text.lower().find("item_6") 

end6 = doc10K.text.lower().find("item 7")
item6 = doc10K.text[st6:end6].replace('$','')
soup = BeautifulSoup(item6, 'lxml')
html_tables = soup.find_all('table')

彼得苏黎世是对的,但标记没有完全定位

# You can try this, too. The start parameter can be a list, just match any one of the above
doc10K = requests.get(url2)

from simplified_scrapy.simplified_doc import SimplifiedDoc 
doc = SimplifiedDoc(doc10K.text)
start = doc.html.rfind('Selected Consolidated Financial Data')
if start<0:
  start = doc.html.rfind('Selected Financial Data')

tables = doc.getElementsByTag('table',start=start,end=['Item 7','Item&#160;7'])
for table in tables:
  trs = table.trs
  for tr in trs:
    tds = tr.tds
    for td in tds:
      print(td.text)
      # print(td.unescape()) #Replace HTML entity
#你也可以试试这个。start参数可以是一个列表,只需匹配上面的任意一个即可
doc10K=请求.get(url2)
从simplified_scrapy.simplified_doc导入SimplifiedDoc
doc=SimplifiedDoc(doc10K.text)
start=doc.html.rfind('选定的合并财务数据')

如果使用bs4 4.7.1+启动,则可以使用:contains和:has为基于html的表指定适当的匹配模式。您可以使用css或语法来匹配下面显示的两种模式中的任何一种

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

urls = ['https://www.sec.gov/Archives/edgar/data/794367/000079436719000038/m-0202201910xk.htm','https://www.sec.gov/Archives/edgar/data/885639/000156459019009005/kss-10k_20190202.htm']

with requests.Session() as s:
    for url in urls:
        r = s.get(url)
        soup = bs(r.content, 'lxml')
        table = pd.read_html(str(soup.select_one('table:contains("Item 6") ~ div:has(table) table, p:contains("Selected Consolidated Financial Data") ~ div:has(table) table')))[0]
        table.dropna(axis = 0, how = 'all',inplace= True)
        table.dropna(axis = 1, how = 'all',inplace= True)
        table.fillna(' ', inplace=True)
        table.rename(columns= table.iloc[0], inplace = True) #set headers same as row 1
        table.drop(table.index[0:2], inplace = True)  #lose row 1
        table.reset_index(drop=True, inplace = True) #re-index
        print(table)

如果你的问题解决了,将其中一个答案标记为已接受。在这一点上,它不会得到表格中的部分,因为内容表格中也有“第6项”。如果内容表存在,我们需要忽略它。我们需要将输出作为一个表,由@qharr完成,这取决于它失败的原因。章节标题和表格似乎没有固定的模式。我的方法是,您至少可以扩展css,或者为标题、标题与表格之间的关系添加其他模式。虽然这对这两种模式很有效,但不能推广到其他URL,例如,您能用“选择一个”来解释这一部分吗,这将有助于修复和推广select_one返回在()中传递的css模式的第一个匹配项。该模式是为匹配您的表而编写的。我使用Or语法指定了两个模式,因此两个模式都是匹配的。这是因为不能对两个URL使用相同的模式,因为title和table之间的关系不同,并且包含title的元素也不同。