美文网首页
62.1-爬虫概述、Robots协议

62.1-爬虫概述、Robots协议

作者: BeautifulSoulpy | 来源:发表于2020-08-26 19:56 被阅读0次

    好的生活就是不瞎想,做得多,要得少,常微笑懂知足!


    总结:

    1. HTTP 是基于 socket 通讯的;是 异步请求;
    2. data参数决定是GET还是POST请求:为空采用GET方法;不为空采用POST方法;
    3. 对URL打包,对数据进行解析;

    1. 概述

    当今大数据的时代,网络爬虫已经成为了获取数据的一个重要手段。

    爬虫,应该称为网络爬虫,也叫网页蜘蛛、网络机器人、网络蚂蚁等。
    搜索引擎,就是网络爬虫的应用者。
    为什么到了今天,反而这个词汇被频繁的提起呢?有搜索引擎不就够了吗?
    实际上,大数据时代的到了,所有的企业都希望通过海量数据发现其中的价值。
    所以,需要爬取对特定网站、特定类别的数据,而搜索引擎不能提供这样的功能,因此,需要自己开发爬虫来解
    决。

    2. 爬虫分类

    通用爬虫

    常见就是搜索引擎,无差别的收集数据、存储,提取关键字,构建索引库,给用户提供搜索接口。

    爬取一般流程
    1.初始一批URL, 将这些URL放到待爬取队列
    2.从队列取出这些URL, 通过DNS解析IP, 对IP对应的站点下载HTML页面, 保存到本地服务器中, 爬取完的
    URL放到已爬取队列。
    3.分析这些网页内容, 找出网页里面的其他关心的URL链接, 继续执行第2步, 直到爬取条件结束。

    搜索引擎如何获取一个新网站的URL
    ● 新网站主动提交给搜索引擎
    ● 通过其它网站页面中设置的外链
    ● 搜索引擎和DNS服务商合作, 获取最新收录的网站

    聚焦爬虫

    有针对性的编写特定领域数据的爬取程序,针对某些类别数据采集的爬虫,是面向主题的爬虫

    3. Robots协议(原则)

    指定一个robots.txt文件,告诉爬虫引擎什么可以爬取。

    / 表示网站根目录,表示网站所有目录。
    Allow 允许爬取的目录
    Disallow 禁止爬取的目录
    可以使用通配符

    淘宝 http://www.taobao.com/robots.txt
    马蜂窝 http://www.mafengwo.cn/robots.txt

    User-agent: Baiduspider
    Allow: /article
    Allow: /oshtml
    Allow: /ershou
    Disallow: /product/
    Disallow: /
    
    User-Agent: Googlebot
    Allow: /article
    Allow: /oshtml
    Allow: /product
    Allow: /spu
    Allow: /dianpu
    Allow: /oversea
    Allow: /list
    Allow: /ershou
    Disallow: /
    
    User-agent: Bingbot
    Allow: /article
    Allow: /oshtml
    Allow: /product
    Allow: /spu
    Allow: /dianpu
    Allow: /oversea
    Allow: /list
    Allow: /ershou
    Disallow: /
    
    User-agent: Baiduspider
    Allow: /article
    Allow: /oshtml
    Allow: /ershou
    Disallow: /product/
    Disallow: /
    其它爬虫,不允许爬取
    User-Agent: *
    Disallow: /
    

    这是一个君子协定,“爬亦有道”

    这个协议为了让搜索引擎更有效率搜索自己内容,提供了如Sitemap这样的文件。Sitemap往往是一个XML文件,
    提供了网站想让大家爬取的内容的更新信息。
    这个文件禁止抓取的往往又是可能我们感兴趣的内容,它反而泄露了这些地址。

    301,302

    301,302 都是HTTP状态的编码,都代表着某个URL发生了转移,不同之处在于:
    301 redirect: 301 代表永久性转移(Permanently Moved)。
    302 redirect: 302 代表暂时性转移(Temporarily Moved )。

    4. HTTP请求和响应处理

    其实爬取网页就是通过HTTP协议访问网页,不过通过浏览器访问往往是人的行为,把这种行为变成使用程序来访问。

    4.1 urllib包

    urllib包(最老的爬虫库)
    urllib是标准库,它一个工具包模块,包含下面模块来处理url:
    urllib.request 用于打开和读写url
    urllib.error 包含了由urllib.request引起的异常
    urllib.parse 用于解析url
    urllib.robotparser 分析robots.txt 文件

    Python2中提供了urllib和urllib2。urllib提供较为底层的接口,urllib2对urllib进行了进一步封装。Python3中将
    urllib合并到了urllib2中,并更名为标准库urllib包。

    1. urllib.request模块

    模块定义了在基本和摘要式身份验证、 重定向、 cookies等应用中打开 Url (主要是 HTTP) 的函数和类。

    urlopen方法
    urlopen(url, data=None)
    url是链接地址字符串,或请求类的实例。
    data提交的数据,如果data为None发起GET请求,否则发起POST请求。见 urllib.request.Request#get_method
    返回http.client.HTTPResponse类的响应对象,这是一个类文件对象。

    from urllib import request
    from http.client import HTTPResponse
    
    url = "https://cn.bing.com/"  
    
    response:HTTPResponse = request.urlopen(url)  # 类文件对象;
    
    with response:
        print(1,type(response))     # 类文件对象
        print(2,response.headers)  # 等价 info ()   #  
        print(2,response.info())  # 等价 info ()    # 
        print(3,response.geturl())
        print(4,response.status,response.reason)     
        print(5,response.read())            # 二进制的bytes对象
    #------------------------------------------------------------------------------
    C:\ProgramData\Miniconda3\envs\blog\python.exe C:/Users/dell/PycharmProjects/spiders/t1.py
    1 <class 'http.client.HTTPResponse'>
    2 Cache-Control: private, max-age=0
    Content-Length: 111838
    Content-Type: text/html; charset=utf-8
    Vary: Accept-Encoding
    P3P: CP="NON UNI COM NAV STA LOC CURa DEVa PSAa PSDa OUR IND"
    Set-Cookie: SRCHD=AF=NOFORM; domain=.bing.com; expires=Fri, 26-Aug-2022 02:43:09 GMT; path=/
    Set-Cookie: SRCHUID=V=2&GUID=ECC0C843F1BA4EE7A8D5557520066A17&dmnchg=1; domain=.bing.com; expires=Fri, 26-Aug-2022 02:43:09 GMT; path=/
    Set-Cookie: SRCHUSR=DOB=20200826; domain=.bing.com; expires=Fri, 26-Aug-2022 02:43:09 GMT; path=/
    Set-Cookie: _SS=SID=2FDBF51342FC674231D5FA2143D266D4; domain=.bing.com; path=/
    Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
    X-MSEdge-Ref: Ref A: 1E707EB1AAB64DB69C0FD272FD61B7BD Ref B: BJ1EDGE0221 Ref C: 2020-08-26T02:43:09Z
    Set-Cookie: _EDGE_S=F=1&SID=2FDBF51342FC674231D5FA2143D266D4; path=/; httponly; domain=bing.com
    Set-Cookie: _EDGE_V=1; path=/; httponly; expires=Mon, 20-Sep-2021 02:43:09 GMT; domain=bing.com
    Set-Cookie: MUID=3AC183D8072E6AED16758CEA06006BDE; samesite=none; path=/; secure; expires=Mon, 20-Sep-2021 02:43:09 GMT; domain=bing.com
    Set-Cookie: MUIDB=3AC183D8072E6AED16758CEA06006BDE; path=/; httponly; expires=Mon, 20-Sep-2021 02:43:09 GMT
    Date: Wed, 26 Aug 2020 02:43:08 GMT
    Connection: close
    
    

    上例,通过urllib.request.urlopen方法,发起一个HTTP的GET请求,WEB服务器返回了网页内容。响应的数据被
    封装到类文件对象中,

    通过read方法、readline方法、readlines方法获取数据,
    status和reason属性表示返回的状态码,
    info方法返回头信息,

    User-Agent问题
    上例的代码非常精简,即可以获得网站的响应数据。但目前urlopen方法通过url字符串和data发起HTTP的请求。
    如果想修改HTTP头,例如useragent,就得借助其他方式。

    userAgent

    源码中构造的useragent如下

    # urllib.request.OpenerDirector
    class OpenerDirector:
    def __init__(self):
    client_version = "Python-urllib/%s" % __version__
    self.addheaders = [('User-agent', client_version)]
    

    当前显示为 Python-urllib/3.6
    有些网站是反爬虫的,所以要把爬虫伪装成浏览器。随便打开一个浏览器,复制浏览器的UA值,用来伪装。

    Request类

    Request(url, data=None, headers={})
    初始化方法,构造一个请求对象。可添加一个header的字典。data参数决定是GET还是POST请求
    add_header(key, val) 为header中增加一个键值对。

    from urllib.request import Request, urlopen
    import random
    # 打开一个url返回一个Request请求对象
    # url = 'https://movie.douban.com/' # 注意尾部的斜杠一定要有
    url = 'http://www.bing.com/'
    
    ua_list = [
    "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36",# chrome
    "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN) AppleWebKit/537.36 (KHTML, like Gecko) Version/5.0.1 Safari/537.36", # safafi
    ]
    
    ua=random.choice(ua_list) #pick one
    #ua需要加到请求头中
    request=Request(url)
    request.add_header('User-Agent', random.choice(ua_list) )
    print(type(request) )
    
    response = urlopen(request, timeout=20) # request对象或者url都可以
    print(type(response))
    
    with response:
        print(1, response.status, response.getcode(), response.reason) # 状态,getcode本质上就是返回 status
    
        print(2, response.geturl()) # 返回数据的url。如果重定向,这个url和原始url不一样
        # 例如原始url是http://www.bing.com/,返回http://cn.bing.com/
        print(3, response.info()) # 返回响应头headers
        print(4, response.read()) # 读取返回的内容
    print(5, request.get_header('User-agent'))
    print(6, 'user-agent'.capitalize())
    
    2.urllib.parse模块

    该模块可以完成对url的编解码; 先看一段代码,进行编码(默认UTF-8)

    from urllib import parse
    #  urlencode函数第一参数要求是一个字典或者二元组序列
    u = parse.urlencode({'url':'http://www.magedu.com/python'})
    print(u)
    #---------------------------------------------------
    url=http%3A%2F%2Fwww.magedu.com%2Fpython
    
    /  %2F
    =  3D
    
    
    

    从运行结果来看冒号、斜杠、&、等号、问号等符号全部被编码了,%之后实际上是单字节十六进制表示的值。

    一般来说url中的地址部分,一般不需要使用中文路径,但是参数部分,不管GET还是POST方法,提交的数据中,
    可能有斜杆、等号、问号等符号,这样这些字符表示数据,不表示元字符。如果直接发给服务器端,就会导致接收
    方无法判断谁是元字符,谁是数据了。

    为了安全,一般会将数据部分的字符做url编码,这样就不会有歧义了。
    后来可以传送中文,同样会做编码,一般先按照字符集的encoding要求转换成字节序列,每一个字节对应的十六
    进制字符串前加上百分号即可。

    # 网页使用utf-8编码
    # https://www.baidu.com/s?wd=中
    # 上面的url编码后,如下
    # https://www.baidu.com/s?wd=%E4%B8%AD
    from urllib import parse
    u = parse.urlencode({'wd':'中'}) # 编码
    url = "https://www.baidu.com/s?{}".format(u)
    
    print(url)
    print('中'.encode('utf-8')) # b'\xe4\xb8\xad'
    print(parse.unquote(u)) # 解码
    print(parse.unquote(url))
    ------------------------------------------------------
    https://www.baidu.com/s?wd=%E4%B8%AD
    b'\xe4\xb8\xad'
    wd=中
    https://www.baidu.com/s?wd=中
    
    4.2 提交方法method

    最常用的HTTP交互数据的方法是GET、POST。
    GET方法,数据是通过URL传递的,也就是说数据是在HTTP报文的header部分。
    POST方法,数据是放在HTTP报文的body部分提交的。
    数据都是键值对形式,多个参数之间使用&符号连接。例如a=1&b=abc

    from urllib import request,parse
    from http.client import HTTPResponse
    
    # ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36"
    
    base_url = "https://cn.bing.com/search"
    
    u = parse.urlencode({'q':'马哥教育'})
    url = "{}?{}".format(base_url,u)
    
    req = request.Request(url,headers={'User-agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36"})
    
    with request.urlopen(req) as response:
        with open('./bing.html','wb') as f:   #注意编码;
            f.write(response.read())
    #-------------------------------------------------------
    
    
    GET方法

    连接 必应 搜索引擎官网,获取一个搜索的URL http://cn.bing.com/search?q=马哥教育
    需求 : 请写程序完成对关键字的bing搜索, 将返回的结果保存到一个网页文件

    from urllib import request,parse
    from http.client import HTTPResponse
    
    # ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36"
    # 请求什么返回什么
    url = "http://httpbin.org/get"
    
    req = request.Request(url,headers={'User-agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36"})
    
    with request.urlopen(req) as response:
        print(response.read())
    #------------------------------------------------------------
    b'{\n  "args": {}, \n  "headers": {\n    "Accept-Encoding": "identity", \n    "Host": "httpbin.org", \n    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36", \n    "X-Amzn-Trace-Id": "Root=1-5f463de0-28f2bea1625061d03c4977d3"\n  }, \n  "origin": "117.150.188.202", \n  "url": "http://httpbin.org/get"\n}\n'
    
    
    POST方法

    http://httpbin.org/ 测试网站

    from urllib import request,parse
    from http.client import HTTPResponse
    
    # ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36"
    # 请求什么返回什么
    url = "http://httpbin.org/post"
    
    req = request.Request(url,headers={'User-agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36"})
    
    params = parse.urlencode({
        'id':100,
        'name':'tommy'
    })
    with request.urlopen(req,params.encode()) as response:
        print(response.read())
    #- --------------------------------------------------------------
    b'{\n  "args": {}, \n  "headers": {\n    "Accept-Encoding": "identity", \n    "Host": "httpbin.org", \n    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36", \n    "X-Amzn-Trace-Id": "Root=1-5f463de0-28f2bea1625061d03c4977d3"\n  }, \n  "origin": "117.150.188.202", \n  "url": "http://httpbin.org/get"\n}\n'
    
    处理JSON数据

    查看"豆瓣电影",看到"最近热门电影"的“热门” ;

    热门

    XHR : xml http request
    tag 标签“热门”,表示热门电影
    type 数据类型,movie是电影
    page_limit 表示返回数据的总数
    page_start 表示数据偏移

    通过分析,我们知道这部分内容,是通过A JAX从后台拿到的Json数据。
    访问URL是https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&page_limit=50&page_start=0%E7%83%AD%E9%97%A8
    是utf-8编码的中文“热门” 服务器返回的Json数据50条

    from urllib import request,parse
    from http.client import HTTPResponse
    
    # ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36"
    # 请求什么返回什么
    url = "https://movie.douban.com/j/search_subjects"
    params = parse.urlencode({
        'type':'movie',
        'tag':'热门',
        'page_limit':3,
        'page_start':5,
    })
    
    url += '?' + params
    req = request.Request(url,headers={'User-agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 Safari/537.36"})
    
    with request.urlopen(req) as response:
        print(response.read())
    -----------------------------------------------
    b'{"subjects":[{"rate":"8.3","cover_x":5906,"title":"\xe5\xb0\x91\xe5\xb9\xb4\xe7\x9a\x84\xe4\xbd\xa0","url":"https:\\/\\/movie.douban.com\\/subject\\/30166972\\/","playable":true,"cover":"https://img3.doubanio.com\\/view\\/photo\\/s_ratio_poster\\/public\\/p2572166063.jpg","id":"30166972","cover_y":8268,"is_new":false},{"rate":"5.6","cover_x":1500,"title":"\xe8\xb6\x85\xe8\x83\xbd\xe8\xae\xa1\xe5\x88\x92","url":"https:\\/\\/movie.douban.com\\/subject\\/30330875\\/","playable":false,"cover":"https://img9.doubanio.com\\/view\\/photo\\/s_ratio_poster\\/public\\/p2614190404.jpg","id":"30330875","cover_y":2222,"is_new":false},{"rate":"6.2","cover_x":1080,"title":"\xe5\xa6\x99\xe5\x85\x88\xe7\x94\x9f","url":"https:\\/\\/movie.douban.com\\/subject\\/34888476\\/","playable":true,"cover":"https://img9.doubanio.com\\/view\\/photo\\/s_ratio_poster\\/public\\/p2614234255.jpg","id":"34888476","cover_y":1512,"is_new":false}]}'
    
    

    相关文章

      网友评论

          本文标题:62.1-爬虫概述、Robots协议

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