zoukankan      html  css  js  c++  java
  • 十三、原生爬虫实战

    一、简单实例

    1、需求:爬取熊猫直播某类主播人气排行

    2、了解网站结构

    分类——英雄联盟——"观看人数"

    3、找到有用的信息

    二、整理爬虫常规思路

    1、使用工具chrome——F12——element——箭头——定位目标元素

    目标元素:主播名字,人气(观看人数)

    2、方法:使用正则表达式提取有用的信息

    主播名字,人气(观看人数)

    总结

    • 爬虫前奏

    1)明确目的

    2)找到数据对应的网页

    3)分析网页的结构找到数据所在的标签位置

    • 步骤

    1)模拟HTTP请求,向服务器发送这个请求,获取到服务器返回给我们的HTML

    2)用正则表达式提取我们要的数据(名字,人气)

    二、断点调试

    我们以如下的一种常见错误,来演示如何通过PyCharm断点追踪的方式发现程序中的错误:

    def foo(bar=[]):
        bar.append('bar')
        return bar
    >>>foo()
    ['bar']
    >>>foo()
    ['bar', 'bar']
    >>>foo()
    ['bar', 'bar', 'bar']

    这里存在一个常见的错误就是误以为:函数在每次不提供可选形参时将参数设置为默认值,也就是本例中的[],一个空的list。

    这里我们便可以通断点调试的方式进行追踪,在每次函数调用(不显示传递形参)时,观察形参值的变化。
    如图所示为:


    这里写图片描述

    下图是以这段为例,来演示如何发现程序中的bug:

    这里写图片描述

    解决方案:

    def foo(bar=None):
        if not bar:
            bar = []
            bar.append('baz')
        return bar
    >>>foo()
    ['baz']
    >>>foo()
    ['baz']

    三、HTML结构分析基本原则

    1、爬虫分析,最重要的一步,找到标签(即左右边界)

    原则:

    1)尽量选择有唯一标识性的标签

    2)尽量选择离目标信息最近的标签

    不同人选择的标签可能不同。

    四、数据提取层级及原则

    1、找到最近的定位标签(肉眼可见)

    有关联的信息作为一组,找离这一组最近的定位标签

    如:示例中的“主播姓名”和“人数”是有关联的,作为一组

    2、判断选择的标签是否是唯一的(需代码验证)

    3、尽量选择可闭合的定位标签

     

    可闭合,是指可将目标信息包裹起来的定位标签。如:<... />

     

    4、代码实战

     1 # coding=utf-8
     2 import re
     3 from urllib import request
     4 
     5 url = 'https://www.panda.tv/all'
     6 r = request.urlopen(url)
     7 htmls = r.read()
     8 
     9 print(type(htmls))  # 打印type,结果是bytes类型
    10 htmls = str(htmls, encoding='utf-8')  # 将bytes转成utf-8
    11 print(htmls)

    运行结果

    Traceback (most recent call last):
      File "E:/pyClass/thirtheen/spider.py", line 12, in <module>
        print(htmls)
    UnicodeEncodeError: 'gbk' codec can't encode character 'xa0' in position 62321: illegal multibyte sequence

    原因是使用的print()是win7系统的编码,但是win7系统的默认编码是GBK,解决方式,增加如下代码

    1 import io
    2 import sys
    3 sys.stdout=io.TextIOWrapper(sys.stdout.buffer,encoding='gb18030')

    优化后代码

    # coding=utf-8
    import re
    from urllib import request
    import io
    import sys
    sys.stdout=io.TextIOWrapper(sys.stdout.buffer,encoding='gb18030')
    
    class Spider():
    
        url = 'https://www.panda.tv/all'
    
        def __fetch_content(self):
            r = request.urlopen(Spider.url)
            htmls = r.read()
            htmls = str(htmls, encoding='utf-8')  # 将bytes转成utf-8
            print(htmls)
            return htmls
    
    
        def go(self):
            self.__fetch_content()
    
    
    
    spider=Spider()
    spider.go()

    五、正则分析HTML

    1、获取root_html

    正则表达式匹配<div class="video-info">和</div>之间的所有字符,有哪些方式?

    匹配所有字符的方式

    1)[sS]*?

    2)[wW]*?

    * 表示任意次

    ?表示贪婪

    2、代码实战

     1 # coding=utf-8
     2 from urllib import request
     3 import re
     4 import io
     5 import sys
     6 sys.stdout=io.TextIOWrapper(sys.stdout.buffer,encoding='gb18030')
     7 
     8 #以下代码解决SSL报错
     9 import ssl
    10 ssl._create_default_https_context = ssl._create_unverified_context
    11 
    12 
    13 class Spider():
    14 
    15     #定义类变量
    16     url = 'https://www.panda.tv/all'
    17     root_html='<div class="video-info">([sS]*?)</div>'  #([sS]*?)匹配任意字符
    18 
    19     #获取服务器响应内容
    20     def __fetch_content(self):
    21 
    22         r=request.urlopen(url=Spider.url)
    23         htmls = r.read()
    24         htmls = str(htmls, encoding='utf-8')  # 将bytes转成utf-8
    25         return htmls
    26 
    27     #分析并获取元素
    28     def __analysis(self,htmls):
    29         root_html=re.findall(Spider.root_html,htmls)
    30         return root_html
    31 
    32 
    33     def go(self):
    34         htmls=self.__fetch_content()
    35         self.__analysis(htmls)
    36 
    37 
    38 spider=Spider()
    39 spider.go()

    遇到的问题:

    1)乱码

    参考python的编码问题整理

    2)SSL错误

    加入如下代码

    import ssl
    ssl._create_default_https_context = ssl._create_unverified_context

    3)类变量的引用

    Spider.root_html

    六、数据精炼

    正则分析获取名字和人数

    1、找到名字的左右边界、找到人数的左右边界

    2、使用正则匹配,从root_html中获取名字和人数,并拼接成字典格式,列表接收

    3、数据精炼——去掉多余的换行和空格(如果有),将value列表转化为str

    代码示例:

     1 # coding=utf-8
     2 from urllib import request
     3 import re
     4 import io
     5 import sys
     6 
     7 sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='gb18030')
     8 
     9 # 以下代码解决SSL报错
    10 import ssl
    11 
    12 ssl._create_default_https_context = ssl._create_unverified_context
    13 
    14 
    15 class Spider():
    16     # 定义类变量
    17     url = 'https://www.panda.tv/all'
    18     root_html = '<div class="video-info">([sS]*?)</div>'  # ([sS]*?)匹配任意字符
    19     name_pattern = '<span class="video-title" title="([sS]*?)">'
    20     number_pattern = '<span class="video-number">([sS]*?)</span>'
    21 
    22     # 获取服务器响应内容
    23     def __fetch_content(self):
    24         r = request.urlopen(url=Spider.url)
    25         htmls = r.read()
    26         htmls = str(htmls, encoding='utf-8')  # 将bytes转成utf-8
    27         return htmls
    28 
    29     # 分析并获取元素
    30     def __analysis(self, htmls):
    31         anchors = []  # 使用list接收
    32         root_html = re.findall(Spider.root_html, htmls)
    33         for html in root_html:
    34             name = re.findall(Spider.name_pattern, html)
    35             number = re.findall(Spider.number_pattern, html)
    36             anchor = {'name': name, 'number': number}  # 组合成需要的字典格式
    37             anchors.append(anchor)
    38 
    39         return anchors
    40 
    41     # 数据精炼——去掉多余的内容,转成需要的格式
    42     def __refine(self, anchors):
    43         l = lambda anchor: {'name': anchor['name'][0], 'number': anchor['number'][0]}  # 上一步得到的name和number是列表类型,需要转成str
    44         return map(l, anchors)
    45 
    46 
    47     def go(self):
    48         htmls = self.__fetch_content()
    49         anchors = self.__analysis(htmls)
    50         anchors=list(self.__refine(anchors))
    51         print(anchors)
    52 
    53 
    54 spider = Spider()
    55 spider.go()

    九、业务处理——排序

  • 相关阅读:
    让IE6 IE7 IE8 IE9 IE10 IE11支持Bootstrap的解决方法
    检测到有潜在危险的 Request.Form 值
    jQuery校验
    C#客户端的异步操作
    泛型(一)
    c#面试题汇总
    多线程(下)
    多线程(上)
    线程篇(二)
    线程篇(一)
  • 原文地址:https://www.cnblogs.com/loveapple/p/9408611.html
Copyright © 2011-2022 走看看