美文网首页Ethical Hackers技术教程我用Python
Python爬虫学习(六)BeautifulSoup来袭

Python爬虫学习(六)BeautifulSoup来袭

作者: 弃用中 | 来源:发表于2017-08-20 23:03 被阅读496次

    在之前的实例中,我们都是用正则表达式来提取我们想要的信息,尤其是在上一节,我们可能写了一个比较长的正则表达式,那有没有更加方便的方式以供我们提取信息呢?
    当然,BeautifulSoup就是一个很好的工具。


    牛刀小试

    为了让大家对BeautifulSoup的方便有个感性的认识,直接上代码比较。
    以下是爬取豆瓣电影Top250的代码:

    import urllib.request
    from urllib.request import Request
    from urllib.parse import urlencode
    import re
    import random
    
    base_url = 'https://www.douban.com/doulist/3936288/'
    pattern = re.compile('<div\sclass="title">\s.*?<a.*?>(.*?)</a>',re.S)
    user_agent = [
        'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)',
        'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
    ]
    for i in range(0,250,25):
        data = {
            'start':i
        }
        data = bytes(urlencode(data),'utf-8')
        headers = {'User-Agent':random.choice(user_agent)}
        requ = Request(base_url,data)
        html = urllib.request.urlopen(requ).read().decode('utf-8')
        results = re.findall(pattern,html)
        for result in results:
            result = re.sub('\n','',result)
            print(result)
    

    下面是使用BeautifulSoup的代码:

    import urllib.request
    from urllib.request import Request
    from urllib.parse import urlencode
    import re
    import random
    from bs4 import BeautifulSoup
    
    base_url = 'https://www.douban.com/doulist/3936288/'
    pattern = re.compile('<div\sclass="title">\s.*?<a.*?>(.*?)</a>',re.S)
    user_agent = [
        'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)',
        'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
    ]
    for i in range(0,250,25):
        data = {
            'start':i
        }
        data = bytes(urlencode(data),'utf-8')
        headers = {'User-Agent':random.choice(user_agent)}
        requ = Request(base_url,data)
        html = urllib.request.urlopen(requ).read().decode('utf-8')
        # 以下为更改内容
        soup = BeautifulSoup(html,'lxml')
        for item in soup.select('.title'):
            a = item.select('a')[0]
            title = a.get_text()
            print(title)
    

    以下为运行结果:


    太长,略去后面的电影

    可以清楚地看到,这碗“靓汤”果然挺好用的!

    下面简单介绍一下BeautifulSoup的使用方法。

    基本使用

    Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.Beautiful Soup会帮你节省数小时甚至数天的工作时间.

    安装

    打开命令行工具,输入pip install beautifulsoup4即可安装。

    已安装显示如图
    安装解析器

    BeautifulSoup除了支持Python标准库中的HTML解析器,还支持一些第三方的解析器。可以使用pip命令安装。

    解析器

    如何使用

    将一段文档传入BeautifulSoup 的构造方法,就能得到一个文档的对象, 可以传入一段字符串或一个文件句柄.
    如演示代码中的soup = BeautifulSoup(html,'lxml')
    我们指定使用lxml解析器解析文档,Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构。

    树形结构
    BeautifulSoup官方文档中有很多详细的资料,这里,只介绍一个搜索文档树的方法find_all()CSS选择器
    find_all()

    该方法搜索出符合过滤器条件的元素,查找到想要查找的文档内容。
    过滤器有很多种,逐一介绍:
    以爱丽丝文档作为例子,

    html_doc = """
    <html><head><title>The Dormouse's story</title></head>
    <body>
    <p class="title"><b>The Dormouse's story</b></p>
    
    <p class="story">Once upon a time there were three little sisters; and their names were
    <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
    <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
    <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
    and they lived at the bottom of a well.</p>
    
    <p class="story">...</p>
    """
    
    from bs4 import BeautifulSoup
    soup = BeautifulSoup(html_doc, 'html.parser')
    
    字符串

    最简单的过滤器是字符串.在搜索方法中传入一个字符串参数,Beautiful Soup会查找与字符串完整匹配的内容,下面的例子用于查找文档中所有的<b>标签:

    soup.find_all('b')
    # [<b>The Dormouse's story</b>]
    
    正则表达式

    如果传入正则表达式作为参数,Beautiful Soup会通过正则表达式的 match() 来匹配内容.下面例子中找出所有以b开头的标签,这表示<body><b>标签都应该被找到:

    import re
    for tag in soup.find_all(re.compile("^b")):
        print(tag.name)
    # body
    # b
    
    列表

    如果传入列表参数,Beautiful Soup会将与列表中任一元素匹配的内容返回.下面代码找到文档中所有<a>标签和<b>标签:

    soup.find_all(["a", "b"])
    # [<b>The Dormouse's story</b>,
    #  <a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
    #  <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>,
    #  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
    
    True

    True可以匹配任何值,下面代码查找到所有的tag,但是不会返回字符串

    for tag in soup.find_all(True):
        print(tag.name)
    # html
    # head
    # title
    # body
    # p
    # b
    # p
    # a
    # a
    # a
    # p
    
    方法

    如果没有合适过滤器,那么还可以定义一个方法,方法只接受一个元素参数 ,如果这个方法返回 True表示当前元素匹配并且被找到,如果不是则反回 False

    下面方法校验了当前元素,如果包含 class属性却不包含id
    属性,那么将返回True

    def has_class_but_no_id(tag):
        return tag.has_attr('class') and not tag.has_attr('id')
    

    将这个方法作为参数传入 find_all()方法,将得到所有<p>标签:

    soup.find_all(has_class_but_no_id)
    # [<p class="title"><b>The Dormouse's story</b></p>,
    #  <p class="story">Once upon a time there were...</p>,
    #  <p class="story">...</p>]
    

    返回结果中只有<p>标签没有<a>标签,因为<a>标签还定义了”id”,没有返回<html><head>,因为<html><head>中没有定义”class”属性.

    CSS选择器

    BeautifulSoup支持大部分的CSS选择器 , 在 Tag或 BeautifulSoup对象的 .select()
    方法中传入字符串参数, 即可使用CSS选择器的语法找到tag:

    soup.select("title")
    # [<title>The Dormouse's story</title>]
    
    soup.select("p nth-of-type(3)")
    # [<p class="story">...</p>]
    

    通过tag标签逐层查找:

    soup.select("body a")
    # [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
    #  <a class="sister" href="http://example.com/lacie"  id="link2">Lacie</a>,
    #  <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
    
    soup.select("html head title")
    # [<title>The Dormouse's story</title>]
    

    更多CSS选择器语法,查看http://www.w3school.com.cn/css/css_selector_type.asp

    以上内容只是官方文档中的一小部分内容,详情请查看:https://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/#

    小技巧

    审查元素

    选择copy selector,我们就把元素的CSS选择复制下来了,也就是说……你再也不用费心思写CSS选择器了!!!

    致谢

    截至到现在,已有1430个人关注了viljw,在此表示万分的感谢,作为一枚24K纯屌丝,从小到大的各种账号都没见过这么多同胞,惶恐惶恐!

    以上,感谢大家的关注!

    相关文章

      网友评论

      • 漁夫:是不是应该把 requ = Request(base_url,data)改为requ = Request(base_url,data,headers)
        要不然就不是伪装成浏览器进行访问了吧?之前爬多个页面的时候,总是直接在url上面进行修改,这次作者让我了解了一个新方法
      • Symbian米汤:学习了

      本文标题:Python爬虫学习(六)BeautifulSoup来袭

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