微信公众号导出的文章统计数据xlsx 文档结构如下。需要用到的数据第6行起,第1列是标题及链接,第3列是发表日期。
php方式解构excel文档已经做过了,最近都是拿python练手,顺便就试试在py中完成这个任务

excel导出公众号数据.png

下文无特别说明是python3.x代码,需要跳过弯路看正确解决方案的的直接跳到最后方案

尝试用 xlrd

能在python读excel文档的组件有很多。xlrd 是python官方的支持读取xls及xlsx格式,所以首选。

安装

pip install xlrd

读取xlsx文件代码

import xlrd

def readxlxs(file, sheet_index=0):
    workbook = xlrd.open_workbook(file)
    # 按索引读取工作表
    sheet = workbook.sheet_by_index(sheet_index)
    print("工作表名称:", sheet.name)
    print("行数:", sheet.nrows)
    print("列数:", sheet.ncols)

    # 按工作表名称读取数据
    # second_sheet = workbook.sheet_by_name("b")
    # print("Second sheet Rows:", second_sheet.nrows)
    # print("Second sheet Cols:", second_sheet.ncols)
    # 获取单元格的数据
    # cell_value = sheet.cell(1, 0).value
    # print("获取第2行第1列的单元格数据:", cell_value)
    data = []
    for i in range(0, sheet.nrows):
        data.append(sheet.row_values(i))
    return data

xls = readxlxs("sample.xlsx")
for idx_row in range(5,len(xls)):
    row = xls[idx_row]
    print("date, title:", row[2], row[0])

这是从别人博客抄过来的,读取没有问题..emm好像缺少了什么,readxlsx()只返回单元格的内容 sheet.cell(r, o).value 不包含链接数据。

基于上文源码改进成以下版本


import xlrd
xls = xlrd.open_workbook("sample.xlsx", formatting_info=True)
sht = xls.sheet_by_index(0)
for row in range(5, sht.nrows):
    rval = sht.row_values(row, start_colx=0, end_colx=2)
    atitle = rval[0]
    adate = rval[2]
    alink = sht.hyperlink_map.get((row, 0))
    url = None if link is None else link.url_or_path
    print("date, title, link:", adate, atitle, url)

但是这个却报错
NotImplementedError: formatting_info=True not yet implemented

搜索原因,被大神告知 open_workbook 方法打开第二参数 formatting_info 不支持 xlsx 格式,晴天霹雳。

xlrd cannot read the hyperlink without formatting_info, which is currently not supported for xlsx.
https://stackoverflow.com/questions/16676727/extracting-hyperlinks-from-excel-xlsx-with-python

被建议的解决办法是,把文档转换格式为 xls
word是旧转新,excel被要求新转旧,真的不安逸。

不妥协,放弃xlrd 继续看其他的解决办法

改尝试 openpyxl

安装

依然简单

pip install openpyxl

代码


import openpyxl
xls = openpyxl.load_workbook('sample.xlsx')
sht_names = xls.get_sheet_names() #获取所有sheet页名字
sht = xls.get_sheet_by_name(sht_names[0]) #第一页
for row in range(5, sht.max_row): #第五行开始是正文
    atitle = sht.cell(row, 0).value
    adate = sht.cell(row, 2).value    
    alink = sht.cell(row, 0).hyperlink.target

    print("date, title, link:", adate, atitle, alink)

除了最大行数,读单元格值的方法名称略有改变外代码和上文xlrd的改动不大, 但是报错有两处需要注意
ValueError: Row or column values must be at least 1
翻了一下文档,openpyxl 对行与列的定位下标从1开始算,与Office中的显示保持一致。

另外 sht.cell(row, col).hyperlink.target 这种方法也需要进行处理,当单元格不包含链接时
hyperlink 对象值为 None, 如果仍直接取 target的话会报错
AttributeError: 'NoneType' object has no attribute 'target'

最后方案

依然使用 openpyxl ,对上一个代码的错误进行小修正


import openpyxl
xls = openpyxl.load_workbook('sample.xlsx')
sht_names = xls.get_sheet_names() #获取所有sheet页名字
sht = xls.get_sheet_by_name(sht_names[0]) #第一页
for row in range(6, sht.max_row+1): #第五行开始是正文
    atitle = sht.cell(row, 1).value
    adate = sht.cell(row, 3).value
    alink = None if sht.cell(row, 1).hyperlink is None else sht.cell(row, 1).hyperlink.target
    print("date, title, link:", adate, atitle, alink)

#尝试从一个没有链接的单元格取链接
noLinkObj = sht.cell(6, 2).hyperlink
noLink = None if noLinkObj is None else noLinkObj.target
print("no link:", noLink)

效率一般般,1800行左右的数据用了大约6秒。

任务完成,睡觉。

标签: python, excel, xlrd, openpyxl, xlsx

添加新评论