爬虫

作者: 咻咻咻滴赵大妞 | 来源:发表于2018-12-23 13:52 被阅读0次

    Day1

    1.什么是爬虫?

    网络爬虫(又被称为网络蜘蛛,网络机器人)是一种按照一定的规则,自动抓取万维网信息的程序或者脚本。

    2.爬虫的作用?

    搜索引擎
    商品比价
    知乎数据分析平台

    3.网页的三大特征?

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

    4.爬虫的流程?

    1)分析网站,得到目标url
    2)根据url发起请求,获得页面源码
    3)从源码中提取数据,提取到目标数据,做数据的筛选和持久化存储
    ,从页面中提取新的url地址,继续执行第二部操作
    4)爬虫结束:所有的目标url都已经提取完毕,并且得到数据,再灭有其他的请求人物,这时意味着爬虫结束

    5.爬虫的分类?

    1.通用爬虫:是搜索引擎的重要组成部分
    1)主要目的?
    是将互联网上的网页下载到本地,经过预处理(去噪,分词,去广告等),最终将数据存储到本地,形成一个互联网内容的镜像
    2)通用爬虫的缺点?
    a.必须遵守robot协议,就是一个网页爬取的规范,告诉爬取者,哪些目录下的资源允许爬取,哪些不允许
    b.搜素引擎返回的都是网页,90%都是无需用的数据
    c.不能够根据不同的用户需求或者见多结果返回不同的结果
    d.通用爬虫对于媒体的文件不能够获取
    2.聚焦爬虫:是面向特定主题需求的一种网络爬虫程序

    6.OSI七层协议:

    • 应用层:用户的应用程序提供网络服务(http,https,ftp...)
    • 表示层:负责端到端的数据信息可以被另一个主机所理解和识别,按照一定的格式将信息传递给会话层。
    • 会话层:会话层管理主机之间的会话进程,即负责建立、管理、终止进程之间的会话.
    • 传输层:(tcp/udp)进行数据传输
      TCP 和 UDP 对比
      传输方式上: 面向连接的 非面向链接的

    传输数据: 数据流 数据包(可能出现丢包)

    传输效率: 慢 快

    传输稳定性: 高 低
    """

    • 网路层:路由器
    • 数据链路层:网桥,交换机
    • 物理层:网卡,网线,集线器,中继器,调制解调器

    2.发起请求
    携带请求头:User-Agent:模拟浏览器进行请求
    Cookies:存储在浏览器里面的,使用cookie表明用户身份
    Refere:说明当前的请求是从哪个页面发起的

    3.str和bytes数据类型
    python2中:对于字符串和bytes类型的数据没有明显的区分
    python3中:有明显区分,将bytes类型的数据转换为字符串使用decode('编码类型')
    将字符串转换为bytes类型使用encode('编码类型')

    bytearray和bytes类型的数据是有区别的:bytearray是可变的。(通过切片的方式,一个字符占2个字节。)
    常见的字符集的编码类型:utf-8 gbk gb2312

    Day2

    1.使用不同的UA发起请求

    User_Agent里面放一些不同的数据,调用random.choice方法,每次获取不同的UA

    2.使用随机UA发起请求

    from fake_useragent import UserAgent
    User_agent = UserAgent()#实例化UA对象
    #随机获取
    Print(user_agent.random)
    

    3.get请求url中含有中文

    From urllib import parse,requets
    #quote将中文转化为URL能够识别的编码格式
    quote_str = parse.quote(kw)
    print(quote_str)
    
    #将url编码格式转化为中文
    unqute_str = parse.unquote(quote_str)
    print(unqute_str)
    # 将字典类型的参数转化为url编码格式
    parmars = {
        'wd': kw,
        'pn':(page-1)*10,
    }
    result = parse.urlencode(parmars)
    print(result)
    

    4.urllib_post请求

    from urllib import parse,request
    
    url = 'https://httpbin.org/post'
    
    #表单数据
    fordata = {
        'name':'赵文竹',
        'age':18,
        'gender':'女',
    }
    #先使用urlencode将参数转为url编码格式的字符串,然后使用encode()将字符串转换为bytes类型的参数
    formdata = parse.urlencode(fordata).encode()
    
    #不需要添加请求头
    response= request.urlopen(url,data=formdata)
    print(response.status)
    print(response.read().decode('utf-8'))
    
    #设置请求头
    req_header = {
        'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36',
    }
    
    req = request.Request(url,headers=req_header,data=formdata)
    response = request.urlopen(req)
    print(response.status)
    

    5.正则表达式:

    实际上爬虫一共就四个主要步骤:
    明确目标 (要知道你准备在哪个范围或者网站去搜索)
    爬 (将所有的网站的内容全部爬下来)
    取 (去掉对我们没用处的数据)
    处理数据(按照我们想要的方式存储和使用)
    目的 给定一个正则表达式和另一个字符串,我们可以达到如下的目的:

    Day3

    1.urllib_parse

    url.parse :定义了url的标准接口,实现url的各种抽取
    parse模块的使用:url的解析,合并,编码,解码
    使用时需导入

    from urllib import parse

    • urlparse()实现URL的识别和分段
    url = 'https://book.qidian.com/info/1004608738?wd=123&page=20#Catalog'
    """
    url:待解析的url
    scheme='':假如解析的url没有协议,可以设置默认的协议,如果url有协议,设置此参数无效
    allow_fragments=True:是否忽略锚点,默认为True表示不忽略,为False表示忽略
    """
    result = parse.urlparse(url=url,scheme='http',allow_fragments=True)
    
    print(result)
    print(result.scheme)
    """
    (scheme='https', netloc='book.qidian.com', path='/info/1004608738', params='', query='wd=123&page=20', fragment='Catalog')
    scheme:表示协议
    netloc:域名
    path:路径
    params:参数
    query:查询条件,一般都是get请求的url
    fragment:锚点,用于直接定位页
    面的下拉位置,跳转到网页的指定位置
    
    • urlunparse()可以实现URL的构造
    url_parmas = ('https', 'book.qidian.com', '/info/1004608738', '', 'wd=123&page=20', 'Catalog')
    #components:是一个可迭代对象,长度必须为6
    result = parse.urlunparse(url_parmas)
    print(result)
    
    """
    https://book.qidian.com/info/1004608738?wd=123&page=20#Catalog
    """
    
    • urljoin()传递一个基础链接,根据基础链接可以将某一个不完整的链接拼接为一个完整链接
    base_url = 'https://book.qidian.com/info/1004608738?wd=123&page=20#Catalog'
    sub_url = '/info/100861102'
    
    full_url = parse.urljoin(base_url,sub_url)
    
    print(full_url)
    
    • urlencode()将字典构形式的参数序列化为url编码后的字符串
    parmas = {
    'wd':'123',
    'page':20
    }
    parmas_str = parse.urlencode(parmas)
    
    print(parmas_str)
    
    """
    page=20&wd=123
    """
    
    • parse_qs()将url编码格式的参数反序列化为字典类型
    parmas_str = 'page=20&wd=123'
    parmas = parse.parse_qs(parmas_str)
    print(parmas)
    
    """
    {'page': ['20'], 'wd': ['123']}
    """
    
    • quote()可以将中文转换为URL编码格式
    word = '中国梦'
    url = 'http://www.baidu.com/s?wd='+parse.quote(word)
    print(parse.quote(word))
    print(url)
    
    """
    %E4%B8%AD%E5%9B%BD%E6%A2%A6
    http://www.baidu.com/s?wd=%E4%B8%AD%E5%9B%BD%E6%A2%A6
    """
    
    • unquote:可以将URL编码进行解码
    url = 'http://www.baidu.com/s?wd=%E4%B8%AD%E5%9B%BD%E6%A2%A6'
    print(parse.unquote(url))
    """
    http://www.baidu.com/s?wd=中国梦
    """
    

    2.urllib 的异常错误处理

    URLError:

    来自urllib库的error模块,继承自OSError,由request模块产生的异常都可以通过捕捉这个类来处理.
    产生的原因主要有:

    • 没有网络连接
    • 服务器连接失败
    • 找不到指定的服务器
    from urllib import error,request
    
    def check_urlerror():
    """
    没有网络
    服务器连接失败
    找不到指定的服务器
    
    reason:返回错误原因
    """
    req_url = 'https://www.baiduxxx.com/'
    
    try:
    response = request.urlopen(url=req_url)
    print(response.status)
    except error.URLError as err:
    """
    1.[Errno -3] Temporary failure in name resolution:
    (没有网络)无法解析域名,即DNS解析配置出现问题
    2.[Errno -2] Name or service not known:
    未知的服务器,找不到服务器
    
    3.timed out
    请求超时
    """
    print('===',err.reason)
    

    HTTPError

    • HTTPError是URLError的子类,我们发出一个请求时,服务器上都会对应一个response应答对象,其中它包含一个数字"响应状态码"。
    • 专门用来处理HTTP请求错误,比如未认证,页面不存在等
    • 有三个属性:
      code:返回HTTP的状态码
      reason:返回错误原因
      headers:返回请求头

    注意,urllib可以为我们处理重定向的页面(也就是3开头的响应码),100-299范围的号码表示成功,所以我们只能看到400-599的错误号码。

    def check_httperror():
    """
    处理认证或则请求失败的错误
    例如:出现404表示页面未找到等
    code:返回的HTTP状态码
    reason:返回的错误原因
    headers:返回的请求头
    :return:
    """
    req_url = 'https://www.qidian.com/all/nsacnscn.htm'
    
    try:
    response = request.urlopen(url=req_url)
    print(response.status)
    except error.HTTPError as err:
    """
    Not Found (reason)
    404 (code)
    Server: nginx (headers)
    Date: Mon, 19 Nov 2018 13:36:11 GMT
    Content-Type: text/html; charset=utf-8
    Content-Length: 15616
    Connection: close
    """
    print('===', err.reason,err.code,err.headers)
    

    改进版

    因为HTTPError的父类是URLError,所以我们更好的处理顺序应该是先捕获子类的错误,再捕获父类的错误

    from urllib import request,error
    
    def check_error():
    """
    因为HTTPError的父类是URLError,所以我们更好的处理顺序应该是
    先捕获子类的错误,再捕获父类的错误
    """
    
    req_url = 'https://www.baiduxxx.com/'
    
    try:
    response = request.urlopen(url=req_url)
    print(response.status)
    except error.HTTPError as err:
    print(err.code,err.reason,err.headers)
    except error.URLError as err:
    print('===', err.reason)
    

    下面是常见的HTTP状态码:

    • 200 - 请求成功
    • 301 - 资源(网页等)被永久转移到其它URL
    • 302 - 资源(网页等)被临时转移到其它URL
    • 401 - 未授权
    • 403 - 禁止访问
    • 408 - 请求超时
    • 404 - 请求的资源(网页等)不存在
    • 500 - 内部服务器错误
    • 503 - 服务器不可用

    3.Handler处理器 和 自定义Opener

    基本的urlopen()方法不支持代理、cookie等其他的HTTP/HTTPS高级功能。所以要支持这些功能:

    1. 使用相关的 Handler处理器 来创建特定功能的处理器对象;
    2. 然后通过 urllib.request.build_opener()方法使用这些处理器对象,创建自定义opener对象;
    3. 使用自定义的opener对象,调用open()方法发送请求。
    import urllib.request
    
    # 构建一个HTTPHandler 处理器对象,支持处理HTTP请求
    http_handler = urllib.request.HTTPHandler()
    
    # 构建一个HTTPHandler 处理器对象,支持处理HTTPS请求
    # http_handler = urllib.request.HTTPSHandler()
    
    # 调用urllib.request.build_opener()方法,创建支持处理HTTP请求的opener对象
    opener = urllib.request.build_opener(http_handler)
    
    # 构建 Request请求
    request = urllib.request.Request("http://www.baidu.com/")
    
    # 调用自定义opener对象的open()方法,发送request请求
    response = opener.open(request)
    
    # 获取服务器响应内容
    print (response.read().decode())
    

    如果在 HTTPHandler()增加 debuglevel=1参数,还会将 Debug Log 打开,这样程序在执行的时候,会把收包和发包的报头在屏幕上自动打印出来,方便调试,有时可以省去抓包的工作。仅需要修改的代码部分:

    4.ProxyHandler处理器用来设置代理

    urllib.request中通过ProxyHandler来设置使用代理服务器,下面代码说明如何使用自定义opener来使用代理:

    from urllib import request,error
    
    #构建支持代理的handler
    proxy = {
    'http':'61.138.33.20:808',
    'https':'120.69.82.110:44693',
    }
    proxy_handler = request.ProxyHandler(proxies=proxy)
    
    # 构建一个私密代理Handler,需要加上私密代理账户的用户名和密码
    # authproxy = {
    # "http" :"username:password@61.135.217.7:80"
    #}
    # authproxy_handler=urllib.request.ProxyHandler(
    # proxies=authproxy
    #)
    
    #根据proxy_handler实例化一个opener对象
    opener = request.build_opener(proxy_handler)
    
    url = 'http://www.baidu.com/'
    
    # 使用https://httpbin.org/get接口验证使用了代理
    # url = 'https://httpbin.org/get'
    
    try:
    response = opener.open(url,timeout=5)
    print(response.status)
    except error.HTTPError as err:
    print(err.reason)
    except error.URLError as err:
    print(err.reason)
    
    # 1. 如果按照上面代码,只有使用opener.open()方法发送
    请求才使用自定义的代理,而urlopen()则不使用自定义代理。
    response = opener.open(request)
    
    # 2. 将自定义的opener设置为全局的opener,之后所有的,不管是
    opener.open()还是urlopen() 发送请求,都将使用自定义代理。
    # request.install_opener(opener)
    # response = urlopen(request)
    

    5.urllib_cookie设置

    Cookie 是指某些网站服务器为了辨别用户身份和进行Session跟踪,而储存在用户浏览器上的文本文件,Cookie可以保持登录信息到用户下次与服务器的会话。

    获取到一个有登录信息的Cookie模拟登陆
    # -*- coding:utf-8 -*-
    import urllib.request
    
    url = 'https://www.douban.com/people/175417123/'
    
    #根据刚才的登录信息来构建一个已经登录过的用户的headers信息
    
    headers = {
    'User-Agent':' Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:59.0) Gecko/20100101 Firefox/59.0',
    'Host':'www.renren.com',
    'Cookie':'anonymid=jgoj4xlw-3izsk4; depovince=BJ; jebecookies=62d94404-de1f-450a-919b-a2d9f4c8b811|||||; _r01_=1; JSESSIONID=abchsGLNgne0L8_wz2Emw; ick_login=cf54f2dc-8b0b-417a-96b2-32d4051f7236; jebe_key=02cb19ad-2966-4641-8828-217160ca67a0%7Cba6f6d6ec917200a4e17a85dbfe33a4a%7C1525230975024%7C1%7C1525230982574; t=87a502d75601f8e8c0c6e0f79c7c07c14; societyguester=87a502d75601f8e8c0c6e0f79c7c07c14; id=965706174; xnsid=e1264d85; ver=7.0; loginfrom=null; wp_fold=0',
    }
    
    # 2. 通过headers里的报头信息(主要是Cookie信息),构建Request对象
    request = urllib.request.Request(url, headers=headers)
    
    # 3. 直接豆瓣个人主页(主要是Cookie信息)
    #,判断这是一个已经登录的用户,并返回相应的页面
    response = urllib.request.urlopen(request)
    
    # 4. 打印响应内容
    print (response.read().decode())
    

    6.cookiejar库 和 HTTPCookieProcessor处理器

    在Python处理Cookie,一般是通过cookiejar模块和 urllib模块的HTTPCookieProcessor处理器类一起使用。

    cookiejar模块:主要作用是提供用于存储cookie的对象

    HTTPCookieProcessor处理器:主要作用是处理这些cookie对象,并构建handler对象。

    • cookiejar 库
      该模块主要的对象有CookieJar、FileCookieJar、MozillaCookieJar、LWPCookieJar。其实大多数情况下,我们只用CookieJar(),如果需要和本地文件交互,就用 MozillaCookjar()

    CookieJar:管理HTTP cookie值、存储HTTP请求生成的cookie、向传出的HTTP请求添加cookie的对象。整个cookie都存储在内存中,对CookieJar实例进行垃圾回收后cookie也将丢失。

    # urllib_cookiejar_test1.py
    
    import urllib
    from http import cookiejar
    
    # 构建一个CookieJar对象实例来保存cookie
    cookiejar = cookiejar.CookieJar()
    
    # 使用HTTPCookieProcessor()来创建cookie处理器对象,参数为CookieJar()对象
    handler=urllib.request.HTTPCookieProcessor(cookiejar)
    
    # 通过 build_opener() 来构建opener
    opener = urllib.request.build_opener(handler)
    
    # 4. 以get方法访问页面,访问之后会自动保存cookie到cookiejar中
    opener.open("http://www.baidu.com")
    
    ## 可以按标准格式将保存的Cookie打印出来
    cookieStr = ""
    for item in cookiejar:
    cookieStr = cookieStr + item.name + "=" + item.value + ";"
    
    ## 舍去最后一位的分号
    print (cookieStr[:-1])
    我们使用以上方法将Cookie保存到cookiejar对象中,
    

    MozillaCookjar()

    MozillaCookjar()保存和使用cookie使用使用MozillaCookjar将cookie信息保存到本地的时候需要调用save()方法实现存储save()函数带有两个参数,ignore_discard和ignore_expires。
    *
    ignore_discard: 即保存需要被丢弃的cookie。
    *
    ignore_expires: 即过期的cookie也保存。

    from urllib import request
    from http.cookiejar import MozillaCookieJar
    
    #文件名(该文件用来并保存cookies信息)
    filename = 'cookies.txt'
    
    #声明一个MozillaCookieJar()对象,用来存储cookies
    mz_cookiejar = MozillaCookieJar(filename)
    
    #使用HTTPCookieProcessor实例化cookie处理器对象
    handler = request.HTTPCookieProcessor(mz_cookiejar)
    
    #自定义opener
    opener = request.build_opener(handler)
    
    response = opener.open('http://www.baidu.com/')
    
    #调用save方法将cookies信息存储到本地
    mz_cookiejar.save(ignore_discard=True,ignore_expires=True)
    

    使用MozillaCookjar()加载本地文件中cookies数据,发起请求

    • 使用load()方法加载出本地文件存储的cookies信息
    mz_cookiejar.load(filename)
    
    from urllib import request
    from http.cookiejar import MozillaCookieJar
    
    #文件名(该文件用来并保存cookies信息)
    filename = 'cookies.txt'
    
    #声明一个MozillaCookieJar()对象,用来存储cookies
    mz_cookiejar = MozillaCookieJar(filename)
    
    #加载出本地文件存储的cookies信息
    mz_cookiejar.load(filename)
    
    #打印加载本地coolies后的mz_cookiejar
    print(mz_cookiejar)
    
    #打印出cookie的name和value
    for item in mz_cookiejar:
    print(item.name,item.value)
    
    #使用HTTPCookieProcessor实例化cookie处理器对象
    handler = request.HTTPCookieProcessor(mz_cookiejar)
    
    #自定义opener
    opener = request.build_opener(handler)
    #发起请求
    response = opener.open('http://www.baidu.com/')
    

    相关文章

      网友评论

          本文标题:爬虫

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