美文网首页
BeautifulSoup模块

BeautifulSoup模块

作者: WeirdoSu | 来源:发表于2017-12-16 19:46 被阅读0次

    Beautiful Soup是一个Python的HTML解析框架,我们可以利用它方便的处理HTML和XML文档。Beautiful Soup有3和4两个版本,目前3已经停止开发。所以我们当然还是学习最新的Beautiful Soup 4.如果需要详细文档的话可以参考Beautiful Soup中文文档,这是难得的不是机翻的文档。

    解析文档

    获取文档

    Beautiful Soup只是一个HTML解析库,所以我们如果想解析网上的内容,第一件事情就是把它下载下来。对于不同的网站,可能会对请求进行过滤。糗事百科的网站就对没有UA的请求直接拒绝掉。所以如果我们要爬这样的网站,首先需要把请求伪装成浏览器的样子。具体网站具体分析,经过我测试,糗事百科只要设置了UA就可以爬到内容,对于其他网站,你需要测试一下才能确定什么设置能管用。

    有了Request对象还不行,还需要实际发起请求才行。下面代码的最后一句就使用了Python3的urllib库发起了一个请求。urlopen(req)方法返回的是Reponse对象,我们调用它的read()函数获取整个结果字符串。最后调用decode('utf-8')方法将它解码为最终结果,如果不调用这一步,汉字等非ASCII字符就会变成\xXXX这样的转义字符。

    import urllib.request as request
    
    user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36'
    headers = {'User-Agent': user_agent}
    req = request.Request('http://www.qiushibaike.com/', headers=headers)
    
    page = request.urlopen(req).read().decode('utf-8')
    

    查询和遍历方法

    有了文档字符串,我们就可以开始解析文档了。第一步是建立BeautifulSoup对象,这个对象在bs4模块中。注意在建立对象的时候可以额外指定一个参数,作为实际的HTML解析器。解析器的值可以指定html.parser,这是内置的HTML解析器。更好的选择是使用下面的lxml解析器,不过它需要额外安装一下,我们使用pip install lxml就可以安装。

    import bs4
    
    soup = bs4.BeautifulSoup(page, "lxml")
    

    有了BeautifulSoup对象,我们就可以开始解析了。首先先来介绍一下BeautifulSoup的对象种类,常用的有标签(bs4.element.Tag)以及文本(bs4.element.NavigableString)。还有注释等对象,不过不太常用,所以就不介绍了。在标签对象上,我们可以调用一些查找方法例如find_all等等,还有一些属性返回标签的父节点、兄弟节点、直接子节点、所有子节点等。在文本对象上,我们可以调用.string属性获取具体文本。

    然后来说说BeautifulSoup的遍历方法。基本所有操作都需要通过BeautifulSoup对象来使用。使用方式主要有两种:

    • 一是直接引用属性,就是soup.title这样的,会返回第一个符合条件的节点;
    • 二是通过查找方法例如find_all这样的,传入查询条件来查找结果。

    再来说说查询条件。查询条件可以是:

    • 字符串,会返回对应名称的节点;
    • 正则表达式,按照正则表达式匹配;
    • 列表,会返回所有匹配列表元素的节点;
    • 真值True,会返回所有标签节点,不会返回字符节点;
    • 方法,我们可以编写一个方法,按照自己的规则过滤,然后将该方法作为查询条件。

    实际例子

    爬取糗事百科段子

    首先打开糗事百科网站,按F12打开开发人员工具,然后在旁边点击分离按钮把它变成独立窗口,然后切到元素标签并最大化窗口。然后点击那个鼠标按钮,再返回糗事百科页面,并点击一个段子,这样就可以查看段子在HTML文档的什么位置了。

    HTML结构

    首先分析一下HTML代码,然后我们就可以查找所需的内容了。这里需要说明一下,查询方法返回的是结果集,对结果集遍历可以得到标签或者文本对象。如果调用标签对象的.contents,会返回一个列表,列表内是标签、文本或注释对象。动态语言的优势就是使用灵活,缺点就是没有代码提示。虽然总共代码没几行,但是还是花了我一番功夫。

    divs = soup.find_all('div', class_='article block untagged mb15')
    for div in divs:
        links = div.find_all('a', href=re.compile(r'/article/\d*'), class_='contentHerf')
        for link in links:
            contents = link.span.contents
            contents = [i for i in contents if not isinstance(i, bs4.element.Tag)]
            print(contents)
    

    上面的代码会输出首页的所有段子。这样我们便实现了半个爬虫。为什么是半个呢?因为一个完整的爬虫可以爬取多个页面,为了简便这里只爬首页,所以只能算半个爬虫。不过如果你想爬取多个页面,代码稍加修改即可实现。

    相关文章

      网友评论

          本文标题:BeautifulSoup模块

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