【问题标题】:Parse website from Wikipedia Infobox data从 Wikipedia Infobox 数据中解析网站
【发布时间】:2018-01-14 20:15:16
【问题描述】:

我正在使用 wikipedia api 来获取信息框数据。我想从这个信息框数据中解析website url。我尝试使用mwparserfromhell解析网站url,但是不同的关键字有不同的格式。

以下是一些网站模式 -

url                  = <!-- {{URL|www.example.com}} -->
| url = [https://www.TheGuardian.com/ TheGuardian.com]
| url = <span class="plainlinks">[https://www.naver.com/ www.naver.com]</span>
|url             = [https://www.tmall.com/ tmall.com]
|url            = [http://www.ustream.tv/ ustream.tv]

我需要帮助解析official website link 以了解维基百科支持的所有模式吗?

编辑 -

代码 -

# get infobox data
import requests
# keyword
keyword = 'stackoverflow.com'
# wikipedia api url
api_url = (
    'https://en.wikipedia.org/w/api.php?action=query&prop=revisions&'
    'rvprop=content&titles=%s&rvsection=0&format=json' % keyword)
# api request
resp = requests.get(api_url).json()
page_one = next(iter(resp['query']['pages'].values()))
revisions = page_one.get('revisions', [])
# infobox daa
infobox_data = next(iter(revisions[0].values()))

# parse website url
import mwparserfromhell
wikicode = mwparserfromhell.parse(infobox_data)
templates = wikicode.filter_templates()
website_url_1 = ''
website_url_2 = ''
for template in templates:
    # Pattern - `URL|http://x.com`
    if template.name == "URL":
        website_url_1 = str(template.get(1).value)
        break
    if not website_url_1:
        # Pattern - `website = http://x.com`
        try:
            website_url_2 = str(template.get("website").value)
        except ValueError:
            pass
    if not website_url_1:
        # Pattern - `homepage = http://x.com`
        try:
            website_url_2 = str(template.get("homepage").value)
        except ValueError:
            pass
if website_url_1:
    website_url = website_url_1
elif website_url_2:
    website_url = website_url_2

【问题讨论】:

  • 你能显示你的代码吗? mwparserfromhell 应该能够处理所有这些(除了第一个实际上不会显示链接)。
  • @Tgr 添加了我正在使用的代码。它仅涵盖少数情况。

标签: python parsing wikipedia wikipedia-api


【解决方案1】:

可以使用正则表达式和 BeautifulSoup 解析您提到的模式。可以想象,可以通过扩展这种方法来解析其他模式。

我从行首删除了包含 'url = ' 的内容,然后使用 BeautifulSoup 处理剩余部分。由于 BeautifulSoup 封装了它给出的内容以形成一个完整的页面,因此可以将原始内容作为 body 元素的文本获得。

>>> import re
>>> patterns = '''\
... url                  = <!-- {{URL|www.example.com}} -->
... | url = [https://www.TheGuardian.com/ TheGuardian.com]
... | url = <span class="plainlinks">[https://www.naver.com/ www.naver.com]</span>
... |url             = [https://www.tmall.com/ tmall.com]
... |url            = [http://www.ustream.tv/ ustream.tv]'''
>>> import bs4
>>> regex = re.compile(r'\s*\|?\s*url\s*=\s*', re.I)
>>> for pattern in patterns.split('\n'):
...     soup = bs4.BeautifulSoup(re.sub(regex, '', pattern), 'lxml')
...     if str(soup).startswith('<!--'):
...         'just a comment'
...     else:
...         soup.find('body').getText()
... 
'just a comment'
'[https://www.TheGuardian.com/ TheGuardian.com]'
'[https://www.naver.com/ www.naver.com]'
'[https://www.tmall.com/ tmall.com]'
'[http://www.ustream.tv/ ustream.tv]'

【讨论】:

  • 谢谢,如果有人可以提供完整的模式列表,这将很有用。我检查了几百页的数据,但没有找到任何标准模式。
  • 我需要更具体的解决方案来解析来自维基百科 api 数据的website。这些方面的任何内容都会有所帮助。
  • 我以为您已经研究过其他人对此的了解。没有标准模式或全面的模式集。尽管如此,您仍然可以以一种有用的方式自己扩展它。
【解决方案2】:

mwparserfromhell 是一个很好的工具:

import mwclient
import mwparserfromhell

site = mwclient.Site('en.wikipedia.org')
text = site.pages[pagename].text()
wikicode = mwparserfromhell.parse(text)
templates = wikicode.filter_templates(matches='infobox .*')
url = templates[0].get('url').value

url_template = url.filter_templates(matches='url')
url_link = url.filter_external_links()
if url_template:
    print url_template[0].get(1)
elif url_link:
    print url_link.url
else:
    print url

【讨论】:

  • 此代码 -url = templates[0].get('url').value 并非在所有情况下都有效。例如。 en.wikipedia.org/wiki/… 数据中的 url 没有标准属性。我从我的观察中找到了website, url and homepage。你知道所有有效的属性名称吗?
  • 没有。在 Wikipedia(例如 technical village pump)上问这类问题可能会更幸运。
【解决方案3】:

我写了this snippet,这可能会有所帮助:

import collections
import wikipedia
from bs4 import BeautifulSoup

def infobox(wiki_page):
    """Returns the infobox of a given wikipedia page"""
    if isinstance(wiki_page, str):
        wiki_page = wikipedia.page(wiki_page)
    try:
        soup = BeautifulSoup(wiki_page.html()).find_all("table", {"class": "infobox"})[0]
    except:
        return None
    ret = collections.defaultdict(dict)
    section = ""
    for tr in soup.find_all("tr"):
        th = tr.find_all("th")
        if not any(th):
            continue
        th = th[0]
        if str(th.get("colspan"))=='2':
            section = th.text.translate({160:' '}).strip()
            continue
        k = th.text.translate({160:' '}).strip()
        try:
            v = tr.find_all("td")[0].text.translate({160:' '}).strip()
            ret[section][k] = v
        except IndexError:
            continue
    return dict(ret)

【讨论】:

    猜你喜欢
    • 2011-03-19
    • 1970-01-01
    • 2014-02-14
    • 2018-01-27
    • 2012-08-25
    • 1970-01-01
    • 2014-07-25
    • 2012-07-31
    • 1970-01-01
    相关资源
    最近更新 更多