【问题标题】:Python - webscraping; dictionary data structurePython - 网页抓取;字典数据结构
【发布时间】:2016-07-12 10:22:49
【问题描述】:

我需要抓取这个网站 (http://setkab.go.id/profil-kabinet/#) 并生成一个 Excel 文件,其中第 1 列的标题为“内阁名称”,第 2 列的标题为“时代”。这意味着每个内阁名称(例如 Kabinet Presidensil、Kabinet Sjahrir I ) 应该有其自己的行 - 与其各自的时代(例如 Era Revolusi Fisik、Era Republik Indonesia Serikat)一起。

这是我得到的最接近的:

import requests
from bs4 import BeautifulSoup

response = requests.get('http://setkab.go.id/profil-kabinet/#')
soup = BeautifulSoup(response.text, 'html.parser')

eras = soup.find_all('div', attrs={'class':"wpb_accordion_section group"})

setkab = {}
for element in eras: 
    setkab[element.a.get_text()] = {}

for element in eras:
    cabname = element.find('div',attrs={'class':'wpb_wrapper'}).get_text()
    setkab[element.a.get_text()]['cbnm'] = cabname

for item in setkab.keys():
    print item + setkab[item]['cbnm']

import os, csv
os.chdir("/Users/mxcodes/Code")

with open("setkabfinal.csv", "w") as toWrite:
    writer = csv.writer(toWrite, delimiter=",")
    writer.writerow(["Era", "Cabinet name"])
    for a in setkab.keys():
        writer.writerow([a.encode("utf-8"), setkab[a]["cbnm"]])

但是,这会创建一个 Excel 文件,其中第 1 列和第 2 列中的标题分别为“Era”和“Cabinet names”。它未能将每个内阁名称放在 单独的 行中。例如,它在第 1 列中有“Era Revolusi Fisik”,并在第 2 列中列出所有橱柜一起

我的猜测是,我需要以某种方式切换键值对,以便每个机柜都成为键,而它的时代成为它的价值——因为目前情况正好相反。但我已经尝试过,但没有成功。有什么帮助吗?谢谢!

【问题讨论】:

    标签: python-2.7 dictionary web-scraping beautifulsoup key-value


    【解决方案1】:

    据我所知,您用于写入的 cabinets[a]["cbnm"] 变量只是一个很长的 Unicode,所以当您执行 writer.writerow([a.encode("utf-8"), cabinets[a]["cbnm"]]) 时,实际发生的情况是您在第一列中写入了时代,而整个 Unicode 在下一列中的单个单元格(即使您的字符串中有\n,它也不会阻止它被写入单个单元格(csv 实际上认为您希望 unicode 仅位于一个单元格中,因此它将"cabinets[a]["cbnm"] 值之前和之后,以确保它实际上会在一个单元格中)),将每个cabinet 值写入另一行中应该做的是对每个所需的行分别使用writerow 方法。 例如这段代码对我来说很好用:

    cabinets = setkab 
    with open("cabinets.csv", "w") as toWrite:
        writer = csv.writer(toWrite, delimiter=",")
        writer.writerow(["Era", "Cabinet name"])
        for a in setkab.keys():
            writer.writerow([a.encode("utf-8")])  #write the era column
            cabinets_list = [i for i in cabinets[a]["cbnm"].split('\n') if i != '']  #get all the values that are separated by newline chars (if they aren't empty strings)
            for i in cabinets_list: writer.writerow([a.encode("utf-8"),i])   #write every value separately in the CABINET NAME row
    

    如您所见,我只更改了最后 3 行。

    希望对你有帮助!

    【讨论】:

    • 感谢您的帮助!该代码确实在单独的行中给出了内阁名称 - 这就是我想要的。但它并没有在相邻的列中给出每个内阁的时代类型——这也是我需要的。换句话说,“时代”列应该有单独的行但重复的时代类型; “内阁名称”列应该有单独的行,但内阁名称是唯一的。目前,“时代”列只有 6 个唯一行。有什么建议吗?
    • @mxcodes 当然,我已经更新了代码(基本上 - 而不是做 writer.writerow(['',i])(在内阁列旁边创建一个空列)我们将这样做writer.writerow([a.encode("utf-8"),i])
    猜你喜欢
    • 1970-01-01
    • 2020-09-26
    • 2021-01-12
    • 1970-01-01
    • 1970-01-01
    • 2021-10-01
    • 1970-01-01
    • 2014-11-10
    • 1970-01-01
    相关资源
    最近更新 更多