zoukankan      html  css  js  c++  java
  • 8月1日开发者日志爬虫初识

    8月1日开发者日志爬虫初识

    讲在课前

    课程1564620386955

    异步会用到协程

    大纲

    1564621793975

    Anacanda:一款集成环境,集成的都是基于数据分析和机器学习的环境(模块)

    jupyter notework : 可视化

    requests

    scrapy

    jupyter notebook 快捷键

    • cell

      添加 一个cell : a b 
      删除cell : x 
      进入编辑 : 双击
      切换cell 模式: 	
      ​	y : markdown -> code
      ​	m :  code  ->	markdown
      tab : 
      执行cell : shift + enter 
      打开帮助文档 : 
      ​	shift + tab 
      

    爬虫定义:

    就是通过编写程序模拟浏览器上网,然后让其去互联网上抓取数据的过程

    • 浏览器就是一款天然的爬虫工具

    爬虫分类

    • 通用爬虫 : 爬取一整张页面源码数据 content text read (response)

      ​ 搜索引擎用的比较多(抓取系统(爬虫))

    • 聚焦爬虫 : 爬取的是一张页面中局部的数据 (数据解析)

    • 增量式爬虫 :

      • 用于监测网站数据更新的情况,从而爬取网站中最新更新出来的数据
    • 反爬机制:(门户网站)

    • 反反爬策略:

    • 第一个反爬机制:

      • robots.txt协议: (防君子不防小人)

        1564625241699

        User-agent请求载体的身份标识 : 1.浏览器 2.爬虫工具

        allow: 可爬, disallow 不可爬

      1564625439119

      ​ 自己写的爬虫权限:根目录不可爬

    http协议和https协议

    • http 协议: 就是客户端和服务端进行数据交互的形式

    • 常用的请求头:

      • User-agent请求载体的身份标识

      • content-type:

      • Connection: keep-alive (http1.1之后都是长链接,有时间)

        ​ : close

    • https: 加密的http(http + ssl)

      相对于http更安全,但是性能较低

      • 对称密钥加密:客户端设立一种加密方式(用户名,密码)->密文+密钥发给服务端

        • 问题 : 一起发送,安全性低,被fiddler拦截了,解析
      • 非对称密钥加密:服务器给客户公钥,客户端以此加密了,传密文给服务端

        • 问题: 1,效率低,通信实现

          ​ 2,非服务器端模拟公钥发送,也造成被劫持

      • 证书密钥加密

        给服务器的公钥认证,就不是假的了,传过去客户端

        1564627209028

      证书:

      ​ 12306不是同一家的证书机构,国家颁发的,浏览器没认可

    • 案例

      网页采集

      爬取豆瓣/肯德基的相关数据

      药监总局企业信息的爬取

    爬虫模块requests

    ​ 网络请求的模块,模拟浏览器发请求的

    • urllib (老的爬取,封装没有这么高级)

      知道如何发起请求就可(老师博客)

    • 编码流程

      • 指定url
      • 发起了请求
      • 获取响应数据
      • 持久化存储
    • 爬取搜狗首页的页面源码数据

      import requests
      # 获取url
      url = 'https://www.sogou.com/'
      # 发起请求,:返回值是一个response
      response = requests.get(url=url)
      # 获取响应数据: text返回的是字符串形式的响应数据(页面源码数据)
      page_text = response.text
      # 持久化存储
      with open('sogou.html','w', encoding='utf-8') as fp:
          fp.write(page_text)
      

      1564654595206因为没有页面渲染,所以生成的html,这个模样,但是只要数据,就行了(有可能会好看排班,看爬下来的数据如何了)

      #简易的网页采集器
      url = 'https://www.sogou.com/web'
      #设定动态的请求参数
      wd = input('enter a key word:')
      params = {
          'query':wd
      }
      #参数2:params是一个字典,是用来处理动态请求参数
      response = requests.get(url=url,params=params)
      page_text = response.text
      fileName = wd+'.html'
      # with open(fileName,'w',encoding='utf-8') as fp:
      #     fp.write(page_text)
      # print(fileName,'下载成功!')
      print(page_text)
      
      #分析:爬取的数据有乱码    爬取的数据有缺失
      

      显示:1564654974222

      乱码 --> 给resoponse = encoding('utf-8') # 改了编码格式

      #修改原始的响应数据的编码
      response.encoding = 'utf-8'
      page_text = response.text
      

      拒绝访问:

      显示:1564655049718

      搜狗队请求载体身份标识做了检查

      • ua 检测:搜狗使用的反爬机制
      • ua 伪装 headers = {} #常识
      #UA伪装
      headers = {
          'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'
      }
      #参数2:params是一个字典,是用来处理动态请求参数
      response = requests.get(url=url,params=params,headers=headers) #将headers作用的get方法的第三个参数中
      #修改原始的响应数据的编码	
      

      完整的简易的网页采集器代码

      #简易的网页采集器
      url = 'https://www.sogou.com/web'
      #设定动态的请求参数
      wd = input('enter a key word:')
      params = {
          'query':wd
      }
      
      #UA伪装
      headers = {
          'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'
      }
      
      #参数2:params是一个字典,是用来处理动态请求参数
      response = requests.get(url=url,params=params,headers=headers) #将headers作用的get方法的第三个参数中
      #修改原始的响应数据的编码
      response.encoding = 'utf-8'
      
      page_text = response.text
      fileName = wd+'.html'
      with open(fileName,'w',encoding='utf-8') as fp:
          fp.write(page_text)
      print(fileName,'下载成功!')
      

    需求:爬取肯德基的餐厅位置信息

    http://www.kfc.com.cn/kfccda/storelist/index.aspx

    • 动态加载的数据:是另一个新的请求请求到的数据

    xml里的http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword

    Headers 里 from data

    cname: 
    pid: 
    keyword: 北京
    pageIndex: 1
    pageSize: 10
    

    1 2000 分析 都出来了

    爬取肯德基的地址程序

    #UA伪装
    headers = {
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'
    }
    
    url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword'
    city = input('enter a city name:')
    #该字典是用来处理封装post请求的请求参数
    data = {
        "cname": '',
        'pid': '',
        'keyword': city,
        'pageIndex': '1',
        'pageSize': '2000',
    }
    response = requests.post(url=url,data=data,headers=headers)
    #json()返回的是序列化之后的json对象.
    json_data = response.json()
    
    for dic in json_data['Table1']:
        print(dic['addressDetail'])
    

    爬取

    爬取页面之前:

    • 验证要爬取的数据,是否为当前页面动态加载的?另一个请请求到的!
      • 是-不可爬 否,可爬
    • 如何验证页面中的局部数据是否为动态加载呢?
      • 首先在页面赋值一部分的页面内容,然后在通过抓包工具定位到url指定的数据包,在数据的response中进行搜索,没有则为动态数据

    1564632750403

    http://125.35.6.84:81/xk/

    http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsList

    http://125.35.6.84:81/xk/itownet/portal/dzpz.jsp?id=3433178cbd7645909317d05199be3e20

    爬取动态网页

    网页: http://125.35.6.84:81/xk/

    搜索动态网址:'http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsList'

    import requests
    headers = {
       'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36'
    }
    url = 'http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsList'
    data = {
        'on': 'true',
        'page': '1',
        'pageSize': '15',
        'productName': '',
        'conditionType': '1',
        'applyname':'',
        'applysn':'', 
    }
    json_date= requests.post(url=url,data=data,headers=headers).json()['list']
    for data in json_date:
        print(data['ID'])
    

    数据格式:1564647724664

    获得ID,进入详细的每一个页面

    因为是根据id合成新的url ---> http://125.35.6.84:81/xk/itownet/portal/dzpz.jsp?id=f0cf7be12d804bbf9b663a5537fdd72a(不是根据动态获得的这个吗?)

    http://125.35.6.84:81/xk/itownet/portal/dzpz.jsp?id=800618396a69448ab7f5162c77f89bf2 # GET

    或者是http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsById,

    不是搜错了,搜有用的数据,不是随便的格式的值.response(返回的是html网页)

    然后会定位到返回的请求的url,response(返回的是字典的数据)

    然后再找form_data,找传的数据.就是提取的ID

    数据格式:1564647754144

        for data in json_date:
            id = data['ID']
            url = 'http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsById'
            data = {'id': id}
            b_data = requests.post(url=url,data=data , headers=headers).json()
            print(b_data['businessPerson'],b_data['epsName'])
    

    1564647926872

    1564647938906

    url = 'http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsById'
        data = {'id': idd}
        b_data = requests.post(url=url, headers=headers,data=data).json()
        print(b_data['businessPerson'],b_data['epsName'])
    

    说是not list的错误,但是打印出来就是只打印第一页的内容

    而且,当只写一页的时候没错误,而且,可以打印在没有打印post第二页的网址的时候.

    最终错误: url和上面重名了,改成urll 就好了,而且老师很细节的也设置成detail_url

    完整版代码:

    import requests
    headers = {
       'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36'
    }
    url = 'http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsList'
    for i in range(1,6):
        data = {
            'on': 'true',
            'page': str(i),
            'pageSize': '15',
            'productName': '',
            'conditionType': '1',
            'applyname':'',
            'applysn':'', 
        }
        print(f'正在爬取第{i}页数据')
        print('
    ')
        json_date= requests.post(url=url,data=data,headers=headers).json()     
        for i in json_date['list']:
            idd = i['ID']
             
            urll = 'http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsById'
            data = {'id':idd}
            b_data = requests.post(url=urll,data=data,headers=headers).json()
            print(b_data['businessPerson'], b_data['epsName'])
            
    

    错误信息:1564649130729

    错误位置:1564649149461

    url = 'http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsById'
            data = {'id':idd}
            b_data = requests.post(url=url,data=data,headers=headers).json()
            print(b_data['businessPerson'], b_data['epsName'])
            
    

    但是之前是对的,可以访问id,为什么不能访问之后的呢?(这个是对的,说明上面的代码没问题,下面的代码有问题,不应该往上面去找bug的)

    1564649348835

    哦,之前没用到url,url引起歧义了,而且id老师也给改成了_id,之前是id

        http://localhost:8888/?token=
    

    47602d77e35da9c700ebb2d712a12ed5c9bd468dcfaa2e02

    爬药监:拔网线,连wifi

    import requests
    headers = {
       'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36'
    }
    url = 'http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsList'
    for i in range(1,6):
        data = {
            'on': 'true',
            'page': str(i),
            'pageSize': '15',
            'productName': '',
            'conditionType': '1',
            'applyname':'',
            'applysn':'', 
        }
       # print(f'正在爬取第{i}页数据')
       # print('
    ')
        json_date= requests.post(url=url,data=data,headers=headers).json()     
        for i in json_date['list']:
            idd = i['ID']
            urll = 'http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsById'
            data = {'id':idd}
            b_data = requests.post(url=urll,data=data,headers=headers).json()
            # print(b_data['businessPerson'], b_data['epsName'])
            
    

    作业完成

    import requests
    url = 'https://movie.douban.com/j/chart/top_list?'    
    headers = {
       'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.108 Safari/537.36'
    }
    count = 0 
    for i in range(0,240,20):
    #     print(i)
        data = {
            'type': '5',
            'interval_id': '100:90',
            'action':'' ,
            'start': str(i),
            'limit': '20',
        }
        json_date= requests.post(url=url,data=data,headers=headers).json()    
        
        for i in json_date:
            count += 1
            print(count,i['title'],i['score'])
    

    https://m701.music.126.net/20190801200826/896ad0df53f36335ffdc331bd1b0464a/jdyyaac/545a/065b/545c/c0b7d8ee4a11b9797762c6a5aa1733a0.m4a

    https://m10.music.126.net/20190801201722/373b61bde2267c0966d30f64b9f6dfbe/yyaac/025f/015f/515b/550e88daed6530687dabf1565f8ebbd2.m4a

  • 相关阅读:
    react-redux
    Vue中常用的UI框架
    vue中router与route的区别
    H5新增input属性
    H5新增的input类型
    菜鸡对作用域链的理解
    自己对路由的一些理解
    浏览器缓存
    黄瓜的不定期更新面试题
    ajax封装
  • 原文地址:https://www.cnblogs.com/Doner/p/11281051.html
Copyright © 2011-2022 走看看