Python Web Scraping:从 Infobox Geography Vcard 中提取维基百科中的区域面积
Python Web Scraping: Extracting the Area of a Region in Wikipedia from the Infobox Geography Vcard
我知道这类问题已被处理过无数次,但在梳理了几个小时的答案和指南后,我还是无法解决这个问题,非常感谢您的帮助。
理想情况下,我想提取维基百科信息框中列出的以平方公里为单位的区域。例如,我 运行 在 https://en.wikipedia.org/wiki/Sandton 上的代码应该产生类似“143.54 km”的内容。
我使用大量指南放在一起的代码似乎只适用于整个国家/地区的维基百科网站,其中“区域”实际上是 link。在西班牙的维基百科页面上试试这个:
from bs4 import BeautifulSoup
import requests
def getAdditionalDetails(URL):
try:
soup = BeautifulSoup(requests.get(URL).text, 'lxml')
table = soup.find('table', {'class': 'infobox geography vcard'})
additional_details = []
read_content = False
for tr in table.find_all('tr'):
if (tr.get('class') == ['mergedtoprow'] and not read_content):
link = tr.find('th')
if (link.get_text().strip() == 'Area'):
read_content = True
if (link.get_text().strip() == 'Population'):
read_content = False
elif ((tr.get('class') == ['mergedrow'] or tr.get('class') == ['mergedbottomrow']) and read_content):
additional_details.append(tr.find('td').get_text().strip('\n'))
if (tr.find('div').get_text().strip() != '•\xa0Total area'):
read_content = False
return additional_details
except Exception as error:
print('Error occured: {}'.format(error))
return []
URL = "https://en.wikipedia.org/wiki/Spain"
print(getAdditionalDetails(URL))
这输出几乎可用:
['505,990[6]\xa0km2 (195,360\xa0sq\xa0mi) (51st)']
有比我更聪明的人帮忙吗?
谢谢。
这不是最干净的方法,但可以。如果您想要特定的行,请从 CSS 选择器开始。
代码示例
import requests
from bs4 import BeautifulSoup
url = 'https://en.wikipedia.org/wiki/Sandton'
html = requests.get(url)
soup = BeautifulSoup(html.text,'html.parser')
area = soup.select('table > tbody > tr')[9].get_text(strip=True)
area = area.replace('\xa0', '').split('(')[0]
cleaned_area = area[7:]
输出
143.54 km2(55.42 sq mi)
解释
这段代码中的区域变量我们使用 CSS 选择器专门选择行。
get_text(strip=True)
是抓取文本的方法,但它会去除所有白色 space。您应该知道 \xa0 在 Latin1 编码中是不间断的 space 。 Strip=True 将在字符串的开头和结尾删除它。
没有strip=True
的区域变量的输出看起来像这样
'\xa0•\xa0Total143.54\xa0km2 (55.42\xa0sq\xa0mi)'
有 strip=True
'•\xa0Total143.54\xa0km2(55.42\xa0sq\xa0mi)'
所以你仍然卡在字符串中。
使用替换字符串的方法,我们可以用 space.
替换 \xa0
所以输出
'• Total143.54 km2(55.42 sq mi)'
然后因为我们实际上不需要前 7 个字符,我们只需要使用字符串附带的切片从第 8 个字符开始。
附加信息
编码在 python 和一般计算中是一个很大的话题,了解一点它很重要。编码本质上是存在的,因为无论喜欢与否,计算机中的一切都是一个字节。必须有从硬件到软件的转换,编码是该步骤的一部分。
我们希望能够将字符转换为位,以便计算机可以在我们编写代码时执行某些操作。
最简单的编码类型是 ASCII,您可能在某些时候已经遇到过。整个ASCII码table有128个字符对应'Code Points'
ASCII码点:97
字符:一个
现在您可能会问这有什么意义?好吧,我们可以将这些字符转换为代码点,这些代码点很容易转换为二进制文件。这很容易转换为位(1 或 0),供计算机在硬件级别执行某些操作。
现在 ASCII 的问题是人类语言中的字符比 128 个字符多得多...所以输入一种新的编码类型。有很多,最常见的是 Unicode,我提供了一些资源来进一步了解它。
现在 Latin-1 编码是 HTTP 请求的默认编码,请求库严格遵循此编码。
部分资源:
我知道这类问题已被处理过无数次,但在梳理了几个小时的答案和指南后,我还是无法解决这个问题,非常感谢您的帮助。
理想情况下,我想提取维基百科信息框中列出的以平方公里为单位的区域。例如,我 运行 在 https://en.wikipedia.org/wiki/Sandton 上的代码应该产生类似“143.54 km”的内容。
我使用大量指南放在一起的代码似乎只适用于整个国家/地区的维基百科网站,其中“区域”实际上是 link。在西班牙的维基百科页面上试试这个:
from bs4 import BeautifulSoup
import requests
def getAdditionalDetails(URL):
try:
soup = BeautifulSoup(requests.get(URL).text, 'lxml')
table = soup.find('table', {'class': 'infobox geography vcard'})
additional_details = []
read_content = False
for tr in table.find_all('tr'):
if (tr.get('class') == ['mergedtoprow'] and not read_content):
link = tr.find('th')
if (link.get_text().strip() == 'Area'):
read_content = True
if (link.get_text().strip() == 'Population'):
read_content = False
elif ((tr.get('class') == ['mergedrow'] or tr.get('class') == ['mergedbottomrow']) and read_content):
additional_details.append(tr.find('td').get_text().strip('\n'))
if (tr.find('div').get_text().strip() != '•\xa0Total area'):
read_content = False
return additional_details
except Exception as error:
print('Error occured: {}'.format(error))
return []
URL = "https://en.wikipedia.org/wiki/Spain"
print(getAdditionalDetails(URL))
这输出几乎可用:
['505,990[6]\xa0km2 (195,360\xa0sq\xa0mi) (51st)']
有比我更聪明的人帮忙吗?
谢谢。
这不是最干净的方法,但可以。如果您想要特定的行,请从 CSS 选择器开始。
代码示例
import requests
from bs4 import BeautifulSoup
url = 'https://en.wikipedia.org/wiki/Sandton'
html = requests.get(url)
soup = BeautifulSoup(html.text,'html.parser')
area = soup.select('table > tbody > tr')[9].get_text(strip=True)
area = area.replace('\xa0', '').split('(')[0]
cleaned_area = area[7:]
输出
143.54 km2(55.42 sq mi)
解释
这段代码中的区域变量我们使用 CSS 选择器专门选择行。
get_text(strip=True)
是抓取文本的方法,但它会去除所有白色 space。您应该知道 \xa0 在 Latin1 编码中是不间断的 space 。 Strip=True 将在字符串的开头和结尾删除它。
没有strip=True
的区域变量的输出看起来像这样
'\xa0•\xa0Total143.54\xa0km2 (55.42\xa0sq\xa0mi)'
有 strip=True
'•\xa0Total143.54\xa0km2(55.42\xa0sq\xa0mi)'
所以你仍然卡在字符串中。
使用替换字符串的方法,我们可以用 space.
替换\xa0
所以输出
'• Total143.54 km2(55.42 sq mi)'
然后因为我们实际上不需要前 7 个字符,我们只需要使用字符串附带的切片从第 8 个字符开始。
附加信息
编码在 python 和一般计算中是一个很大的话题,了解一点它很重要。编码本质上是存在的,因为无论喜欢与否,计算机中的一切都是一个字节。必须有从硬件到软件的转换,编码是该步骤的一部分。
我们希望能够将字符转换为位,以便计算机可以在我们编写代码时执行某些操作。
最简单的编码类型是 ASCII,您可能在某些时候已经遇到过。整个ASCII码table有128个字符对应'Code Points'
ASCII码点:97
字符:一个
现在您可能会问这有什么意义?好吧,我们可以将这些字符转换为代码点,这些代码点很容易转换为二进制文件。这很容易转换为位(1 或 0),供计算机在硬件级别执行某些操作。
现在 ASCII 的问题是人类语言中的字符比 128 个字符多得多...所以输入一种新的编码类型。有很多,最常见的是 Unicode,我提供了一些资源来进一步了解它。
现在 Latin-1 编码是 HTTP 请求的默认编码,请求库严格遵循此编码。
部分资源: