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('\n')
    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('\n')
    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

posted @ 2019-08-01 10:41  learnacode  阅读(202)  评论(0编辑  收藏  举报