【问题标题】:how Iterate each link to scrape all dataframe inside HTML?如何迭代每个链接以抓取 HTML 中的所有数据框?
【发布时间】:2021-09-29 08:16:41
【问题描述】:

我正在通过链接列表抓取一个网站,总共 442 个链接。在每个链接中都有数据框,通过使用 pd.read_html() 我设法拉出数据框。所以我尝试循环所有链接并抓取所有数据框并加入它们,但是在完成所有操作后,我发现某些链接的数据框位置不同,我无法提取数据框。我该如何解决这个问题。很抱歉,如果我无法清楚地解释它,但这是我的脚本:

allin = []

for link in titlelink :
    driver.get(link)
    html = driver.page_source
    soup = bs(html, 'html.parser')
    iframe = soup.find('iframe')['src']
    #open iframe
    openiframe = driver.get(iframe)
    iframehtml = driver.page_source
    print('fetching --',link)
    #using pandas read html ang get table
    All = pd.read_html(iframehtml)
    try :
        table1 = All[1].set_index([0, All[1].groupby(0).cumcount()])[1].unstack(0)
    except :
        table1 = All[2].set_index([0, All[2].groupby(0).cumcount()])[1].unstack(0)
    try :
        table2 = All[3].set_index([0, All[3].groupby(0).cumcount()])[1].unstack(0)
    except :
        pass
    df = table1.join(table2)
    try :
        df['Remarks'] = All[2].iloc[1]
    except :
        df['Remarks'] = All[3].iloc[1]
    allin.append(df)
    
finaldf = pd.concat(allin, ignore_index=True)
print(finaldf)
finaldf.to_csv('data.csv', index=False)

另外,我已将所有链接导出到 csv 并附在此处(https://drive.google.com/file/d/1Tk2oKVEZwfxAnHIx3p2HbACE6vOrJq5A/view?usp=sharing),以便您更清楚地了解我所面临的问题。感谢您的所有帮助。

【问题讨论】:

  • 您想将Proposed company name,Remarks,Announcement Info 合并为一个DataFrame
  • @Xitiz 是的,但是它的某些链接具有额外的功能,即“Admission Sponsor”和“Sponsor”
  • 你也想在你的最终df中添加它吗?
  • @Xitiz 是的,我想在最终的 df 中添加所有内容,包括额外的功能

标签: python pandas dataframe selenium beautifulsoup


【解决方案1】:

我在链接中发现了一些模式,所以我尝试了这个,现在它工作正常。不是 100% 完美,但它正在工作,95%。代码如下:

import pandas as pd
import requests

df=pd.read_csv("link.csv") # That google drive document

links=df["0"].values.tolist()

for link in links:
    nlink=f"https://disclosure.bursamalaysia.com/FileAccess/viewHtml?e={link.split('ann_id=')[1]}"
    page=requests.get(nlink,headers={"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.1 Safari/605.1.15"})
    df=pd.read_html(page.text)
    df=pd.concat(df[1:],axis=0).to_numpy().flatten()
    
    df=pd.DataFrame(df[~pd.isna(df)].reshape(-1,2))
    # For explanation about these last two line you may check here https://stackoverflow.com/questions/68479177/how-to-shift-a-dataframe-element-wise-to-fill-nans
    print(df)

您必须根据需要更改大部分内容。如果您需要任何帮助,您可以在评论中提问。从技术上讲,这不是一个完整的答案,但它可以加快你的抓取速度,也可以提供你想要的输出,但并不完全。您可以将其作为解决问题 90% 到 95% 的建议和想法。

【讨论】:

    【解决方案2】:

    一直在尝试和错误,最后,我得到了我自己问题的答案。这是脚本

    frame = []
    
    for link in titlelink :
        time.sleep(1)
        driver.get(link)
        html = driver.page_source
        soup = bs(html, 'html.parser')
        iframe = soup.find('iframe')['src']
        #open iframe
        openiframe = driver.get(iframe)
        iframehtml = driver.page_source
        print('fetching --',link)
        #using pandas read html ang get table
        df_proposed_company_name = pd.read_html(iframehtml,  match='Proposed company name')[0]
        df_announcement_info = pd.read_html(iframehtml, match='Stock Name ')[0]
       
        try:
            df_remarks = pd.read_html(iframehtml, match='Remarks :')[0].iloc[1]
        except:
            pass
        
        try : 
            df_Admission_Sponsor = pd.read_html(iframehtml, match='Admission Sponsor')[1]
        except :
            pass
    
        
        try:
            t1_1 = df_Admission_Sponsor.set_index([0,df_Admission_Sponsor.groupby(0).cumcount()])[1].unstack(0)
        except:
            t1_1 = pd.DataFrame({'Admission Sponsor':np.nan,
                               'Sponsor':np.nan},index=[0])
        t1_2 = df_proposed_company_name.set_index([0, df_proposed_company_name.groupby(0).cumcount()])[1].unstack(0)
        t3 = df_announcement_info.set_index([0, df_announcement_info.groupby(0).cumcount()])[1].unstack(0)
    
        dfs = t1_1.join(t1_2).join(t3)
        try:
            dfs['remarks'] = df_remarks
        except:
            dfs['remarks'] = np.nan
            
        frame.append(dfs)
        
    finaldf = pd.concat(frame, ignore_index=True)
    # print(finaldf)
    finaldf.to_csv('data.csv', index=False)
    

    如果你们中的任何人有更先进的经验和更好的解决方案,我愿意接受并向你们学习新事物:-)

    【讨论】:

    • 我的回答不适合你吗,你什么都没回应!请让我知道它是否有效。
    • @Xitiz 是的,它运作良好,感谢您的帮助
    猜你喜欢
    • 2017-03-21
    • 1970-01-01
    • 2023-03-20
    • 2021-04-17
    • 2020-03-05
    • 2021-09-25
    • 2017-10-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多