使用 Beautifulsoup 从维基百科 table 访问另一列的子列

accessing a sub column of another column from wikipedia table using Beautifulsoup

我有一个项目需要我们从维基百科下载和阅读 table,然后使用这些信息进行计算。 维基百科页面是 https://en.wikipedia.org/wiki/List_of_United_States_cities_by_crime_rate#Criticism_of_ranking_crime_data

我们需要列出每个城市、州的总暴力犯罪(州重复),但是该列的所有单元格都只有标签。它在一个 table 下,问题是我将如何使用 beautifulsoup 阅读暴力犯罪栏

下的特定栏

我搜索了互联网,从这里和其他网站上找到了很多选择,但在这种特定情况下它们并没有真正帮助但这是我目前拥有的代码,可以从 table。大多数变量在我测试时都是持有者,因为我已经研究了几天

state = soup.find_all('th', limit = 7)
for row in state:
    row_data = row.get_text(strip = True, separator = '|').split('|')[0:1]
    outfile.write(str(row_data)+ "\n")
umber = soup.find_all('td')

for column in number:
     column_data = column.get_text(strip = True, separator = '|').split('|')[0:1]

     outfile.write(str(column_data)+ "\n")

我基本上想将这些信息存储到列表中供以后使用,然后使用指向每个城市的链接并获取它们的电源线,然后将其引用到德克萨斯州最靠近边境的几个城市

我们只允许使用 BeautifulSoup 和 CSV no Pandas 或 NumPy

编辑: 写出功能也仅用于测试。只是看是否正确抓取了table的信息。我的 IDE 控制台无法显示所有这些,所以写出来是我能想到的下一个最好的事情

看起来这只是创建列表的问题。您可以通过初始化您的列表,然后将您的列表添加到其中来完成此操作。或者您可以将 for 循环中的每个项目附加到它。或者您可以通过列表推导来使它更简洁。

你一无所获的原因是你在循环中不断覆盖你的 row_datacolumn_data。它会写入文件,但是,它会在每个文件之后放一个新行,当我假设你想写整行,然后再写一个新行,所以我也会把你的写在列表之后是​​ created/complete:

将列表合并为一个列表:

row_data = []
for row in state:
    row_data = row_data + row.get_text(strip = True, separator = '|').split('|')[0:1]
outfile.write(str(row_data)+ "\n")


number = soup.find_all('td')

column_data = []
for column in number:
     column_data = column_data + column.get_text(strip = True, separator = '|').split('|')[0:1]
outfile.write(str(column_data)+ "\n")

将 item/element 添加到列表中:

# Initiate and then append to a list
row_data = []
for row in state:
    row_data.append(row.text)
outfile.write(str(row_data)+ "\n")


number = soup.find_all('td')
column_data = []
for column in number:
     column_data.append(column.text)
outfile.write(str(column_data)+ "\n")

列表理解:

#List comprehension
row_data = [ row.text for row in state ]
outfile.write(str(row_data)+ "\n")

column_data = [ column.text for column in number ] 
outfile.write(str(column_data)+ "\n")

就获取这些子列而言,这很棘手,因为它们不是子标签。然而,它们是您拉出的 <th> 标签之后的下一个 <tr> 标签,因此我们可以使用它。

import bs4
import requests
import csv



url = 'https://en.wikipedia.org/wiki/List_of_United_States_cities_by_crime_rate#Criticism_of_ranking_crime_data'

response = requests.get(url)

soup = bs4.BeautifulSoup(response.text, 'html.parser')

# Only want State and City so limit = 2
headers = soup.find_all('th', limit = 2)
sub_headers = headers[0].findNext('tr')


# Initiate and then append to a list
header_data = []
for data in headers:
    header_data.append(data.text.strip())


sub_header_data = []
for data in sub_headers.find_all('th'):
    sub_header_data.append(data.text.strip())

# Only want to append the first Total column from the sub_headers    
header_data.append(sub_header_data[0])


with open('C:/test.csv', mode='w', newline='') as outfile:
    writer = csv.writer(outfile)
    writer.writerow(header_data)



    table_body = soup.find_all('tbody')[1]
    rows = table_body.find_all('tr')
    for row in rows:
        tds = row.find_all('td', limit = 4)

        #Skip the blank rows of data
        if tds == []:
            continue

        tds_data = []
        for data in tds:
            tds_data.append(data.text.strip())

        #Remove the Population number/data
        del tds_data[2]

        writer.writerow(tds_data)