此文章为作者原创,如转载请先联系作者。
一、任务描述
如下图(excel表截图,输出示例.xlsx):
现需要从上图V列“参考文献”里提取出从N列到U列(除Q列以外,Q列文献期的内容不存在)
二、思考
第一步,观察数据
以参考文献下的第一个数据为例:
首先观察到双引号里的内容是“文献题目”,“1990”是文献年,”Acker, Joan”是文献作者,“Gender and Society”是文献期刊,4是文献卷,139-58中139是文献起始页,58是页数,则文献结束页就是197。
当然这是理想的情况,扫视一遍数据,发现还是有很多不属于这个格式的。
像下面几种数据
Acker, Joan. 2006. Class Questions: Feminist Answers.
Lanham, MD: Rowman & Littlefíeld.
这样的数据大概有两三个。他们是没有文献卷和文献起始页和页数的,有的文献题目还不在双引号内。
Charles, Maria and David B. Grusky. 2007. “Egalitari-
anism and Gender Inequality.” Pp. 327-42 in The
Inequality Reader: Contemporary and Foundational
Readings in Race, Class, and Gender, edited by D.
Grusky and S. Szelényi. Boulder, CO: Westview Press.
这样的完全不同格式的数据只有这一个。
总之,大部分数据还是符合最开始的那种格式,大体把数据的当做第一种,之后为了让程序能够运行,再稍作处理。
第二步,构思提取方法。
这样的分词工具在github上有很多开源的。
如:用于中文分词的jieba(https://github.com/hosiet/jieba)
用于中英文等多种语言的Stanford corenlp(https://github.com/stanfordnlp/CoreNLP)
后面这个我测试了一下,识别能力真的特别强,功能强大,用于自然语言处理比较多,虽然说我这个任务用不着。(在线测试网址:corenlp.run)——以第一条数据为例
特别提醒:corenlp-python接口不支持windows系统(我也是试了很久发现不支持)
思路:
re是python的一个模块
对excel的操作是用pandas模块
- re.findall提取双引号之间的内容——得到文献题目(不考虑特殊数据,程序正常运行)
- re.sub想办法去除双引号及双引号里的内容,得到余下部分内容text
- re.sub(“\D”,”“, string)提取余下部分内容text中所有的数字,取前四个数字即文献年。
- 得到文献年第一个数字在余下部分内容text中的索引,文献年之前的内容都是作者名,对text进行切片即可
- 提取文献年后的内容(对text进行切片),得到的内容finalText包括文献期刊和文献起始页和页数的(如果有的话)
- re.sub(“\d”, “”,finalText)提取除数字以外的字符串即文献期刊(如果有的话,可以不用判断,没有就不会输出)
- 由于前面提到有几个特殊的数据,(他们是没有文献卷和文献起始页和页数的)所以这里在提取数字的时候要进行判断一下
- bool(re.search(r’\d’, finalText))判断一下finalTetx里是否是数字
- 如果有的话,对finalText进行re.split(r’[:,\s])’切割,得到一个列表,列表的后两项即是“4”,“139-58 ”(以第一个数据为例子)
- “139-58 ”可以用spit(”-“)分离
以上为大体思路,事实上,才运行时,由于之前提到的有一些特殊数据,导致了程序不能运行,只能通过一些条件处理,把它过滤。
最终结果为如下:
完整代码如下:
#encoding=utf-8
import pandas as pd
import re
df = pd.read_excel("./data/输出示例.xlsx")
rf = df["参考文献"]
for i in range(0,90):
# 提取T列文献题目
t = re.findall('"([^"]+)"', rf.iat[i])
T = ','.join(t)
df.iat[i, 19] = T
#去除双引号中的内容
text = re.sub('"([^"]+)"', "", rf.iat[i])
# 提取O列文献年
totalCount = re.sub("\D", "", text)
newNumber = totalCount[0:4]
df.iat[i, 14] = newNumber
#提取N列文献作者
opsition = text.index(newNumber)
author = text[0:opsition]
df.iat[i, 13] = author
#提取文献年后的内容(此时双引号及双引号里的内容也没有)
finalText = text[opsition + 1 + len(newNumber):]
#提取U列文献期刊,如果有的话
journal = re.sub("\d", "", finalText)
df.iat[i, 20] = journal
if bool(re.search(r'\d', finalText)):
finalNumber = re.split(r'[: ,\s]', finalText)
# print(finalNumber)
# 提取P列文献卷
last1 = finalNumber[-2]
try:
float(last1)
df.iat[i, 15] = last1
except ValueError:
df.iat[i, 15] = 0
#提取文献起始页和结束页
last2 = finalNumber[-1]
if bool(re.search(r'\d', last2)):
start = last2.split("-")[0]
end1 = last2.split("-")[-1]
end2 = int(end1.strip(".")) + int(start)
df.iat[i, 17] = start
df.iat[i, 18] = end2
else:
pass
else:
pass
df.to_excel("./data/test.xlsx")