美文网首页
爬虫基础知识总结

爬虫基础知识总结

作者: changzj | 来源:发表于2018-12-23 17:47 被阅读0次

    什么是爬虫

    爬虫:网络爬虫机器人,从互联网自动抓取数据的程序

    爬虫的基本流程

    • 分析网站,得到目标url
    • 根据url,发起请求,获取页面的HTML源码
    • 从页面源码中提取数据
           a.提取到目标数据,做数据的赛选和持久化存储
           b.从页面中提取到新的url地址,继续执行第二部操作
    • 爬虫结束:所有的目标url都提取完毕,并且得到数据了,再也没有其他请求任务了,这是意味着爬虫结束

    网页的三大特征

    1.每一个网页都有一个唯一的url(统一资源定位符),来进行定位
    2.网页都是通过HTML(超文本)文本展示的
    3.所有的网页都是通过HTTP<超文本传输协议>(HTTPS)协议来传输的

    通用爬虫和聚焦爬虫

    通用网络爬虫:是捜索引擎抓取系统(Baidu、Google、Yahoo等)的重要组成部分。主要目的是将互联网上的网页下载到本地,形成一个互联网内容的镜像备份。
    聚焦爬虫:聚焦爬虫是面向主题的爬虫,再爬取数据的过程中会对数据进行筛选
    往往只会爬虫与需求相关的数据

    Robot.txt 是什么,里面的参数是什么意思

    Robots协议:(也叫爬虫协议、机器人协议等),全称是“网络爬虫排除标准”(Robots Exclusion Protocol),网站通过Robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取

    User-agent:(识别是哪家的爬虫
    Allow: 允许爬取的目录
    Disallow: 不允许爬取的目录

    七层协议

    应用层,表示层,会话层,传输层,网络层,数据链路层,物理层

    http和https协议

    http:是用于从网络传送超文本数据到本地浏览器的传送协议
    https:简单讲是HTTP的安全版,在HTTP协议的基础上加入SSL层(HTTP+SSL) 。 SSL(Secure Sockets Layer 安全套接层)主要用于Web的安全传输协议,在传输层对网络连接进行加密,保障在Internet上数据传输的安全。

    url的基本组成部分

    scheme:协议(例如:http, https, ftp)
    host:服务器的IP地址或者域名
    port#:服务器的端口(如果是走协议默认端口,缺省端口80)
    path:访问资源的路径
    query-string:参数,发送给http服务器的数据
    anchor:锚(跳转到网页的指定锚点位置)

    发起一个请求的基本流程

    1、当用户 在浏览器的地址栏中输入一个URL并按回车键之后(会先经过DNS服务将域名解析为ip),浏览器会向HTTP服务器发送HTTP请求。HTTP请求主要分为“Get”和“Post”两种方法。
    2、当我们在浏览器输入URL http://www.baidu.com 的时候,浏览器发送一个Request请求去获取 http://www.baidu.com 的html文件,服务器把Response文件对象发送回给浏览器。
    3、浏览器分析Response中的 HTML,发现其中引用了很多其他文件,比如Images文件,CSS文件,JS文件。 浏览器会自动再次发送Request去获取图片,CSS文件,或者JS文件。
    4、当所有的文件都下载成功后,网页会根据HTML语法结构,完整的显示出来了。

    get请求和post请求的区别

    GET是从服务器上获取数据,
    GET请求参数显示,都显示在浏览器网址上
    POST是向服务器传送数据
    POST请求参数在请求体当中,消息长度没有限制而且以隐式的方式进行发送,通常用来向HTTP服务器提交量比较大的数据

    请求头参数和响应头里面的参数

    请求头:

    1、User-Agent:是客户浏览器的名称
    2、Cookie:浏览器用这个属性向服务器发送Cookie
    3、Referer:表明产生请求的网页来自于哪个URL
    4、Content-Type:POST请求里用来表示的内容类型。
    5、 Host :主机和端口号
    6、X-Requested-With: XMLHttpRequest(表示是一个Ajax异步请求)
    7、Connection (链接类型) Connection:表示客户端与服务连接类型
    8、Upgrade-Insecure-Requests:升级不安全的请求,意思是会在加载 http 资源时自动替换成 https 请求
    9、Accept:指浏览器或其他客户端可以接受的文件类型
    10、Accept-Encoding:指出浏览器可以接受的编码方式。
    11、Accept-Langeuage:指出浏览器可以接受的语言种类
    12、Accept-Charset:指出浏览器可以接受的字符编码

    响应头:

    1、Cache-Control:must-revalidate, no-cache, private。是否需要缓存资源
    2、Connection:keep-alive(保持连接)
    3、Content-Encoding:gzip(web服务器支持的返回内容压缩编码类型)
    4、Content-Type:text/html;charset=UTF-8(文件类型和字符编码格式)
    5、Date:Sun, 21 Sep 2016 06:18:21 GMT(服务器消息发出的时间)
    6、Expires:Sun, 1 Jan 2000 01:00:00 GMT(响应过期的日期和时间)
    7、Pragma:no-cache 这个含义与Cache-Control(是否缓存资源)
    8、Server:Tengine/1.4.6(服务器和服务器版本)
    9、Transfer-Encoding:chunked这个响应头告诉客户端,服务器发送的资源的方式是分块发送的
    10、Vary: Accept-Encoding告诉缓存服务器,缓存压缩文件和非压缩文件两个版本

    请求常见的状态码

    200:请求成功

    301:永久重定向
    302:临时重定向

    400:客户端错误
    401:未授权
    403:服务器拒绝访问
    404:页面未找到
    405:请求方式不对
    408:请求超时

    500:服务器错误
    503:服务器不可用

    bytes类型和str字符串类型的相互转换,bytes和bytearray的区别

    str类型使用encode方法转化为bytes类型 bytes类型通过decode转化为str类型
    bytearray和bytes不一样的地方在于,bytearray是可变的。

    二 .urllib模块的基本使用

    • request: 它是最基本的HTTP请求模块,可以用来模拟发送请求,就像在浏览器中输入网址,然后敲击回车键一样,使用的时候只需要给库方法传入相关的URL和相关的参数即可

    urlopen()的使用:
    1.request.urlopen():使用URLopen方法模拟浏览器发起请求

     # 目标url
    url = 'http://www.baidu.com/'
    # request.urlopen():使用URLopen方法模拟浏览器发起请求
    response = request.urlopen(url)
    """
    url,请求目标url地址
    data=None,默认情况下为none,表示发起的是get请求,不为None,则发起的是一个post请求
    timeout,设置请求的超时时间
    cafile=None,设置证书
    cadefault=False,是否要使用默认证书(默认为false)
    context=None:是一个ssl值,表示忽略ssl认证
    """
    html = response.read()
    z_html = html.decode()
    print(z_html)
    #是一个ssl值,表示忽略ssl认证(如果请求出现了ssl证书认证错误,
    #我们就需要设置ssl._create_unverified_context(),忽略证书认证)
    content = ssl._create_unverified_context()
    response = request.urlopen(url,timeout=10,context=content)
    #从response响应结果中获取参数
    #状态码
    code = response.status
    print(code)
    #获取页面源码的二进制数据
    b_html = response.read()
    print(type(b_html),len(b_html))
    #获取响应的响应头部(response headers)
    res_headers = response.getheaders()
    print(res_headers)
    #获取响应头中指定参数的值
    cookie_data = response.getheader('Set-Cookie')
    print(cookie_data)
    #reason返回一个响应结果的原因
    reason = response.reason
    print(reason)
    
    
    #如果请求要携带请求头
    
    #需要先构建一个request对象
    """
    url:发起请求的url地址
    data=None, 默认情况为None,表示发起的是一个get请求,不为None,则发起的是一个post请求
    headers={},设置请求头(headers对应的数据类型是一个字典)
    origin_req_host=None, (指定发起请求的域)
    unverifiable=False,忽略SSL认证
    method=None:指定发起请求的方式
    """
    req_header = {
        'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
    }
    # url作为Request()方法的参数,构造并返回一个Request对象
    req = request.Request(url,headers=req_header)
    
    #根据构建的req请求对象发起请求
    response = request.urlopen(req)
    
    • User-Agent 用不同的浏览器在发送请求的时候,会有不同的User-Agent头
    from urllib import request
    import random
    # 使用随机ua发起请求
    USER_AGDNTS = [
        'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',
        'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:64.0) Gecko/20100101 Firefox/64.0',
        'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1',
        'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0',
    ]
    
    url = 'http://www.baidu.com/'
    #携带请求头,需要先创建一个Request对象
    # url,:发起请求的url
    # data=None, :默认为None,表示一个get请求
    # headers={}:设置请求头,对应的是一个字典类型的参数
    req_header = {
        'User-Agent':random.choice(USER_AGDNTS)
    }
    #构建一个request对象
    req = request.Request(url,headers=req_header)
    
    #根据Request对象发起请求
    response = request.urlopen(req)
    
    • 使用fakeuseragent随机ua发起请求
    from fakeuseragent import UserAgent
    #实例化一个UA
    user_agent = UserAgent()
    
    #获取google浏览器的ua
    print(user_agent.chrome)
    #获取火狐浏览器的ua
    print(user_agent.firefox)
    #获取safar浏览器的ua
    print(user_agent.safari)
    
    
    • error: 异常处理模块,如果出现请求错误,我们可以使用这个模块来捕获异常,然后进行重试或者其他操作,保证程序不会意外终止.
    # urllib.error:在发起请求过程中,可能会因为各种情况
    # 导致请求出现异常,因而导致代码崩溃,所以要处理这些异常请求
    from urllib import error,request
    
    #error.URLError
    
    def check_urlerror():
        '''
        1.没有网络
        2.服务器连接失败
        3.找不到指定服务器
        :return:
        '''
        url = 'http://www.baiduxxx.com/'
        try:
    
            response=request.urlopen(url,timeout=0.01)
            print(response.status)
        except error.URLError as err:
            # [Errno -2] Name or service not known   未知服务器
            # [Errno -3] Temporary failure in name resolution  没网
            # time out 请求超时
            print(err.reason)
    check_urlerror()
    
    # error.HTTPError 是 URLError的子类
    
    def check_httperror():
        url = 'https://www.qidian.com/all/nsacnscn.htm'
        try:
            response = request.urlopen(url)
            print(response.status)
        except error.HTTPError as err:
            # httperror的三个属性
            # 返回错误原因
            print(err.reason)
            # 状态码
            print(err.code)
            # 响应头
            print(err.headers)
        except error.URLError as err:
            print(err.reason)
    check_httperror()
    
    • parse: 这是一个工具模块,提供了许多url的处理方法,比如拆分,解析,合并等等
    # urllib的parse模块主要是实现url解析,合并,编码,解码
    from urllib import parse
    
    # 实现了url的识别和分段
    url = 'httpsL://www.1712B.com/daxuesheng?name=zs#123'
    '''
    url:要解析和拆分的url
    scheme='':设置协议,只有在url没有协议的情况下才会生效
    allow_fragments=True:是否忽略锚点,默认为True表示不忽略
    '''
    
    result=parse.urlparse(url)
    '''
    (scheme='https'(协议), netloc='www.1712B.com'(域), 
    path='/daxuesheng'(路径), params=''(可选参数), 
    query='name=zhangsan'(查询参数), fragment='123'(锚点))
    '''
    # 取出拆分后的某一个参数
    print(result.scheme)
    # 可以实现url的组合
    data = [sub_str for sub_str in result]
    print('-------',data)
    full_url=parse.urlunparse(data)
    print(full_url)
    
    # parse.urljoin需要传递一个基类url,根据基类将某一个不完整的url拼接完整
    sub_url = '/p/12345'
    base_url= 'httpsL://www.1712B.com/daxuesheng?name=zs#123'
    full_url=parse.urljoin(base_url,sub_url)
    print(full_url)
    
    # 将字典类型参数,序列化为url的编码格式的字符串
    parmars = {
        'name':'张三',
        'class':'1712B'
    }
    result = parse.urlencode(parmars)
    print('urlencode',result)
    
    # 反序列化,将url编码格式的字符串,转为字典类型
    result = parse.parse_qs(result)
    print('parse.parse_qs',result)
    
    # 可以将中文字符,转为url编码格式
    kw = '刚刚'
    result=parse.quote(kw)
    print('quote',result)
    
    # 将url编码进行解码
    result = parse.unquote(result)
    print(result)
    
    # 最常用的 urljoin,urlencode两个方法
    

    正则

    '''
    .:表示匹配除了换行符之外的任意字符
    \:转义字符
    [a - z]: 匹配a - z里面的任意一个字符
    
    \d: 匹配数字 -> [0 - 9]
    \D: 匹配非数字 [ ^\d]
    \s: 匹配空白字符(空格,\n,\t...)
    \S: 匹配非空白字符 
    \w: 匹配单词字符 [A - Za - z0 - 9_]
    \W: 匹配非单子字符
    
    ^:匹配以...开头
    $:匹配以....结尾
    
    (): 分组
    |:或
    
    多字符匹配
    *:匹配*前面的字符任意次数
    +: 匹配+号前面的字符至少1次
    ?: 匹配?前面的字符0次或1次
    {m}: 匹配
    {m}
    前面的字符m次
    {m, n}: 匹配
    {m, n}
    前面的字符m
    ~n次
    
    非贪婪匹配
    * ?
    +?
    ??
    {m, n}?
    '''
    import re
    
    #把正则表达式构建为一个pattern对象
    sub_str = 'abcdefabcd'
    pattern = re.compile('b')
    #从字符串的起始位置开始匹配,开头就必须符合正则规则,
    # 如果匹配到结果了返回结果,如果匹配不到返回None,单次匹配
    result = re.match(pattern,sub_str)
    print(type(result))
    if result:
        print(result.group())
    
    #在整个字符串中进行匹配,同样是单次匹配,匹配到结果立即返回
    #匹配不到则返回None
    result = re.search(pattern,sub_str)
    print(result.group())
    
    # 再整个字符串中进行匹配,匹配出所有符合正则规则的结果,
    # 以列表的形式返回
    result = re.findall(pattern,sub_str)
    print(result)
    
    #再整个字符串中进行匹配,匹配出所有符合正则规则的结果,
    #但是返回的是一个迭代器
    result = re.finditer(pattern,sub_str)
    # <class 'callable_iterator'>
    print(type(result))
    for note in result:
        #<class '_sre.SRE_Match'>
        print(type(note))
        print(note.group())
    #替换re.sub()
    url = 'http://www.baidu.com/s?kw=aaa&pn=20'
    # pattern, \正则规则
    # repl, \要替换的字符串
    # string,原始字符串
    pattern = re.compile('pn=\d+')
    result = re.sub(pattern,'pn=30',url)
    print(result)
    
    #分割re.split()
    pattern = re.compile('[=:&]')
    #pattern, string
    result = re.split(pattern,url)
    print(result)
    

    cookiejar使用

    # 使用cookiejar的目的:管理cookiejar,保存cookie值,
    # 一旦储存cookie后,下一次发起请求的时候就会携带cookie
    # cookie是保存在内存里面的,最后会进行垃圾回收,
    from urllib import request,parse
    from http.cookiejar import CookieJar
    
    #创建cookiejar对象,目的如上
    cookie_jar = CookieJar()
    
    # 自定义HTTPCookieProcessor创建handler处理器
    handler=request.HTTPCookieProcessor(cookie_jar)
    
    # 自定义opener
    opener = request.build_opener(handler)
    

    urllib下使用代理

    • 代理的作用
      1.突破自身IP访问限制
      2.访问一些单位或团体内部资源
      3.提高访问速度
      4.隐藏真实IP

    requests简单使用

    • Requests 继承了urllib的所有特性。Requests支持HTTP连接保持和连接池,支持使用cookie保持会话,支持文件上传,支持自动确定响应内容的编码,支持国际化的URL和 POST 数据自动编码。
    # requsets模块:是对urllib的封装,可以实现urllib的所有功能
    # 并且api调用更加简单方便
    
    import requests
    
    
    # url = 'http://www.baidu.com/'
    url = 'http://www.sina.com/'
    # url 要请求的url目标
    # parms: get请求后面要拼接的参数
    '''
        :param method: 要发起什么类型的请求
        :param url: 要请求的目标url
        :param params: get 后面要拼接的参数
        :param data: Dictionary, post请求的表单数据
        :param json: 传递json数据跟上面的data效果一样
        :param headers: (optional) Dictionary 请求头.
        :param cookies: (optional) Dict or CookieJar object (设置cookies信息模拟用户请求)
        :param files: 上传文件      
        :param auth: 网站要验证的信息(账号和密码).
        :param timeout:设置请求超时时间 (optional)  
        :type allow_redirects: bool,是否允许重定向
        :param proxies: (optional) Dictionary(设置代理) 
        :param verify:  Defaults to ``True``.(忽略认证证书,默认为True表示不忽略)
        
    '''
    # response = requests.get(url)
    
    req_header = {
        'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:59.0) Gecko/20100101 Firefox/59.0'
    }
    parmars = {
        'wd':'豆瓣',
    }
    response = requests.get(url,params=parmars,headers=req_header)
    
    # 从响结果中获取的信息
    # (这里得到解码后的字符串)
    html = response.text
    # 如果使用response.text出现乱码
    # 方式一 response.content.decode('')
    # 方式二 response.encoding=''设置编码类型
    # 获取bytes类型数据
    b_html = response.content
    # 获取状态码
    code = response.status_code
    # 获取响应头
    response_header = response.headers
    # 获取请求头
    req_headers=response.request.headers
    # 当前请求url地址
    current = response.url
    #response.json():可以将json字符串转为python数据类型
    
    

    Xpath与lxml

    • xpath:可以在xml中查找信息,对xml文档中的元素进行属性的提取

    • xml:设计目的是为了传输数据,结构和html相像,是一种标记语言

    • xpath常见语法:

    nodename : 选取此节点的所有子节点
    / : 从根节点开始查找
    // : 匹配节点不考虑节点的位置
    . : 选取当前节点
    .. : 选取当前节点的父节点
    a/@href : 取标签数据
    a/text() : 取标签文本
    a[@class='123'] : 根据class属性寻找标签
    a[@id='123'] : 根据id属性寻找标签
    a[@id='123'][last()] : 取最后一个id为123 的 a标签
    a[@id='123'][postion()<2] : 取前两个id为123的 a标签

    相关文章

      网友评论

          本文标题:爬虫基础知识总结

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