前言:在网络无处不在的今天,大数据的分析与提取也逐渐发展了起来。现在我们使用Python来做一个原生爬虫的小案例——爬取斗鱼直播平台分区下推荐视频播放量的排名,通过这个案例可以回顾前面所学的正则表达式等知识。

原生爬虫步骤:1.模拟请求

​ 2.用标签定位并提取数据(重点是正则表达式的编写)

​ 3.数据精炼

​ 4.业务处理

一.模拟请求

  • 建立Spider类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    from urllib import request

    class Spider():
    url = "https://www.douyu.com/g_LOL"

    def __fetch_content(self):
    r = request.urlopen(Spider.url)
    htmls = r.read()
    #此处断点调试

    def go(self):
    self.__fetch_content()

    spider = Spider()
    spider.go()

    调试结果

    可以看出,需要对htmls进行转码:

    1
    htmls = str(htmls,encoding='utf-8')

    再次调试后报错:

    网上查阅资料后发现,是因为:

    1
    以"b’\x1f\x8b\x08"开头的 ,说明它是gzip压缩过的数据,这也是报错的原因,所以我们需要对我们接收的字节码进行一个解码操作。

    修改代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    from urllib import request
    from io import BytesIO
    import gzip

    class Spider():
    #需要爬虫的URL
    url = "https://www.douyu.com/g_LOL"

    def __fetch_content(self):
    r = request.urlopen(Spider.url)
    #获取HTML字节码
    htmls = r.read()
    buff = BytesIO(htmls)
    f = gzip.GzipFile(fileobj=buff)
    result = f.read().decode('utf-8') #解码

    def go(self):
    self.__fetch_content()

    spider = Spider()
    spider.go()

    调试结果:

    p3

    可以看到,已经爬取到了网页的HTML数据

  • 上面部分可能会遇到的错误与解决方法

    • urllib.error.URLError: urlopen error [SSL: CERTIFICATE_VERIFY_FAILED]

      1
      2
      3
      4
      # 全局取消证书验证

      import ssl
      ssl._create_default_https_context = ssl._create_unverified_context

二.定位数据与提取、业务处理

  • 第一步:观察游览器内HTML数据,尽可能选择闭合标签

    如上图所示,我定位到了包含了主播名字、播放量的数据的div标签

  • 第二步:编写正则表达式,抽取div标签

    1
    2
    root_pattern = '<div class="DyListCover-info">[\s\S]*?</div>'
    #使用re.findall方法

    匹配取得一个列表后,打印其中一个元素验证是否获取成功

    可以看到,我们成功获取了主播"芜湖大司马"的一个视频播放量"224.9万",但还需要精确提取

  • 第三步:在div标签中抽取数据

    1
    2
    #在正则表达式中加入组()标签,即可取出中间内容
    root_pattern = '<div class="DyListCover-info">([\s\S]*?)</div>'

    写名字、播放量的正则表达式(根据有规律的标签定位)

    1
    2
    name_pattern = '<use xlink:href="#icon-user_c95acf8"></use></svg>([\s\S]*?)</h2>'
    number_pattern = '</use></svg>([\s\S]*?)</span><h2 class="DyListCover-user is-template">'

    然后调用函数进行匹配

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    def __analysis(self, htmls):
    root_html = re.findall(Spider.root_pattern, htmls)
    anchors = []
    for html in root_html:
    name = re.findall(Spider.name_pattern, html)
    number = re.findall(Spider.number_pattern, html)
    if name!=[]:
    anchor = {'name':name, 'number':number}
    anchors.append(anchor)
    return anchors

    匹配并打印anchors结果如下

    可以看到,我们已经成功抓取出这部分数据了

  • 第四步:数据精炼

    1
    2
    3
    4
    5
    6
    def __refine(self, anchors):
    l = lambda anchor: {
    'name':anchor['name'][0].strip(), #strip()为python内置函数
    'number':anchor['number'][0] #用于去除字符串前后空格
    }
    return map(l, anchors)
  • 第五步:业务处理(排序)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def __sort(self, anchors):
    anchors = sorted(anchors,key=self.__sort_seed,reverse=True) #第二个参数为key,指定比较大小的元素,第三个参数reverse可调整顺序或倒序排序
    return anchors

    def __sort_seed(self, anchor):
    r = re.findall('\d*',anchor['number'])
    number = float(r[0])

    if '万' in anchor['number']: #将万转换为10000
    number *= 10000

    return number
  • 第六步:打印数据

    1
    2
    3
    4
    5
    def __show(self, anchors):
    # for anchor in anchors:
    # print(anchor['name'] + "-----" + anchor['number'])
    for rank in range(0,len(anchors)):
    print('rank' + str(rank+1) + ': ' + anchors[rank]['name']+' '+ anchors[rank]['number'])

    结果:

以上就是简单的使用Python原生爬虫的一个小案例,虽然成功爬取,但是代码复用性较差(比如只能爬取斗鱼某个区的视频播放量,如果更换其他直播平台要重写正则表达式),可以考虑使用框架(如Scrapy)。