【问题标题】:Python Regex Extract Date to New Column in DataframePython 正则表达式将日期提取到数据框中的新列
【发布时间】:2020-09-13 16:29:42
【问题描述】:

我正在使用 Python 抓取网站,但在提取日期和使用正则表达式创建新的 Date 数据框时遇到了麻烦。

以下代码使用 BeautifulSoup 来抓取事件数据和事件链接:

import pandas as pd
import bs4 as bs
import urllib.request

source = urllib.request.urlopen('https://www.techmeme.com/events').read()
soup = bs.BeautifulSoup(source,'html.parser')

event = []
links = []

# ---Event Data---
for a in soup.find_all('a'):
    event.append(a.text)

df_event = pd.DataFrame(event)
df_event.columns = ['Event']
df_event = df_event.iloc[1:]

# ---Links---
for a in soup.find_all('a', href=True): 
    if a.text: 
        links.append(a['href'])
df_link = pd.DataFrame(links)
df_link.columns = ['Links']

# ---Combines dfs---
df = pd.concat([df_event.reset_index(drop=True),df_link.reset_index(drop=True)],sort=False, axis=1)

在每个事件数据行的开头,都有日期。示例:(5 月 26-29 日增强型世博会...)。日期遵循以下格式,并且我已经包含了我的正则表达式(我认为这是正确的)。

Different Date Formats:
May 27: [A-Z][a-z]*(\ )[0-9]{1,2}
May 26-29:  [A-Z][a-z]*(\ )[0-9]{1,2}-[0-9]{1,2}
May 28-Jun 2: [A-Z][a-z]*(\ )[0-9]{1,2}-[A-Z][a-z]*(\ )[0-9]{1,2}

Combined
[A-Z][a-z]*(\ )[0-9]{1,2}|[A-Z][a-z]*(\ )[0-9]{1,2}-[0-9]{1,2}|[A-Z][a-z]*(\ )[0-9]{1,2}-[A-Z][a-z]*(\ )[0-9]{1,2}

当我尝试使用正则表达式创建新列并提取日期时,我只收到一个空的 df['Date'] 列。

df['Date'] = df['Event'].str.extract(r[A-Z][a-z]*(\ )[0-9]{1,2}')
df.head()

任何帮助将不胜感激!谢谢。

【问题讨论】:

标签: python python-3.x regex pandas


【解决方案1】:

你可以使用

date_reg = r'([A-Z][a-z]* [0-9]{1,2}(?:-(?:[A-Z][a-z]* )?[0-9]{1,2})?)'
df['Date'] = df['Event'].str.extract(date_reg, expand=False)

请参阅regex demo。如果你想匹配整个单词和数字,你可以使用(?<![A-Za-z])([A-Z][a-z]* [0-9]{1,2}(?:-(?:[A-Z][a-z]* )?[0-9]{1,2})?)(?!\d)

详情

  • [A-Z][a-z]* - 一个大写字母,然后是 0 个或多个小写字母
  • - 一个空格(替换为 \s 以匹配任何空格)
  • [0-9]{1,2} - 一位或两位数
  • (?:-(?:[A-Z][a-z]* )?[0-9]{1,2})? - 可选序列
    • - - 连字符
    • (?:[A-Z][a-z]* )? - 可选序列
      • [A-Z][a-z]* - 一个大写字母,然后是 0 个或多个小写字母
      • - 一个空格(替换为 \s 以匹配任何空格)
    • [0-9]{1,2} - 一位或两位数

(?<![A-Za-z]) 构造是一个向后查找,如果在当前位置之前有一个字母,则匹配失败;如果紧随其后有一个数字,(?!\d) 则匹配失败。

【讨论】:

  • 感谢您的解释!现在这很有意义。该网站看起来像是一个很棒的学习工具。非常感谢。
  • 我能够创建新的日期列,但是原始日期仍然存在于事件列中。我将如何删除它?我假设 extract 做到了。
  • @LeslieTate 如果要从 Event 列中删除日期,则需要在其上使用str.replace,使用df['Event'] = df['Event'].str.replace(date_reg, '')str.extract 只找到匹配项,不会删除任何内容。
  • 啊,很高兴知道。再次感谢您的帮助:)
【解决方案2】:

这个脚本:

import requests
from bs4 import BeautifulSoup

url = 'https://www.techmeme.com/events'

soup = BeautifulSoup(requests.get(url).content, 'html.parser')

data = []
for row in soup.select('.rhov a'):
    date, event, place = map(lambda x: x.get_text(strip=True), row.find_all('div', recursive=False))
    data.append({'Date': date, 'Event': event, 'Place': place, 'Link': 'https://www.techmeme.com' + row['href']})

df = pd.DataFrame(data)
print(df)

将创建此数据框:

          Date                                           Event          Place                                               Link
0    May 26-29                NOW VIRTUAL:Augmented World Expo    Santa Clara      https://www.techmeme.com/gotos/www.awexr.com/
1       May 27                               Earnings: HPQ,BOX                 https://www.techmeme.com/gotos/finance.yahoo.c...
2       May 28                              Earnings: CRM, VMW                 https://www.techmeme.com/gotos/finance.yahoo.c...
3    May 28-29         CANCELED:WeAreDevelopers World Congress         Berlin  https://www.techmeme.com/gotos/www.wearedevelo...
4        Jun 2                                    Earnings: ZM                 https://www.techmeme.com/gotos/finance.yahoo.c...
..         ...                                             ...            ...                                                ...
140   Dec 7-10                         NEW DATE:GOTO Amsterdam      Amsterdam         https://www.techmeme.com/gotos/gotoams.nl/
141   Dec 8-10                 Microsoft Azure + AI Conference      Las Vegas  https://www.techmeme.com/gotos/azureaiconf.com...
142   Dec 9-10           NEW DATE:Paris Blockchain Week Summit          Paris  https://www.techmeme.com/gotos/www.pbwsummit.com/
143  Dec 13-16                          NEW DATE:KNOW Identity      Las Vegas  https://www.techmeme.com/gotos/www.knowidentit...
144  Dec 15-16  NEW DATE, NEW LOCATION:Fortune Brainstorm Tech  San Francisco  https://www.techmeme.com/gotos/fortuneconferen...

[145 rows x 4 columns]

【讨论】:

  • 这是一个更简单的解决方案!我想它显示了如何用更少的代码行来完成。我没有看到 df 中包含的链接。
  • @LeslieTate 我更新了我的答案以包括链接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-13
  • 2023-02-04
  • 2018-01-12
  • 2021-01-22
  • 2020-09-21
  • 2019-07-17
相关资源
最近更新 更多