首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python:在关键字前后抓取文本

Python:在关键字前后抓取文本
EN

Stack Overflow用户
提问于 2014-08-13 02:51:31
回答 3查看 638关注 0票数 1
代码语言:javascript
复制
keywords = ("banana", "apple", "orange", ...)
before = 50
after = 100
TEXT = "a big text string,  i.e., a page of a book"

for k in keywords:
    if k in TEXT:
        #cut = portion of text starting 'beforeText' chars before occurrence of 'k' and ending 'afterText' chars after occurrence of 'k'
        #finalcut = 'cut' with first and last WORDS trimmed to assure starting words are not cut in the middle

伙计们,你能帮我在上面的例子中编写cutfinalcut字符串变量吗?

什么是最有效的解决方案,考虑到我正在处理的大文本,众多的网页和可能超过20个关键字的搜索?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-08-13 03:18:33

可以使用re.finditer在字符串中找到所有匹配项。每个匹配对象都有一个start()方法,您可以使用它来计算字符串中的位置。您也不需要检查键是否在字符串中,因为然后finditer返回一个空迭代器:

代码语言:javascript
复制
keywords = ("banana", "apple", "orange", ...)
before = 50
after = 100
TEXT = "a big text string,  i.e., a page of a book"

for k in keywords:
    for match in re.finditer(k, TEXT):
        position = match.start()
        cut = TEXT[max(position - before, 0):position + after] # max is needed because that index must not be negative
        trimmed_match = re.match("\w*?\W+(.*)\W+\w*", cut, re.MULTILINE)
        finalcut = trimmed_match.group(1)

正则表达式将所有内容修剪到并包括第一个非单词字符序列,以及所有来自和包括最后一个非单词字符序列的内容(如果文本中有换行符,我添加了re.MULTILINE )。

票数 3
EN

Stack Overflow用户

发布于 2014-08-13 03:23:19

你需要调整你的算法。正如所写的,它是O(n*m),n是关键字的#,m是文本的长度。这不会有很好的规模。

相反:

  • keywords成为set,而不是tuple。您只关心针对keywords的成员资格测试,并且设置成员资格测试为O(1)。
  • 您需要标记TEXT。这比仅仅执行split()要复杂一些,因为您还需要处理删除标点符号/换行的操作。
  • 最后,使用“滑动窗口”迭代器在令牌上迭代3块。如果中间令牌位于keywords集中,则获取其周围的令牌并继续执行。

就这样。所以,一些伪代码:

代码语言:javascript
复制
keywords = {"banana", "apple", "orange", ...}
tokens = tokenize(TEXT)

for before, target, after in window(tokens, n=3):
    if target in keywords:
        #do stuff with `before` and `after`

window是您选择滑动窗口实现的地方,比如here,而tokenize是您自己的涉及splitstrip的实现,或者是如果您想要库解决方案的话,可能是ntlk.tokenize

票数 3
EN

Stack Overflow用户

发布于 2014-08-13 03:48:21

代码语言:javascript
复制
import string
import re

alphabet = string.lowercase + string.uppercase
regex1 = re.compile("(%s)" % "|".join(keywords))
regex2 = re.compile("^(%s)" % "|".join(keywords))
regex3 = re.compile("(%s)$" % "|".join(keywords))

for match in regex1.finditer(TEXT):
    cut = TEXT[max(match.start() - before, 0) : match.end() + after]
    finalcut = cut
    if not regex2.search(cut):
        finalcut = finalcut.lstrip(alphabet)
    if not regex3.search(cut):
        finalcut = finalcut.rstrip(alphabet)
    print cut, finalcut

这一点可以进一步改进,因为只有两次关键字可以在文本的开头或结尾,因此不应该删除。

代码语言:javascript
复制
cuts = [TEXT[max(match.start() - before, 0) : match.end() + after] for match in regex1.finditer(TEXT)]
finalcuts = [0] * len(cuts)
for i, cut in enumerate(cuts):
    if i == 0 and not regex2.search(cut):
        finalcuts[0] = cuts[0].lstrip(alphabet)
    elif i == 0:
        finalcuts[0] = cuts[0]
    if i == len(cuts) - 1 and not regex3.search(cut):
            if i == 0:
                finalcuts[i] = finalcuts[i].rstrip(alphabet)
            elif i > 0:
                finalcuts[i] = cuts[i].rstrip(alphabet)
    elif i > 0:
        finalcuts[i] = cuts[i].strip(alphabet)
print cuts, finalcuts
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25277305

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档