Beautiful Soup 和 scraping 维基百科条目:

Beautiful Soup and scraping wikipedia entries:

初学者 BeautifulSoup,我正在尝试提取

来自此维基百科的公司名称、等级和收入 link。

https://en.m.wikipedia.org/wiki/List_of_largest_Internet_companies

到目前为止我使用的代码是:

from bs4 import BeautifulSoup 
import requests 
url = "https://en.wikiepdia.org" 
req = requests.get(url) 
bsObj = BeautifulSoup(req.text, "html.parser") 
data = bsObj.find('table',{'class':'wikitable sortable mw-collapsible'})
revenue=data.findAll('data-sort-value')

我意识到甚至 'data' 也不能正常工作,因为当我将它传递到 flask 网站时它没有任何值。

有人可以建议修复和实现上述目标的最优雅的方法,以及一些关于我们在抓取(和格式)时在 HTML 中寻找的最佳方法的建议.

关于这个 link, https://en.m.wikipedia.org/wiki/List_of_largest_Internet_companies 我不确定我要用来提取什么 - table class, div class 或正文 class。此外,如何进一步提取 link 和树下的收入。

我也试过:

data = bsObj.find_all('table', class_='wikitable sortable mw-collapsible')

它运行服务器没有错误。但是,在网页“[]”

上只显示一个空列表

基于以下一个答案:我将代码更新为以下内容:

url = "https://en.wikiepdia.org" 
req = requests.get(url) 
bsObj = BeautifulSoup(req.text, "html.parser") 
mydata=bsObj.find('table',{'class':'wikitable sortable mw-collapsible'})
table_data=[]
rows = mydata.findAll(name=None, attrs={}, recursive=True, text=None, limit=None, kwargs='')('tr')
for row in rows:
    cols=row.findAll('td')
    row_data=[ele.text.strip() for ele in cols]
    table_data.append(row_data)

data=table_data[0:10]

持续错误为:

 File "webscraper.py", line 15, in <module>
    rows = mydata.findAll(name=None, attrs={}, recursive=True, text=None, limit=None, kwargs='')('tr')
AttributeError: 'NoneType' object has no attribute 'findAll'

根据下面的回答,它现在正在抓取数据,但不是上面要求的格式:

我知道了:

url = 'https://en.m.wikipedia.org/wiki/List_of_largest_Internet_companies' 
req = requests.get(url) 
bsObj = BeautifulSoup(req.text, 'html.parser')
data = bsObj.find('table',{'class':'wikitable sortable mw-collapsible'})

table_data = []
rows = data.find_all('tr')
for row in rows:
    cols = row.find_all('td')
    row_data = [ele.text.strip() for ele in cols]
    table_data.append(row_data)

# First element is header so that is why it is empty
data=table_data[0:5]

for in in range(5):
    rank=data[i]
    name=data[i+1]

为了完整性(和完整答案),我希望它显示

-table前五家公司 -公司名称、职级、收入

当前显示为:

维基百科

[[], ['1', 'Amazon', '280.5 美元', '2019', '798,000', '920.22 美元', 'Seattle', '1994', '[1] [2]'], ['2', 'Google', '161.8', '2019', '118,899', '921.14', 'Mountain View', '1998', '[3][4] '], ['3', 'JD.com', '82.8', '2019', '220,000', '51.51', 'Beijing', '1998', '[5][6]'], ['4', 'Facebook', '70.69 美元', '2019', '45,000', '585.37 美元', 'Menlo Park', '2004', '[7][8]']]

['1', 'Amazon', '280.5 美元', '2019', '798,000', '920.22 美元', 'Seattle', '1994', '[1][2]' ]

['2', 'Google', '161.8', '2019', '118,899', '921.14', 'Mountain View', '1998', '[3][4]' ]

通常(并非总是)在处理维基百科表格时,您不必费心 beautifulsoup。只需使用 pandas:

import pandas as pd
table = pd.read_html('https://en.m.wikipedia.org/wiki/List_of_largest_Internet_companies')
table[0]

输出:

    Rank    Company     Revenue ($B)    F.Y.    Employees   Market cap. ($B)    Headquarters    Founded     Refs
0   1   Amazon  0.5  2019    798000  0.22     Seattle     1994    [1][2]
1   2   Google  1.8  2019    118899  1.14     Mountain View   1998    [3][4]

等 然后,您可以使用标准 pandas 方法 select 或删除列等。

编辑: 仅显示前 5 名公司的名称、排名和收入:

table[0][["Rank", "Company","Revenue ($B)"]].head(5)

输出:

    Rank Company    Revenue ($B)
0   1   Amazon      0.5
1   2   Google      1.8
2   3   JD.com     .8
3   4   Facebook    .69
4   5   Alibaba     .152

这是一个使用 BeautifulSoup 的示例。以下很多内容都是基于这里的答案 .

from bs4 import BeautifulSoup 
import requests

url = 'https://en.m.wikipedia.org/wiki/List_of_largest_Internet_companies' 
req = requests.get(url) 

bsObj = BeautifulSoup(req.text, 'html.parser')
data = bsObj.find('table',{'class':'wikitable sortable mw-collapsible'})

table_data = []
rows = data.find_all('tr')
for row in rows:
    cols = row.find_all('td')
    row_data = [ele.text.strip() for ele in cols]
    table_data.append(row_data)

# First element is header so that is why it is empty
table_data[0:5]
# [[],
#  ['1', 'Amazon', '0.5', '2019', '798,000', '0.22', 'Seattle', '1994', '[1][2]'],
#  ['2', 'Google', '1.8', '2019', '118,899', '1.14', 'Mountain View', '1998', '[3][4]'],
#  ['3', 'JD.com', '.8', '2019', '220,000', '.51', 'Beijing', '1998', '[5][6]'],
#  ['4', 'Facebook', '.69', '2019', '45,000', '5.37', 'Menlo Park', '2004', '[7][8]']]

所以隔离这个列表的某些元素,你只需要注意内部列表的数字索引。在这里,让我们看看亚马逊的前几个值。

# The entire row for Amazon
table_data[1]
# ['1', 'Amazon', '0.5', '2019', '798,000', '0.22', 'Seattle', '1994', '[1][2]']

# Rank
table_data[1][0]
# '1'

# Company
table_data[1][1]
# 'Amazon'

# Revenue
table_data[1][2]
# '0.5'

因此,为了仅隔离前几列(排名、公司和收入),您可以 运行 以下列表理解。

iso_data = [tab[0:3] for tab in table_data]

iso_data[1:6]
# [['1', 'Amazon', '0.5'], ['2', 'Google', '1.8'], ['3', 'JD.com', '.8'], ['4', 'Facebook', '.69'], ['5', 'Alibaba', '.152']]

然后,如果你想把它放到一个pandas数据框中,你可以这样做。

import pandas as pd

# The `1` here is important to remove the empty header
df = pd.DataFrame(table_data[1:], columns = ['Rank', 'Company', 'Revenue', 'F.Y.', 'Employees', 'Market cap', 'Headquarters', 'Founded', 'Refs'])

df
#    Rank     Company  Revenue  F.Y. Employees Market cap   Headquarters Founded        Refs
# 0     1      Amazon   0.5  2019   798,000    0.22        Seattle    1994      [1][2]
# 1     2      Google   1.8  2019   118,899    1.14  Mountain View    1998      [3][4]
# 2     3      JD.com    .8  2019   220,000     .51        Beijing    1998      [5][6]
# 3     4    Facebook   .69  2019    45,000    5.37     Menlo Park    2004      [7][8]
# 4     5     Alibaba  .152  2019   101,958    0.95       Hangzhou    1999     [9][10]
# ..  ...         ...      ...   ...       ...        ...            ...     ...         ...
# 75   77    Farfetch    .02  2019     4,532      .51         London    2007  [138][139]
# 76   78        Yelp    .01  2019     5,950      .48  San Francisco    1996  [140][141]
# 77   79   Vroom.com     .1  2020     3,990       .2  New York City    2003       [142]
# 78   80  Craigslist     .0  2018     1,000          -  San Francisco    1995       [143]
# 79   81    DocuSign     .0  2018     3,990     .62  San Francisco    2003       [144]
# 
# [80 rows x 9 columns]

这是另一个,这次只有 beautifulsoup,打印出前 5 家公司的排名、名称和收入:

table_data=[]
trs = soup.select('table tr')
for tr in trs[1:6]:
    row = []
    for t in tr.select('td')[:3]:    
        row.extend([t.text.strip()])
    table_data.append(row)
table_data

输出:

[['1', 'Amazon', '0.5'],
 ['2', 'Google', '1.8'],
 ['3', 'JD.com', '.8'],
 ['4', 'Facebook', '.69'],
 ['5', 'Alibaba', '.152']]