【问题标题】:Creating new columns by scraping information通过抓取信息创建新列
【发布时间】:2020-04-06 02:05:23
【问题描述】:

我正在尝试将从网站抓取的信息添加到列中。我有一个看起来像这样的数据集:

COL1   COL2    COL3
...     ...    bbc.co.uk

我想要一个包含新列的数据集:

 COL1   COL2    COL3          Website Address   Last Analysis   Blacklist Status \  
...     ...    bbc.co.uk

IP Address  Server Location    City       Region

这些新列来自此网站:https://www.urlvoid.com/scan/bbc.co.uk。 我需要用其相关信息填充每一列。

例如:

  COL1   COL2    COL3          Website Address   Last Analysis   Blacklist Status \  
...     ...    bbc.co.uk         Bbc.co.uk         9 days ago       0/35

Domain Registration               IP Address       Server Location    City       Region
1996-08-01 | 24 years ago       151.101.64.81    (US) United States   Unknown    Unknown

不幸的是,我在创建新列并用从网站上抓取的信息填充它们时遇到了一些问题。我可能有更多的网站要查看,不仅仅是 bbc.co.uk。 请参阅下面使用的代码。我确信有更好的(并且更少混淆)的方法来做到这一点。 如果您能帮我弄清楚,我将不胜感激。谢谢

编辑:

如上例所示,对于包含三列 (col1, col2 and col3) 的现有数据集,我还应该添加来自抓取的字段 (Website Address,Last Analysis,Blacklist Status, ...)。那么,对于每个 url,我应该有与之相关的信息(例如,示例中的 bbc.co.uk)。

 COL1   COL2    COL3          Website Address   Last Analysis   Blacklist Status \  
...     ...    bbc.co.uk          Bbc.co.uk         9 days ago       0/35
...     ...    stackoverflow.com
...     ...    ...


IP Address  Server Location    City       Region
  COL1   COL2    COL3          Website Address   Last Analysis   Blacklist Status \  
...     ...    bbc.co.uk         Bbc.co.uk         9 days ago       0/35
...     ...    stackoverflow.com Stackoverflow.com  7 days ago      0/35


Domain Registration               IP Address       Server Location    ...
996-08-01 | 24 years ago       151.101.64.81    (US) United States    ...
2003-12-26 | 17 years ago      ...

(格式不好,但我认为它足以让您了解预期的输出)。

更新代码:

urls= ['bbc.co.uk', 'stackoverflow.com', ...]

for x in urls:
        print(x)
        r = requests.get('https://www.urlvoid.com/scan/'+x)
        soup = BeautifulSoup(r.content, 'lxml')
        tab = soup.select("table.table.table-custom.table-striped")
        dat = tab[0].select('tr')
        for d in dat:
                row = d.select('td')
                original_dataset[row[0].text]=row[1].text

不幸的是,我做错了一些事情,因为它仅将网站上检查的第一个 url 中的信息(即 bbc.co.uk)复制到新列下的所有行中。

【问题讨论】:

  • 我会有一个空的数据框并添加我得到的数据。

标签: python pandas dataframe web-scraping beautifulsoup


【解决方案1】:

如果这是您要找的,请告诉我:

cols = ['Col1','Col2']
rows = ['something','something else']
my_df= pd.DataFrame(rows,index=cols).transpose()
my_df

从此行中提取现有代码:

dat = tab[0].select('tr')

添加:

for d in dat:
    row = d.select('td')
    my_df[row[0].text]=row[1].text
my_df

输出(抱歉格式化):

    Col1       Col2       Website Address   Last Analysis   Blacklist Status    Domain Registration     Domain Information  IP Address  Reverse DNS     ASN     Server Location     Latitude\Longitude  City    Region
0   something   something else  Bbc.com     11 days ago  |  Rescan  0/35    1989-07-15 | 31 years ago   WHOIS Lookup | DNS Records | Ping   151.101.192.81   Find Websites  |  IPVoid  |  ...   Unknown     AS54113 FASTLY  (US) United States  37.751 / -97.822   Google Map   Unknown     Unknown

编辑:

要使用多个网址,请尝试以下操作:

urls = ['bbc.com', 'stackoverflow.com']
ares = []
for u in urls:
    url = 'https://www.urlvoid.com/scan/'+u
    r = requests.get(url)
    ares.append(r)
rows = []
cols = []
for ar in ares:
    soup = bs(ar.content, 'lxml')
    tab = soup.select("table.table.table-custom.table-striped")        
    dat = tab[0].select('tr')
    line= []
    header=[]
    for d in dat:
        row = d.select('td')
        line.append(row[1].text)
        new_header = row[0].text
        if not new_header in cols:
            cols.append(new_header)

    rows.append(line)

my_df = pd.DataFrame(rows,columns=cols)   
my_df

输出:

Website Address     Last Analysis   Blacklist Status    Domain Registration     Domain Information  IP Address  Reverse DNS     ASN     Server Location     Latitude\Longitude  City    Region
0   Bbc.com     12 days ago  |  Rescan  0/35    1989-07-15 | 31 years ago   WHOIS Lookup | DNS Records | Ping   151.101.192.81   Find Websites  |  IPVoid  |  ...   Unknown     AS54113 FASTLY  (US) United States  37.751 / -97.822   Google Map   Unknown     Unknown
1   Stackoverflow.com   5 minutes ago  |  Rescan    0/35    2003-12-26 | 17 years ago   WHOIS Lookup | DNS Records | Ping   151.101.1.69   Find Websites  |  IPVoid  |  Whois   Unknown     AS54113 FASTLY  (US) United States  37.751 / -97.822   Google Map   Unknown     Unknown

请注意,这没有您现有的两个列(因为我不知道它们是什么),因此您必须将它们分别附加到数据框。

【讨论】:

  • 谢谢@Jack Fleeting。是的,这就是我要找的。你能看看我的问题吗?我更新了代码,因为我犯了一些错误,因为它只从检查的第一个 url (bbc.co.uk) 复制所有行的信息。
  • 谢谢杰克。最后一个问题。要更新已经包含 url 的数据集(我称之为 original_dataset)并加入仅包含新列的新数据集,我应该使用 pd.merge(original_dataset, my_df, left_index=True, right_index=True, how='outer') 吗?最后,我应该从原始数据集中获得三列 + 新列(即输出中的列),参考答案中的最后几行
  • @Val - 您的建议应该可行,但我会从您的原始数据集中删除 Col 3,因为它与新的“网站地址”重叠。
  • 非常感谢您的帮助,杰克!真的很感激!
  • 嗨@Jack,我可以请你看看我的新问题吗? stackoverflow.com/questions/61108005/…我已经批准了一个答案,但实际上它并不能完全满足我的要求。由于代码与您提出的不同,我想继续使用您的代码,如果您能提出答案并帮助我,我将不胜感激。谢谢。
【解决方案2】:

您可以使用更简单的方法来获取数据,即使用 pandas read_html 方法。这是我的镜头-

import pandas as pd

df = pd.read_html("https://www.urlvoid.com/scan/bbc.co.uk/")[0]

df_transpose = df.T

现在您有了所需的转置数据。如果您愿意,可以删除不需要的列。之后,您现在要做的就是将其与现有数据集连接起来。考虑到您可以将数据集加载为 pandas 数据框,您可以简单地为此使用 concat 函数(axis=1 是连接为列):

pd.concat([df_transpose, existing_dataset], axis=1)

请参阅有关合并/连接的 pandas 文档:http://pandas.pydata.org/pandas-docs/stable/merging.html

【讨论】:

  • 谢谢@Prakhar Jhudele。它不添加标题,因此结果不完全匹配。对于我拥有的每个 url,我应该添加该网站抓取的相应信息,并且应该在右侧添加列(在旧列之后)。不幸的是,您的代码也添加了新闻行,而不是向已经存在的行添加信息(请参阅示例)。我需要为每个现有行(url)添加新列,以存储从该网站抓取的信息
  • 在这种情况下,您需要一个连接列。您可以对旧数据集第 3 列和新数据框中的网站地址进行外部联接..
  • 我尝试使用pd.merge(original_dataset, df_transpose, left_index=True, right_index=True, how='outer'),但问题是它仍在添加行并且没有标题。新列的标题应为Website Address Last Analysis Blacklist Status ...,但这些字段作为行添加
  • 更新了问题,包括更完整的预期输出。当我打印输出数据集时,添加的所有列都包含最后检查的项目。你能看看我帖子里的代码吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-14
  • 2016-05-23
  • 2013-06-22
  • 2021-04-09
  • 1970-01-01
  • 2018-10-19
  • 1970-01-01
相关资源
最近更新 更多