美文网首页Python爬虫从入门到放弃
python爬虫从入门到放弃之十六:Xpath简化

python爬虫从入门到放弃之十六:Xpath简化

作者: 52d19f475fe5 | 来源:发表于2019-08-05 12:14 被阅读88次
    1. 什么是Xpath
    • 解析XM语言的一种语言(HTML其实是XML的子级),广泛用于解析HTML数据
    • 几乎所有语言都能使用xpath,比如Java和C语言
    • 除了xpath还有其他手段用于XML解析,比如lxml、bs4等

    2. Xpath语法
    • 层级:/直接子级      //跳级
    • 节点:.当前节点      ..当前父节点
    • 属性:@直接属性访问      contains()包含属性访问
    • 索引:[1]第一个、[2]第二个......[last()-1]倒数第二个、[last()]最后一个
    • 文本:text()提取文本

    3. 使用xpath

    在浏览器中是有xpath的,通过在浏览器的练习,可以快速上手

    示例:打开浏览器,打开百度,输入xpath,我们就搜索xpath好了,如下:

    按F12→Element →按ctrl+F

    我们输入一个最简单的xpath://title,找title标签,这时浏览器就帮我们找出来

    用代码实现:

    import requests
    from lxml import etree
    
    r = requests.get('http://www.baidu.com/s?wd=xpath')
    
    html = etree.HTML(r.text)
    print(html,type(html))
    
    title = html.xpath('//title')
    print(title,type(title))
    
    title = html.xpath('//title/text()')
    print(title,type(title))
    

    运行结果:

    <Element html at 0x22e8696fc48> <class 'lxml.etree._Element'>
    [<Element title at 0x22e86b8e548>] <class 'list'>
    ['xpath_百度搜索'] <class 'list'>
    >>> 
    

    可以发现,利用etree.HTML,将字符串转化为Element对象,Element对象具有xpath的方法,返回结果的列表

    //title就是我们找的title标签,如果我们直接去打印它,只能看到它的内存地址

    我们可以通过/text()取出标签中的文本,/@属性名取出属性的值

    接下来我们找一个带属性的标签

    可以看到,//div[@class="FYB_RD"],这就是找一个带属性的标签示例了,我们可以看到它显示只有一个:1 of 1,如果我们直接//div那你会发现出来一大坨,这显然不是我们想要的!

    此时,可以看到"搜索热点"所在的标签在<div class="FYB_RD">子级下的第一个div标签,用//div[@class="FYB_RD"]/div[1]就可以拿到了,我们还可以用属性访问来提取

    代码实现:

    import requests
    from lxml import etree
    
    r = requests.get('http://www.baidu.com/s?wd=xpath')
    
    html = etree.HTML(r.text)
    
    search_hot1= html.xpath('//div[@class="FYB_RD"]/div[1]/@title')
    print(search_hot1)
    
    search_hot2= html.xpath('//div[@class="cr-title opr-toplist1-title"]/@title')
    print(search_hot2)
    
    search_hot3= html.xpath('//div[contains(@class,"opr-toplist1-title")]/@title')
    print(search_hot3)
    

    运行结果:

    ['搜索热点']
    ['搜索热点']
    ['搜索热点']
    >>> 
    

    以上,我们通过三种方式取出这个div标签的title属性的值,最后一种方式包含属性访问的,因为"opr-toplist1-title"并不是class的全部属性值,它只是包含了这一部分,所以要用contains()函数

    接下来看一下节点的问题,在//div[@class="FYB_RD"]后面加上/./..

    可以看到//div[@class="FYB_RD"]/.等价于//div[@class="FYB_RD"],而//div[@class="FYB_RD"]/..则是//div[@class="FYB_RD"]的父亲标签,这里指的是它的父标签,自然是一个,并不代表//div[@class="cr-content "]就是一个,我们试试看

    可以看到//div[@class="cr-content "]找出两个,第二个是//div[@class="FYB_RD"]的父标签

    那么这个.代表的当前节点有什么用途呢?

    其实,它主要用于二次xpath的节点本身,例如我们第一次取出//div[@class="cr-content "],接着取它下面的子孙级,就用上.

    示例代码:

    import requests
    from lxml import etree
    
    r = requests.get('http://www.baidu.com/s?wd=xpath')
    html = etree.HTML(r.text)
    
    content= html.xpath('//div[@class="cr-content "]')[1]
    print(content)
    fyb = content.xpath('./div[@class="FYB_RD"]/@class')
    print(fyb)
    

    运行结果:

    <Element div at 0x2202c7d2948>
    ['FYB_RD']
    >>> 
    

    接下来我们来取出今天的50个搜索热点

    通过在浏览器的测试,我们可以实行一行代码取出50个搜索热点所在的a标签

    代码实现:

    import requests
    from lxml import etree
    
    r = requests.get('http://www.baidu.com/s?wd=xpath')
    html = etree.HTML(r.text)
    search_hot= html.xpath('//div[@class="FYB_RD"]//tbody/tr//a/@title')
    print(search_hot)
    

    这时,我们取出了搜索热点的标题,下面我们点开一个搜索热点

    可以看到,有五家新闻报道,我们来看看怎么取出对应的链接

    代码实现:

    import requests
    from lxml import etree
    
    
    # 获取解析后的页面
    def get_html(url):
        s = requests.Session()
        r = s.get(url)
        html = etree.HTML(r.text)
        return html
    
    # 获取搜索热点
    def get_search_hots():
        html = get_html('http://www.baidu.com/s?wd=xpath')
        search_hots= html.xpath('//div[@class="FYB_RD"]//tbody/tr//a/@title')
        hots_dict={}
        for index,word in enumerate(search_hots):
            print(index,word)
            hots_dict[str(index)] = word
        return hots_dict
    
    
    # 获取搜索热点的提交网址
    def get_hot_url(word):
        url = 'http://www.baidu.com/s?wd='+word
        return url
      
    
    # 获取搜索热点的新闻报道
    def get_news(url):
        html = get_html(url)
        links = html.xpath('//div[@class="c-offset"]/div//a/@href')
        times = html.xpath('//div[@class="c-offset"]/div//span[1]/text()')
        news = html.xpath('//div[@class="c-offset"]/div//span[2]/text()') 
        links = [requests.get(link).url for link in links]
        for new,time,link in zip(news,times,links):
            print(new,time,link)
    
    def run():
        hots_dict = get_search_hots()    
        while True:
            index = input('\n请输入对应的序号查看新闻报道:')
            if index not in hots_dict:
                continue
            word = hots_dict[index]
            url = get_hot_url(word)
            get_news(url)
    
    
    if __name__ == "__main__":
        print('最新的百度热搜如下:\n')
        try:
            run()
        except:
            print('产生异常!爬取失败...')
    

    运行结果:

    最新的百度热搜如下:
    
    0 华为预测十大趋势
    1 潘粤明 绯闻女友
    2 利奇马最大风力
    3 歌手平安喜获二胎
    4 鸿蒙操作系统开源
    5 老赖藏5500万珠宝
    6 青岛发布道歉
    7 郎朗机场亲密挽手
    8 李嫣为王菲画像
    9 李保芳谈茅台涨价
    10 阿sir发来感谢信
    11 首个台风红色预警
    12 9号利奇马台风
    13 华为正式发布鸿蒙
    14 北京奥运会11周年
    15 中兴通讯跌停
    16 柳岩称暧昧不道德
    17 苏州商业街爆炸
    18 买茅台人脸识别
    19 魏大勋否认恋情
    20 中日重启战略对话
    21 TFBOYS报平安
    22 萧亚轩告白粉丝
    23 大润发私罚小偷
    24 香港局势座谈会
    25 小S全家福曝光
    26 陆毅女儿晒自拍
    27 黄明昊坐轮椅现身
    28 比斯利被禁赛5场
    29 网红名字被抢注
    30 刘湘破世界纪录
    31 张馨予妈妈受伤
    32 主持人涂磊道歉
    33 河南6名儿童溺亡
    34 香港两大巴车相撞
    35 使徒行者2上映
    36 魏大勋杨幂
    37 胡歌薛佳凝聚餐
    38 日本偶遇王思聪
    39 香港光头警长回信
    40 七夕情侣扎堆领证
    41 哪吒票房破30亿
    42 潘粤明女友探班
    43 乔碧萝全网黑名单
    44 杭州现七彩祥云
    45 大陆暂停参加金马
    46 易烊千玺红眼航班
    47 苹果遭集体诉讼
    48 范冰冰七夕自拍
    49 中国男篮全新战袍
    
    请输入对应的序号查看新闻报道:0
    前瞻网 1天前 https://baijiahao.baidu.com/s?id=1641285641204066160&wfr=spider&for=pc
    金融界 1天前 https://baijiahao.baidu.com/s?id=1641266819972047150&wfr=spider&for=pc
    网易 1天前 http://news.163.com/19/0808/19/EM32LML800019K82.html
    新京报 1天前 https://baijiahao.baidu.com/s?id=1641286241207755953&wfr=spider&for=pc
    川北在线 18小时前 http://www.guangyuanol.cn/news/roll/2019/0808/983647.html
    
    请输入对应的序号查看新闻报道:
    



    >>>阅读更多文章请点击以下链接:

    python爬虫从入门到放弃之一:认识爬虫
    python爬虫从入门到放弃之二:HTML基础
    python爬虫从入门到放弃之三:爬虫的基本流程
    python爬虫从入门到放弃之四:Requests库基础
    python爬虫从入门到放弃之五:Requests库高级用法
    python爬虫从入门到放弃之六:BeautifulSoup库
    python爬虫从入门到放弃之七:正则表达式
    python爬虫从入门到放弃之八:Xpath
    python爬虫从入门到放弃之九:Json解析
    python爬虫从入门到放弃之十:selenium库
    python爬虫从入门到放弃之十一:定时发送邮件
    python爬虫从入门到放弃之十二:多协程
    python爬虫从入门到放弃之十三:Scrapy概念和流程
    python爬虫从入门到放弃之十四:Scrapy入门使用
    python爬虫从入门到放弃之十五:Scrapy爬取多个页面
    python爬虫从入门到放弃之十六:Xpath简化
    python爬虫从入门到放弃之十七:常见反爬手段

    相关文章

      网友评论

        本文标题:python爬虫从入门到放弃之十六:Xpath简化

        本文链接:https://www.haomeiwen.com/subject/kacedctx.html