10《Python 原生爬虫教程》BeatifulSoup 的使用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了10《Python 原生爬虫教程》BeatifulSoup 的使用相关的知识,希望对你有一定的参考价值。

参考技术A 还记得之前我们在第一个爬虫案例中使用过的 BeatifulSoup 吗?这节课我们就来正式学习一下 BeatifulSoup 这个页面提取工具,通过本节课的学习你会熟悉使用 BeatifulSoup 提取常见的网页元素。

使用 Requests 获取到页面源码后,我们需要一种工具来帮助我们结构化这些数据,从而方便我们检索需要的某个或者某些数据内容。BeautifulSoup 库就是这样一种工具,可以很方便我们对数据进行解析和数据的提取。

BeautifulSoup 的名字来源于大家耳熟能详的一部外国名著里面的小说,这部小说的名字叫做《爱丽丝梦游仙境》。从名字就可以看出,发明这个库的作者的目的是为了让使用这个库的人,心情舒畅,使用起来很方便舒适,接口简单人性化。

因为 BeautifulSoup 并不是 Python 内置的库,我们需要额外安装它。我们现在普遍使用的版本是 BeautifulSoup4, 简称作 bs4。

使用 pip 来安装 BeautifulSoup 很简单,打开 CMD 窗口运行下面这条命令:

安装成功后,如图所示:

解析器是一种帮我们结构化网页内容的工具,通过解析器,我们可以得到结构化的数据,而不是单纯的字符,方便我们解析和查找数据。

BeautifulSoup 的解析器有 html.parse,html5lib,lxml 等。BeautifulSoup 本身支持的标准库是 html.parse,html5lib。但是,lxml 的性能非常棒,以及拥有良好的容错能力,现在被广泛的使用。

解析器对比:

安装 lxml 和安装 BeautifulSoup 类似,同样只需一行命令就好:

安装成功后,如下所示:

BeautifulSoup 将 HTML 转换成树形结构,每个节点都是 Python 对象,所有对象可以归纳为 4 种:

下面我们一一来看下这四类对象:

下面我们就来具体使用一下 BeautifulSoup 这个解析工具,我们首先模仿 HTML 页面结构创建一个字符串:

工作中,我们一般经常的使用的方法就是 find_all 方法。但是,除了上述我们讲的 find_all 方法之外,BeautifulSoup 还有其他一些以 find 开头的方法,由于不是经常使用,这里就简单的列举一下,如果同学们感兴趣的话可以自己深入了解下。

多线程Beatiful Soup爬取斗鱼所有在线主播的信息

  最近看了个爬虫的教程,想着自己也常在斗鱼看直播,不如就拿它来练练手。于是就写了个爬取斗鱼所有在线主播的信息,分别为类别、主播ID、房间标题、人气值、房间地址。

  需要用到的工具python3下的bs4,requests,pymongo。我用的IDE是pycharm,感觉这个软件实在太强大,有点离开它什么都不会的感觉,数据库Mongodb,结合pycharm工具可以直接在右侧显示数据。

#-*- coding:utf-8 -*-
from bs4 import BeautifulSoup
import requests, time ,datetime
import json
import pymongo

class douyu_host_info():
    def __init__(self):
        self.date_time = datetime.datetime.now().strftime(%Y-%m-%d_%H-%M)
        self.host_url = https://www.douyu.com
        self.list_data = []
        self.urls_list = []
        self.headers = {
        User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36,
        }
    def get_url(self):
        #获取所有类别的网站地址
        urls = https://www.douyu.com/directory
        data = requests.get(urls)
        Soup = BeautifulSoup(data.text, lxml)
        list = Soup.select(.r-cont.column-cont  dl  dd  ul  li  a)
        for i in list:
            urls = i.get(href)
            self.urls_list.append(urls)
        print (self.urls_list)
        return self.urls_list

    def get_info(self, url):
        #查询所需信息并写调用写入数据库及本地磁盘的函数
        time.sleep(1) #避免服务器承压过大,每个网站爬取设置1s间隔
        url = self.host_url + url
        print (Now start open {}.format(url))
        get_data = requests.get(url, headers=self.headers)
        Soup = BeautifulSoup(get_data.text, lxml)
        names = Soup.select(.ellipsis.fl)
        nums = Soup.select(.dy-num.fr)
        titles = Soup.select(.mes h3)
        hrefs = Soup.select(#live-list-contentbox  li  a)
        #网站中带directory时只是一个分类页面没有主播信息
        if directory in url:
            pass
        #异常处理,有少数类别的HTML元素有差别,这里就舍弃了
        try:
            category = Soup.select(.listcustomize-topcon-msg h1)[0].get_text()
        except:
            category = 秩名类别
        for name, num, href, title in zip(names, nums, hrefs, titles):
            data = {
                类别: category,
                主播: name.get_text(),
                标题: title.get_text().split(
)[-1].strip(),
                链接: https://www.douyu.com + href.get(href),
                #把人气指数转换成以万为单位的浮点型,方便后面计算查找
                人气指数: float(num.get_text()[:-1]) if in num.get_text() else float(num.get_text())/10000,
            }
            if data[人气指数] > 2:
                print (data)
                self.w_to_local(data)
                self.w_to_db(data)


    def open_data(self, date_time):
        #需要用到时可以输入指定时间点读取本地保存的数据
        with open(D:douyu_host{}.csv.format(date_time), r) as r_data:
            r_data = json.load(r_data)
            for i in r_data:
                print (i)

    def w_to_local(self,data):
        #在将数据写入数据库的同时在本地磁盘保存一份
        with open(D:douyu_host{}.csv.format(self.date_time), a) as w_data:
            json.dump(data, w_data)

    def w_to_db(self, data):
        #将数据写入一个以时间为后缀的数据库表, data需要是字典格式
        client = pymongo.MongoClient(localhost, 27017)
        walden = client[walden_{}.format(self.date_time)]
        sheet_tab = walden[sheet_tab]
        if data is not None:
            sheet_tab.insert_one(data)

    def check_from_db(self, date_time):
        #输入时间从数据库查询相关人气信息
        client = pymongo.MongoClient(localhost, 27017)
        walden = client[walden_{}.format(date_time)]
        sheet_tab = walden[sheet_tab]
        for data in sheet_tab.find({人气指数:{$gte:40}}):
            print (data)

  本来没想用类来写的,后来发现很多数据传来传去很乱,而且重要的数据存储时间不好统一,于是就写在一个类里了。里面很关键的一点,用select模块选取元素路径,如下图。

技术分享图片

  复制出来的是很长的一段路径,可以慢慢观察选取主要的关键字段就好了。

  然后新建一个py文件用来调用之前写好的类,实例化后,用pool多线程运行,结果就出来了。

#-*- coding:utf-8 -*-
import time
from multiprocessing import Pool
from test0822 import douyu_host_info

douyu = douyu_host_info()


if __name__ == __main__:
    #多线程爬取数据
    urls_list = douyu.get_url()
    pool = Pool()
    pool.map(douyu.get_info, urls_list)

来个运行后的全景图。

技术分享图片

 


以上是关于10《Python 原生爬虫教程》BeatifulSoup 的使用的主要内容,如果未能解决你的问题,请参考以下文章

15《Python 原生爬虫教程》爬虫和反爬虫

2019最新Python学习教程(Python学习路线_Python爬虫教程)爬虫工程师必备的10个爬虫工具

Beatiful Soup

Python爬虫圈最抗打的专栏教程,《Python爬虫120例》教程导航帖(2022.10.7更新)

Python爬虫圈最抗打的专栏教程,《Python爬虫120例》教程导航帖(2022.10.7更新)

Python爬虫圈最抗打的专栏教程,《Python爬虫120例》教程导航帖(2022.10.7更新)