php中文网 | cnphp.com

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 611|回复: 0

百科人物爬虫-属性解析

[复制链接]

2667

主题

2674

帖子

9484

积分

管理员

Rank: 9Rank: 9Rank: 9

UID
1
威望
0
积分
6695
贡献
0
注册时间
2021-4-14
最后登录
2024-5-14
在线时间
673 小时
QQ
发表于 2022-1-16 15:40:00 | 显示全部楼层 |阅读模式
词条分析
百科中的人物属性下还有各行业的人物标签,其对应的描述信息也是不同的,所以在做解析前需要提取出通用的字段。
image.png 首先去除《 网络红人、演员、电竞人物、影视幕后人物、音乐人物、明星组合、虚拟人物、体育人物》。

根据剩余人物标签提取特征词:

政治人物:人物履历、职务任免、人物事件、主要贡献、所获荣誉、人物评价
企业人物:人物经历、个人生活、主要贡献、所获荣誉、人物评价
历史人物:人物生平、个人作品、主要成就、轶事典故、史料记载、艺术形象、亲属成员、人物评价
文化任务:人物经历、个人生活、个人作品、主要贡献、获奖记录、人物评价
科学人物:人物经历、个人生活、研究方向、主要成就、所获荣誉、社会任职、人物影响、人物评价
教育人物:人物经历、研究方向、主要成就、获奖记录、社会任职、人物评价
医疗人物:人物经历、研究方向、著作译作、科研成果、获奖情况、学术任职、擅长领域、出诊时间
其他人物:人物经历、主要贡献、所获荣誉、人物评价
其他人物-作家:人物经历、个人生活、出版著作、出版图书、人物评价、所获荣誉
其他人物-科研:人物简介、承担课题、学术成果、奖项荣誉、人物观点、出版作品

经过观察和分析,最终保留以下信息,所以结合人物基本信息栏需要解析的内容有:

中文名、外文名、别名
国籍、民族、籍贯
出生日期、逝世日期
毕业院校、职业、主要成就
性别、职务、学位
人物经历、个人生活、研究方向、成就、获奖|荣誉、任职、影响、评价
页面解析
由于页面数据参差不齐,如何智能解析是百科数据采集的关键。
我构建了一个通用的字段提取器。
[mw_shl_code=applescript,true]import requests,re
from lxml import etree

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36'
}

# 过滤[n]、[n-n]标签
def filter_label(para):
    for label_num in re.findall('\[\d+\]|\[\d+-\d+\]', para):
        para = para.replace(label_num, '')
    return para

def get_item(url):
    doc = requests.get(url,headers=headers).text
    e = etree.HTML(doc)
    item = {}
    item['baike_url'] = url
    # 封面图
    item['baike_pic'] = ''.join(e.xpath('//div[@class="summary-pic"]/a/img/@src'))
    #print("封面图片:",item['pic'])

    # 个人简介
    item['baike_desc'] = ''
    for desc in e.xpath('//div[@class="lemma-summary"]/div[@class="para"]'):
        para = ''.join(desc.xpath('.//text()')).replace('\n','')
        para = filter_label(para)
        item['baike_desc']+=para+'\n'
    #print("人物简介:",item['baike_desc'])

    # 基本信息
    item['baike_basicInfo'] = {}
    dt = e.xpath('//div[@class="basic-info J-basic-info cmn-clearfix"]/dl/dt')
    dd = e.xpath('//div[@class="basic-info J-basic-info cmn-clearfix"]/dl/dd')
    for t,d in zip(dt,dd):
        key =  ''.join(''.join(t.xpath('./text()')).split())
        value =  ''.join(''.join(d.xpath('.//text()')).split())
        item['baike_basicInfo'][key] = value
    #print("基本信息:",item['baike_basicInfo'])

    # 通用提取器
    def parse_label(label):
        re_rule = f'<a name=".*?{label}" class="lemma-anchor " ></a>\n</div>(.*?)<div class="anchor-list ">'
        experiences = re.findall(re_rule, doc, re.S)
        labels = []
        if experiences:
            exper = ''.join(experiences)
            ex = etree.HTML(exper)
            labels = filter_label(''.join(ex.xpath('//div[@class="para"]//text()')))
        return labels

    # 经历
    exper = parse_label('经历')
    if exper:
        exper = exper.split(';')

    # 方向
    field = parse_label('方向')
    if not field:
        field = parse_label('领域')

    # 兼职
    social = parse_label('兼职')
    if social:
        social = social.split(';')

    # 荣誉
    awards = parse_label('荣誉')
    if not awards:
        awards = parse_label('获奖')

    item['baike_experience'] = exper
    item['baike_awards'] = awards
    item['baike_social'] = social
    item['baike_field'] = field
    item['baike_results'] = parse_label('成果')
    item['baike_life'] = parse_label('生活')
    item['baike_affect'] = parse_label('影响')
    item['baike_eval'] = parse_label('评价')
    return item
[/mw_shl_code]
运行测试
如果说你采集的人物有其他比较明显的字段,比如课题、科普、作品等。

可以通过parse_labe增加字段,进行智能解析。
image.png
print(get_item(‘https://baike.baidu.com/item/%E7%8E%8B%E5%85%83%E5%8D%93’))

运行测试:
image.png





上一篇:PHP 文件上传及格式验证
下一篇:因使用 Cookie 引发的 15 亿“天价”罚单
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|php中文网 | cnphp.com ( 赣ICP备2021002321号-2 )

GMT+8, 2024-5-15 05:30 , Processed in 0.179975 second(s), 35 queries , Gzip On.

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2020, Tencent Cloud.

申明:本站所有资源皆搜集自网络,相关版权归版权持有人所有,如有侵权,请电邮(fiorkn@foxmail.com)告之,本站会尽快删除。

快速回复 返回顶部 返回列表