如何使用 Python 3 和 Beautiful Soup 获取 Wikipedia 文章的文本?
Posted
技术标签:
【中文标题】如何使用 Python 3 和 Beautiful Soup 获取 Wikipedia 文章的文本?【英文标题】:How can I get a Wikipedia article's text using Python 3 with Beautiful Soup? 【发布时间】:2019-05-17 04:41:27 【问题描述】:我有这个用 Python 3 编写的脚本:
response = simple_get("https://en.wikipedia.org/wiki/Mathematics")
result =
result["url"] = url
if response is not None:
html = BeautifulSoup(response, 'html.parser')
title = html.select("#firstHeading")[0].text
如您所见,我可以从文章中获得标题,但我不知道如何将文本从“数学(来自希腊语 μά...”)获取到目录...
【问题讨论】:
【参考方案1】:有一种更简单的方法可以从***获取信息 - Wikipedia API。
有this Python wrapper,它只允许您在几行代码中完成零 HTML 解析:
import wikipediaapi
wiki_wiki = wikipediaapi.Wikipedia('en')
page = wiki_wiki.page('Mathematics')
print(page.summary)
打印:
数学(来自希腊语 μάθημα máthēma,“知识、学习、学习”) 包括对数量、结构、空间和 改变……(特意省略)
而且,一般来说,如果有可用的直接 API,请尽量避免屏幕抓取。
【讨论】:
【参考方案2】:选择<p>
标签。有 52 个元素。不确定你是否想要整个东西,但你可以遍历这些标签来尽可能地存储它。我只是选择打印它们中的每一个来显示输出。
import bs4
import requests
response = requests.get("https://en.wikipedia.org/wiki/Mathematics")
if response is not None:
html = bs4.BeautifulSoup(response.text, 'html.parser')
title = html.select("#firstHeading")[0].text
paragraphs = html.select("p")
for para in paragraphs:
print (para.text)
# just grab the text up to contents as stated in question
intro = '\n'.join([ para.text for para in paragraphs[0:5]])
print (intro)
【讨论】:
if response is not None
可以重写为if response
。另外,由于将来内容可能会发生变化,我建议获取整个 div,只阅读 p
并在到达带有“toclimit-3”类的 div 时停止
@PinoSan 我认为明确检查 None 并没有什么坏处。例如bool('' is not None)
与bool('')
不同。但是,在这种情况下,None 检查是完全没有必要的,因为response
将始终是requests.models.Response
对象。如果请求失败,将引发异常。
@t.m.adam 你说的是真的,但正如你所说,响应不是字符串。所以你只是想检查它是一个有效的对象,而不是一个空字符串,None 或一个空字典,......关于异常,我同意我们应该检查异常以防网络错误,但我们也应该检查状态代码为 200
@PinoSan 当然,我也更喜欢if response
风格,但你知道,"Explicit is better than implicit."。 if response
的问题是它可能会产生奇怪的错误,难以调试。但是,是的,在大多数情况下,一个简单的布尔检查就足够了。
仅仅因为你可以抓取页面,并不意味着你应该。 Wikipedia API 具有 python 包,允许轻松直接地访问文章,而无需在网站上过度加载或额外工作。【参考方案3】:
使用库wikipedia
import wikipedia
#print(wikipedia.summary("Mathematics"))
#wikipedia.search("Mathematics")
print(wikipedia.page("Mathematics").content)
【讨论】:
我会改用wikipediaapi
,wikipedia
模块似乎没有维护。不过,两者都会以类似的方式完成工作。【参考方案4】:
您可以使用lxml
库获得所需的输出,如下所示。
import requests
from lxml.html import fromstring
url = "https://en.wikipedia.org/wiki/Mathematics"
res = requests.get(url)
source = fromstring(res.content)
paragraph = '\n'.join([item.text_content() for item in source.xpath('//p[following::h2[2][span="History"]]')])
print(paragraph)
使用BeautifulSoup
:
from bs4 import BeautifulSoup
import requests
res = requests.get("https://en.wikipedia.org/wiki/Mathematics")
soup = BeautifulSoup(res.text, 'html.parser')
for item in soup.find_all("p"):
if item.text.startswith("The history"):break
print(item.text)
【讨论】:
【参考方案5】:您似乎想要的是没有周围导航元素的 (HTML) 页面内容。正如我在this earlier answer from 2013 中所描述的,有(至少)两种方法可以得到它:
在您的情况下,最简单的方法可能是在 URL 中包含参数 action=render
,如 https://en.wikipedia.org/wiki/Mathematics?action=render。这将只为您提供内容 HTML,而不是其他内容。
您也可以通过MediaWiki API获取页面内容,如https://en.wikipedia.org/w/api.php?format=xml&action=parse&page=Mathematics。
使用 API 的优势在于它还可以为您提供a lot of other information 关于您可能觉得有用的页面的信息。例如,如果您想要一个通常显示在页面侧边栏中的跨语言链接列表,或者通常显示在内容区域下方的类别,您可以从 API 中获取这些内容,如下所示:
https://en.wikipedia.org/w/api.php?format=xml&action=parse&page=Mathematics&prop=langlinks|categories
(若要获取相同请求的页面内容,请使用prop=langlinks|categories|text
。)
有几个Python libraries for using the MediaWiki API 可以自动化使用它的一些基本细节,尽管它们支持的功能集可能会有所不同。也就是说,直接从您的代码中使用 API 而无需中间的库也是完全可能的。
【讨论】:
【参考方案6】:要获得正确的函数使用方法,您可以获取 Wikipedia 提供的 JSON API :
from urllib.request import urlopen
from urllib.parse import urlencode
from json import loads
def getJSON(page):
params = urlencode(
'format': 'json',
'action': 'parse',
'prop': 'text',
'redirects' : 'true',
'page': page)
API = "https://en.wikipedia.org/w/api.php"
response = urlopen(API + "?" + params)
return response.read().decode('utf-8')
def getRawPage(page):
parsed = loads(getJSON(page))
try:
title = parsed['parse']['title']
content = parsed['parse']['text']['*']
return title, content
except KeyError:
# The page doesn't exist
return None, None
title, content = getRawPage("Mathematics")
然后你可以用任何你想提取你需要的库来解析它:)
【讨论】:
【参考方案7】:我使用这个:通过 'idx' 我可以确定我想阅读哪个段落。
from from bs4 import BeautifulSoup
import requests
res = requests.get("https://de.wikipedia.org/wiki/Pferde")
soup = BeautifulSoup(res.text, 'html.parser')
for idx, item in enumerate(soup.find_all("p")):
if idx == 1:
break
print(item.text)
【讨论】:
那么页面里面的第一段就是文章的内容?我对此表示怀疑。 不,这只是第一段。您可以使用 idx == 来确定要查看的段落。 我知道,但除了它可能会改变之外,从文档中提取或多或少随机元素并不是最好的选择。 @shaedrich 我想再次解释一下。重点是遍历各个章节。例如,在类似 Alexa 版本的 Dialog 中:询问“什么是马”。在这种情况下,您会收到很多文本。在对话中你现在可以说:“阅读更多”。或者跳过这一章。我希望你现在明白这种迭代的可能性是多么有用。谢谢。 对不起,不是真的。以上是关于如何使用 Python 3 和 Beautiful Soup 获取 Wikipedia 文章的文本?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Python 和 Beautiful Soup 从框架中抓取信息
如何在 Beautiful Soup 4 (Python) 中使用搜索栏
Python 3.6 Beautiful Soup - 在网页抓取期间无法获取嵌入式视频 URL
[Python3网络爬虫开发实战] 1.3.2-Beautiful Soup的安装