Python爬虫-稳健上手

Pytthon爬虫-基础

Intro

  • 网络爬虫是什么:
    • 网络爬虫是一个模仿人类请求网站行为的程序。可以自动请求网页、以及抓取相关数据
  • 为何用Python写爬虫程序
    • python语法优美,代码简洁,开发效率高,相关的HTTP请求模块和HTML解析模块非常丰富。还有scrapy和scrapy-redis框架让我们开发爬虫变得异常容易
  • 爬虫的实际例子
      1. 搜索引擎
    • 2.伯乐在线
      1. 惠惠购物助手
      1. 数据分析与研究(数据冰山知乎专栏)
    • 5.抢票软件等
  • 通用爬虫和聚焦爬虫
    • 通用爬虫是搜索引擎抓取系统的重要组成部分,主要是将互联网上的网页下载到本地,形成一个互联网内容的镜像备份
    • 聚焦爬虫是面向特定需求的一种网络爬虫程序,在实施网页抓取的时候会对内容进行筛选和处理,尽量保证只抓取与需求相关的网页信息

http协议和chrome抓包工具

  • http/https协议

    • HTTP协议:超文本传输协议,一种传输.html文件的规范。服务器端口默认为80
    • HTTPS协议:是HTTP协议的加密版本,在HTTP下加入了SSL层,服务器端口默认是443
  • 在浏览器发送一个http请求的过程

      1. 在浏览器地址栏输入一个URL并按下回车,浏览器会向对应URL所在的HTTP服务器发送HTTP请求(主要分为GET和POST两种请求方式)
      1. 比如输入的URL是https://baidu.com,浏览器会发送一个Request请求试图获取百度首页的html文件,百度的服务器接收到这个请求后使用Request所在的Socket向本地的浏览器发送回Response文件对象
      1. 浏览器分析Response中的HTML,发现其中引用的很多其他文件,比如image.CSS.JS文件,浏览器会自动再次发送Request取获取相应的图片,样式等
      1. 当所有的文件都下载成功后,网页会根据HTML语法结构完整地在浏览器界面显示出来
  • url详解

    • Uniform Resource Locator 统一资源定位符。一个URL有以下几部分组成:
      scheme://host:port/path/?query-string=xxx#anchor
    • scheme:代表访问协议,一般为http/https以及ftp等
      • host:主机名,域名,比如localhost,www.baidu.com
      • port:端口号:当你访问一个网站时,浏览器默认使用80端口
      • path:查找路径。比如:www.tencent.com/game/LOL,后面的game/LOL就是path
      • query-string:查询字符串,比如www.baidu.com/s?wd=python问号,后面的wd=python就是查询字符串
      • anchor:锚点,前端用来做页面定位的标识符,类似于markdown语法中的标题
    • 在浏览器中请求一个url,浏览器会对这个url进行一个编码。除英文字母,数字和部分符号外,其他的都用
      百分号+十六进制码值进行编码
  • 常用请求方法

    • 在http协议中,定义了八种请求方法,其中最常用的两种分别是GETPOST请求
      • get请求:一般情况下,只从服务器获取数据下来,并不会对服务器资源产生任何影响的时候会使用get请求
      • post请求:向服务器发送数据(登陆)、上传文件等,会对服务器资源产生影响的时候会使用post请求。
      • 最直观的区别:
        • get请求的请求参数是作为一个key/value对的序列(查询字符串)附加到URL上的。
        • post的请求参数是在http标题的一个不同部分(名为entity body)传输的,这一部分用来传输表单信息,因此必须将Content-type设置为:application/x-www-form-urlencoded。
      • 行为上的区别
        • GET请求会被浏览器主动cache,而POST不会,除非手动设置。
        • GET产生一个TCP数据包;POST产生两个TCP数据包,GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
  • 请求头常见参数

    • 在http协议中,向服务器发送一个请求,数据分为三部分。

      • 第一个是把数据放在url中
      • 第二个是把数据放在body中(post请求)
      • 第三个是把数据放在head
    • 在网络爬虫中经常会用到的一些请求头参数

      • User-Agent:浏览器名称。这个在网络爬虫中经常会被使用到。请求一个网页的时候,服务器通过这个参数就可以知道这个请求是由哪种浏览器发送的。如果我们是通过爬虫发送请求,那么我们的User-Agent就是Python,这对于那些有反爬虫机制的网站来说,可以轻易的判断你这个请求是爬虫。因此我们要经常设置这个值为一些浏览器的值,来伪装我们的爬虫。
      • Referer:表明当前这个请求是从哪个url过来的。这个一般也可以用来做反爬虫技术。如果不是从指定页面过来的,那么就不做相关的响应。
      • Cookie:http请求是无状态的。也就是说即使第一次和服务器连接后并且登录成功后,第二次请求服务器依然不能知道当前请求是哪个用户。
        • cookie的出现就是为了解决这个问题,第一次登录后服务器返回一些数据(cookie)给浏览器,然后浏览器保存在本地,当该用户发送第二次请求的时候,就会自动的把上次请求存储的cookie数据自动的携带给服务器,服务器通过浏览器携带的数据就能判断当前用户是哪个了。cookie存储的数据量有限,不同的浏览器有不同的存储大小,但一般不超过4KB。因此使用cookie只能存储一些小量的数据。
        • cookie的格式:
          • Set-Cookie: NAME=VALUE;Expires/Max-age=DATE;Path=PATH;Domain=DOMAIN_NAME;SECURE
            • 参数意义:
              • NAME:cookie的名字
              • VALUE:cookie的值。
              • Expires:cookie的过期时间。
              • Path:cookie作用的路径。
              • Domain:cookie作用的域名。
              • SECURE:是否只在https协议下起作用。
  • 常见响应状态码:

    • 200:请求正常,服务器正常的返回数据。
    • 301:永久重定向。比如在访问www.jingdong.com的时候会重定向到www.jd.com。
    • 302:临时重定向。比如在访问一个需要登录的页面的时候,而此时没有登录,那么就会重定向到登录页面。
    • 400:请求的url在服务器上找不到。换句话说就是请求url错误。
    • 403:服务器拒绝访问,权限不够。
    • 500:服务器内部错误。可能是服务器出现bug了。
  • Chrome抓包工具:

    • Chrome浏览器是一个非常亲近开发者的浏览器。可以方便的查看网络请求以及发送的参数。对着网页右键->检查。然后就可以打开开发者选项。
      • 快捷键F12
    • 开发者选项中导航栏
      • Elements
        • 构成这个网页的源代码
      • console
        • 这个网页的控制台
      • Sources
        • 组成这个网页的所有源文件
      • Network
        • 加载这个页面的时候,浏览器发送的所有请求

urlib库

  • urllib.request模块:在Python3的urllib库中,所有和网络请求相关的方法,都被集到下面了

    • urlopen函数
      • es:访问百度获取相关资源

        from urllib import request   
        resp = request.urlopen('http://www.baidu.com')   
        print(resp.read())  
        
        • 参数
          • url:请求的url。
          • data:请求的data,如果设置了这个值,那么将变成post请求。
        • 返回值:返回值是一个http.client.HTTPResponse对象,这个对象是一个类文件句柄对象。有read(size)、readline、readlines以及getcode等方法。
    • urlretrieve函数
      • 这个函数可以方便的将网页上的一个文件保存到本地。
        es:将百度的首页下载到本地:

        from urllib import request  
        request.urlretrieve('http://www.baidu.com/','baidu.html')  
        
        • 参数
          • url:请求路径
          • filepath:保存的文件路径
    • ProxyHandler处理器(代理设置)
      • 很多网站会检测某一段时间某个IP的访问次数(通过流量统计,系统日志等),如果访问次数多的不像正常人,它会禁止这个IP的访问。
        所以我们可以设置一些代理服务器,每隔一段时间换一个代理,就算IP被禁止,依然可以换个IP继续爬取。

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

          from urllib import request  
          #  这个是没有使用代理的   
          resp = request.urlopen('http://httpbin.org/get')   
          print(resp.read().decode("utf-8"))  
            
          # 这个是使用了代理的   
          handler = request.ProxyHandler({"http":"218.66.161.88:31769"})  
          opener = request.build_opener(handler)  
          req = request.Request("http://httpbin.org/ip")   
          resp = opener.open(req) print(resp.read())  
          
        • 常用的代理

  • urllib.parse模块:所有涉及编码译码的方法,以及各种解析操作

    • urlencode函数

      • 如果使用代码发送请求,对于url中包含了中文或者其他特殊字符的情况,必须手动的进行编码,这时候就应该使用urlencode函数来实现。urlencode可以把字典数据转换为URL编码的数据。
        • es:
          from urllib import parse  
          data = {'name':'爬虫基础','greet':'hello world','age':100}   
          qs = parse.urlencode(data) print(qs)  
          
    • parse_qs函数

      • 可以将经过编码后的url参数进行解码。
        • es:
          from urllib import parse qs = "name=%E7%88%AC%E8%99%AB%E5%9F%BA%E7%A1%80&greet=hello+world&age=100"   
          print(parse.parse_qs(qs))  
          
    • urlparse和urlsplit

      • 有时候拿到一个url,想要对这个url中的各个组成部分进行分割,那么这时候就可以使用urlparse或者是urlsplit来进行分割。
        • es:

          from urllib import request,parse url = 'http://www.baidu.com/s?username=zhiliao'   
          result = parse.urlsplit(url)  
          result = parse.urlparse(url)  
          print('scheme:',result.scheme)   
          print('netloc:',result.netloc)   
          print('path:',result.path)   
          print('query:',result.query)  
          
        • 注意:urlparse和urlsplit基本上是一模一样的。唯一不一样的地方是,urlparse里面多了一个params属性,而urlsplit没有这个params属性。

          • 比如有一个url为:url = 'http://www.baidu.com/s;hello?wd=python&username=abc#1'
            那么urlparse可以获取到hello,而urlsplit不可以获取到。url中的params也用得比较少
  • request.Request类:自定义请求头

    • 如果想要在请求的时候增加一些请求头,那么就必须使用request.Request类来实现。
      • 比如要增加一个User-Agent,示例代码如下:
        from urllib import request   
        headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36' }   
        req = request.Request("http://www.baidu.com/",headers=headers)   
        resp = request.urlopen(req)   
        print(resp.read())  
        

requests库

  • 虽然Python的标准库中 urllib模块已经包含了平常我们使用的大多数功能,但是它的 API 使用起来让人感觉不太好,而 Requests宣传是 “HTTP for Humans”,说明使用更简洁方便。

  • 发送GET请求:

    • 最简单的发送get请求就是通过requests.get来调用:

      •   response = requests.get("http://www.baidu.com/")  
        
    • 添加headers和查询参数:

      • 如果想添加 headers,可以传入headers参数来增加请求头中的headers信息。
      • 如果要将参数放在url中传递,可以利用 params 参数。
      •   import requests  
            
           kw = {'wd':'中国'}  
            
           headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}  
            
         # params 接收一个字典或者字符串的查询参数,字典类型自动转换为url编码,不需要urlencode()  
           response = requests.get("http://www.baidu.com/s", params = kw, headers = headers)  
            
         # 查看响应内容,response.text 返回的是Unicode格式的数据  
           print(response.text)  
            
         # 查看响应内容,response.content返回的字节流数据  
           print(response.content)  
            
         # 查看完整url地址  
           print(response.url)  
            
         # 查看响应头部字符编码  
           print(response.encoding)  
            
         # 查看响应码  
           print(response.status_code)  
        
  • 发送POST请求:

    • 最基本的POST请求可以使用post方法:

      •   response = requests.post("http://www.baidu.com/",data=data)  
        
    • 传入data数据:
      这时候就不要再使用urlencode进行编码了,直接传入一个字典进去就可以了。

      •   import requests  
            
           url = "https://www.lagou.com/jobs/positionAjax.json?city=%E6%B7%B1%E5%9C%B3&needAddtionalResult=false&isSchoolJob=0"  
            
           headers = {  
               'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36',  
               'Referer': 'https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput='  
           }  
            
           data = {  
               'first': 'true',  
               'pn': 1,  
               'kd': 'python'  
           }  
            
           resp = requests.post(url,headers=headers,data=data)  
          # 如果是json数据,直接可以调用json方法  
           print(resp.json())  
        
  • 使用代理:

    • 使用requests添加代理也非常简单,只要在请求的方法中(比如get或者post)传递proxies参数就可以了。
      •   import requests  
            
          url = "http://httpbin.org/get"  
            
          headers = {  
              'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36',  
          }  
            
          proxy = {  
              'http': '171.14.209.180:27829'  
          }  
            
          resp = requests.get(url,headers=headers,proxies=proxy)  
          with open('xx.html','w',encoding='utf-8') as fp:  
              fp.write(resp.text)  
        
  • cookie:

    • 如果在一个响应中包含了cookie,那么可以利用cookies属性拿到这个返回的cookie值
      •   import requests  
            
          url = "http://www.renren.com/PLogin.do"  
          data = {"email":"970138074@qq.com",'password':"pythonspider"}  
          resp = requests.get('http://www.baidu.com/')  
          print(resp.cookies)  
          print(resp.cookies.get_dict())  
        
  • session:

    • 在使用urllib库时,是可以使用opener发送多个请求,多个请求之间是可以共享cookie的。如果使用requests,也要达到共享cookie的目的,那么可以使用requests库给我们提供的session对象。注意,这里的session不是web开发中的那个session,这个地方只是一个会话的对象而已。还是以登录人人网为例,使用requests来实现。
      •   import requests  
            
          url = "http://www.renren.com/PLogin.do"  
          data = {"email":"970138074@qq.com",'password':"pythonspider"}  
          headers = {  
              'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36"  
          }  
            
          #登录  
          session = requests.session()  
          session.post(url,data=data,headers=headers)  
            
          #访问大鹏个人中心  
          resp = session.get('http://www.renren.com/880151247/profile')  
            
          print(resp.text)  
        
  • 处理不信任的SSL证书:

    • 对于那些已经被信任的SSL证书的网站,比如https://www.baidu.com/,那么使用requests直接就可以正常的返回响应。

    • 而对于没被信任的SSL证书的网站,可以在request.get中传递参数verify=False,手动设置不再验证该网站的SSL证书

      resp = requests.get('http://www.12306.cn/mormhweb/',verify=False) # 跳过验证SSL证书即可访问不被信任的网站
      print(resp.content.decode('utf-8'))
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值