美文网首页
初级爬虫使用指北(4)--解析网页

初级爬虫使用指北(4)--解析网页

作者: ArthurN | 来源:发表于2018-07-25 13:42 被阅读0次

    目录

    1. 目的
    2. 网页构成
    3. 获取标签里的信息
    4. 解析网页的一般流程
    5. 完整代码
    6. 附加题

    1. 目的

    当获取到指定网页文件(html源代码)后,下一步工作即是要提取出其中所需要的信息。程序的优势在于可以“不知疲倦地”完成某些重复性的工作——这意味着当需求是获取某些具有规律性的重复性的结构化网页时(例如目标网页们都长的差不多),可以让爬虫根据一些 固定规则 抽取网页上的信息。

    这一节即是关于如何编写 固定规则 的内容。


    2. 网页构成:定位,定位,再定位!

    回忆上一节中我获取的网页的数据,我将它打印到屏幕上了,那就像右侧的样子,我想获取的只是这其中很小的一部分信息。

    在屏幕中打印网页

    Chrome浏览器
    所以,我开始利用浏览器的辅助工具帮我在这些数据中找到我需要的信息。
    使用Chrome浏览器,在页面上点击右键(Mac触摸板 两只手指按下去),点击“检查”功能。

    分析国民级网站-百度一下

    “检查”功能
    浏览器就会出现“检查”对应的功能板。
    现在我想提取百度首页右上角的栏目信息,包括栏目名称和对应的链接(图中左侧的红色方框),这些信息存储在网页对应的标签信息中(图中右侧的红色方框)。

    Chrome浏览器-"检查"功能

    HTML标签
    可以通过以下的标签顺序提取出这些信息,例如,“新闻”。

    <body><div id="wrapper"><div id="head"><div class="head_wrapper"><div id="u1"><a href="https....." name="...." class="mnav"> 新闻 </a>
    

    3. 获取标签里的信息:你猜我会怎么提取目标信息

    使用爬虫解析网页数据,获取目标信息

    """
    上一节中我们是这样做的
    data = requests.get("www.baidu.com", headers=headers)
    print(data.text)
    让我们继续
    """
    from bs4 import BeautifulSoup
    
    html =  data.content
    soup = BeautifulSoup(html,'lxml')
    titles = soup.select("div#wrapper > div#head > div.head_wrapper > div#u1 > a.mnav")
    titles[0].get_text
    titles[0].get("href")
    

    对比目标信息的标签,有什么发现吗?

    <body><div id="wrapper"><div id="head"><div class="head_wrapper"><div id="u1"><a href="https....." name="...." class="mnav"> 新闻 </a>
    

    当然有!

    • 提取 <div id="head"> 使用div#head
    • 提取 <a class="mnav"> 使用 a.mnav

    BeautifulSoup是什么?
    美丽汤是一个Python用于解析网页的包,记得在命令行中使用pip3 install bs4进行预先安装。

    使用美丽汤解析网页后,必须使用soup来命名生成的对象吗?
    要是心情不好,我可能就直接s = BeautifulSoup(html,'lxml')


    4. 解析网页的一般流程

    使用爬虫获取目标信息的过程一般可以包括这些:

    • 使用浏览器“检查”功能定位目标信息(初级爬虫使用指北 (4) 第二节)
    • 使用爬虫获取网页数据(初级爬虫使用指北 (3) )
    • 使用爬虫解析网页数据,获取目标信息(初级爬虫使用指北 (4) 第三节)

    5. 完整代码

    现在我来完成一次获取网页+解析网页的过程。

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    """
    Created on Wed Jul 25 13:15:14 2018
    
    @author: alfonso
    """
    # ------- obtain html data 指北(3)
    import requests
    url = 'http://www.baidu.com'
    headers = {
        'User-Agent': 'Chrome/53.0.2785.143',
        'Connection': 'keep-alive',
        'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
    }
    html = requests.get(url, headers=headers)  # 这里我改变了一个变量名称
    # ------- mining html 指北(4)
    # 1. 导入相关包
    from bs4 import BeautifulSoup
    
    # 2. 使用 BeautifulSoup 解析网页
    soup = BeautifulSoup(html.content, 'lxml')
    
    # 3. 使用CSS选择器,传入解析规则
    titles = soup.select(
        "div#wrapper > div#head > div.head_wrapper > div#u1 > a.mnav")
    
    # 4. 打印出自己所需的信息
    print("先看看一共获取到了哪些数据")
    print(titles)
    print() # 打印一个空行,作用类似于留空一行
    print("获取一个标题试试")
    print(titles[0].get_text)
    print()
    print("获取这个标题对应的链接试试")
    print(titles[0].get("href"))
    print()
    
    运行后的样子

    6. 附加题

    美丽汤的功能非常强大,如果你真有兴趣的话,可以百度一下它的官方文档(应该有中文版的),或者看看以下我的笔记。
    网页源代码

    <div class="text">
        <em class="f14 l24">
            <a target="_blank" class="linkto" href="http://news.qq.com/a/20170104/000968.htm">台拟将蔡英文贺岁春联“自自冉冉”一词列入辞典
            </a>
        </em>
    </div>
    

    相关BeautifulSoup操作

    • 节点选择器
    • 方法选择器
    • CSS选择器

    Let's go

    • 节点选择器
    # coding:utf-8
    from bs4 import BeautifulSoup
    """
    使用 div.text # <div, class="text">
    """
    soup = BeautifulSoup(html,'lxml')
    
    news_titles = soup.select("div.text > em.f14 > a.linkto")# 使用select选择器,返回一个列表,包括所有符合的元素
    news_titles[0].get_text() # "台拟将蔡英文贺岁春联“自自冉冉”一词列入辞典"
    news_titles[0].get("href") # "http://news.qq.com/a/20170104/000968.htm"
    
    '''
    a1 > a2 父节点为a1的所属有a2元素
    a1#nodeID, 选择 <a1, id="nodeID"> </a1>
    a1[nodeID], 选择 <a1, attr="nodeID"> </a1>
    其他参见https://cuiqingcai.com/5476.html
    '''
    
    ## 名称 name
    soup.title.name # title 利用name属性获取节点的名称
    
    ## 属性 attrs
    print(soup.p.attrs) #{'class': ['title'], 'name': 'dromouse'}
    print(soup.p.attrs['name']) #dromouse
    
    ## 获取内容 string
    print(soup.p.string) # 利用string属性获取节点元素包含的文本内容
    
    ## 关联
    ### 子孙节点
    soup.p.contents #返回结果是列表形式,得到的结果是直接子节点的列表
    
    soup.p.children # 返回结果是生成器
    for i, child in enumerate(soup.p.children): 
        print(i, child)
    
    # contents 和 children 作用相同
    
    # 获得所有子孙节点
    soup.p.descendants# 返回结果是生成器
    for i, child in enumerate(soup.p.descendants):
        print(i, child)
    
    ### 祖先节点
    soup.a.parent # 获取直接父节点,生成器类型 
    soup.a.parents # 所有祖先节点,生成器类型 
    # 用列表输出了它的索引和内容
    print(list(enumerate(soup.a.parents)))
    
    ### 兄弟节点
    print('Next Sibling', soup.a.next_sibling)
    print('Prev Sibling', soup.a.previous_sibling)
    print('Next Siblings', list(enumerate(soup.a.next_siblings)))
    print('Prev Siblings', list(enumerate(soup.a.previous_siblings)))
    '''
    next_sibling和previous_sibling分别获取节点的下一个和上一个兄弟元素,next_siblings和previous_siblings则分别返回所有前面和后面的兄弟节点的生成器。
    '''
    
    • 方法选择器
    ## 方法选择器
    find_all(name , attrs , recursive , text , **kwargs)
    # name = 'ul' 'li' 等标签名称
    # attrs = 字典型 {'id': 'list-1'}
    # 也可以直接使用一些常见的属性
    '''
    print(soup.find_all(id='list-1'))
    print(soup.find_all(class_='element'))
    '''
    
    # text 参数可用来匹配节点的文本,传入的形式可以是字符串,可以是正则表达式对象
    
    print(soup.find_all(text=re.compile('link')))
    
    '''
    find相关的方法
    find_parents()和find_parent():前者返回所有祖先节点,后者返回直接父节点。
    find_next_siblings()和find_next_sibling():前者返回后面所有的兄弟节点,后者返回后面第一个兄弟节点。
    find_previous_siblings()和find_previous_sibling():前者返回前面所有的兄弟节点,后者返回前面第一个兄弟节点。
    find_all_next()和find_next():前者返回节点后所有符合条件的节点,后者返回第一个符合条件的节点。
    find_all_previous()和find_previous():前者返回节点后所有符合条件的节点,后者返回第一个符合条件的节点。
    '''
    
    • CSS选择器
    # 使用CSS选择器
    #需要调用select()方法,传入相应的CSS选择器
    print(soup.select('.panel .panel-heading'))
    print(soup.select('ul li'))
    print(soup.select('#list-2 .element'))
    print(type(soup.select('ul')[0]))
    
    #节点类型是Tag类型,所以获取属性还可以用原来的方法
    for ul in soup.select('ul'):
        print(ul['id'])
        print(ul.attrs['id'])
        print('Get Text:', ul.get_text()) # 效果与.string一样
        print('String:', ul.string) #
    

    相关文章

      网友评论

          本文标题:初级爬虫使用指北(4)--解析网页

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