用Python爬取维基百科:提取画家实体及对应画作的方法
维基百科API爬取画家相关问题解决方案
1. 移除列表中的非画家条目
核心思路是利用维基百科页面的分类标签——正规的画家条目通常会被归类到包含"Painter"或"painters"的分类中。修改原有代码,在添加页面实例前先做分类校验:
import re import wikipedia paintersListArray = [] check = re.compile("List of painters by name*") for link in dt.links: if check.match(link): try: page = wikipedia.page(link, auto_suggest=False) # 检查页面分类是否包含画家相关关键词 is_painter = any("Painter" in cat or "painters" in cat for cat in page.categories) if is_painter: paintersListArray.append(page) except wikipedia.exceptions.DisambiguationError: # 跳过消歧义页面,也可根据需求进一步筛选 continue except wikipedia.exceptions.PageError: # 跳过不存在的页面 continue
如果分类校验不够精准,还可以通过解析页面的Infobox来判断:画家条目通常会有标识为"painter"的Infobox,可结合BeautifulSoup提取Infobox的标题或类型进行验证。
2. 获取特定画家的所有画作
有两种可靠的实现方式:
方式一:解析维基百科页面内容提取作品
直接抓取画家页面的HTML,定位"Selected works"、"Works"等相关章节,提取其中的作品列表:
from bs4 import BeautifulSoup import wikipedia import re def extract_painter_works(painter_name): works = [] try: page = wikipedia.page(painter_name, auto_suggest=False) soup = BeautifulSoup(page.html(), "html.parser") # 匹配所有包含作品的章节标题 work_section_heads = soup.find_all( "span", class_="mw-headline", string=re.compile("(Selected works|Works|Major works)", re.IGNORECASE) ) for head in work_section_heads: # 遍历章节下的内容,提取列表项 current_node = head.parent.next_sibling while current_node and current_node.name != "h2": if current_node.name == "ul": for li in current_node.find_all("li"): works.append(li.get_text(strip=True)) current_node = current_node.next_sibling return works except Exception as e: print(f"提取作品失败: {str(e)}") return [] # 示例调用 print(extract_painter_works("Abram Arkhipov"))
方式二:通过Wikidata查询作品
维基百科的画家条目大多关联Wikidata条目,其中专门有属性标记画家的作品(属性ID:P180)。通过Wikidata的API可以批量、精准获取作品列表:
import requests def get_works_via_wikidata(painter_name): works = [] # 第一步:获取画家对应的Wikidata QID search_params = { "action": "wbsearchentities", "search": painter_name, "language": "en", "format": "json" } search_res = requests.get("https://www.wikidata.org/w/api.php", params=search_params).json() if search_res.get("search"): qid = search_res["search"][0]["id"] # 第二步:SPARQL查询作品 sparql_query = f""" SELECT ?work ?workLabel WHERE {{ wd:{qid} wdt:P180 ?work. SERVICE wikibase:label {{ bd:serviceParam wikibase:language "en". }} }} """ sparql_params = {"query": sparql_query, "format": "json"} sparql_res = requests.get("https://query.wikidata.org/sparql", params=sparql_params).json() for item in sparql_res["results"]["bindings"]: works.append(item["workLabel"]["value"]) return works # 示例调用 print(get_works_via_wikidata("Abram Arkhipov"))
内容的提问来源于stack exchange,提问作者Mary
相关产品推荐
相关产品推荐

