爬虫之基本操作篇

2.爬虫基本流程

img

1、发起请求
    使用http库向目标站点发起请求,即发送一个Request
    Request包含:请求头、请求体等

2、获取响应内容
    如果服务器能正常响应,则会得到一个Response
    Response包含:html,json,图片,视频等

3、解析内容
    解析html数据:正则表达式,第三方解析库如Beautifulsoup,pyquery等
    解析json数据:json模块
    解析二进制数据:以b的方式写入文件

4、保存数据
    数据库
    文件

2.1请求与响应

img

#http协议:        
    http://www.cnblogs.com/linhaifeng/articles/8243379.html

#Request:
    用户将自己的信息通过浏览器(socket client)发送给服务器(socket server)

#Response:
    服务器接收请求,分析用户发来的请求信息,然后返回数据(返回的数据中可能包含其他链接,如:图片,js,css等)

#ps:
    浏览器在接收Response后,会解析其内容来显示给用户,而爬虫程序在模拟浏览器发送请求然后接收Response后,是要提取其中的有用数据

3.jupyter的基本使用

  • 什么是anaconda
    • 是一个基于数据分析+机器学习的集成环境。
  • 什么是jupyter(超级终端)
    • 是anaconda中的一个基于浏览器可视化的编码工具
  • 在指定目录下启动终端:录入jupyter notebook指令开辟指定的服务。

cell的两种模式

image-20191202100919070

makedown 兼容笔记 笔记的编写

code编写代码

运行会开辟一块内存空间
然后就可以执行寻找变量对应的内存空间的数值 

快捷键

插入cell:a,b
删除cell:x
执行cell:shift+enter
tab:自动补全
切换cell的模式:y,m
打开帮助文档:shift+tab

补充 http和https

是遵循的一种通讯协议 进行字节 字符串的传输
https 内布绒使用ssl加密 使用ca证书 防止黑客劫持

数据解析 爬去的数据进行筛选

达到对应ajax的url请求 xhr标签

image-20191202120200195

4.requests模块

需要环境的安装:pip install requests

#1、请求方式:
    常用的请求方式:GET,POST
    get进行页面的获取 post用于搜索框查询和提交数据 然后post返回的响应数据需要使用json序列化
    其他请求方式:HEAD,PUT,DELETE,OPTHONS

ps:用浏览器演示get与post的区别,(用登录演示post)    
    post与get请求最终都会拼接成这种形式:k1=xxx&k2=yyy&k3=zzz
    post请求的参数放在请求体内:
        可用浏览器查看,存放于form data内
    get请求的参数直接放在url后


#2、请求url
    url全称统一资源定位符,如一个网页文档,一张图片
    一个视频等都可以用url唯一来确定

    url编码
    https://www.baidu.com/s?wd=图片
    图片会被编码(看示例代码)

    网页的加载过程是:
    加载一个网页,通常都是先加载document文档,
    在解析document文档的时候,遇到链接,则针对超链接发起下载图片的请求

#3、请求头
    User-agent:请求头中如果没有user-agent客户端配置,
    服务端可能将你当做一个非法用户
    host
    cookies:cookie用来保存登录信息
    一般做爬虫都会加上请求头 来进行UA检测的反反爬策略


#4、请求体
    如果是get方式,请求体没有内容
    如果是post方式,请求体是format data
    ps:
    1、登录窗口,文件上传等,信息都会被附加到请求体内
    2、登录,输入错误的用户名密码,然后提交,就可以看到post,正确登录后页面通常会跳转,无法捕捉到post 
  • 是一个基于网络请求的模块。

  • 作用:模拟浏览器发起请求

  • 分析requests的编码流程:

  • 指定url
    发起了请求
    获取响应数据
    持久化存储
    

import requests 引用模块

2.1参数

import requests
#1.指定url
url = 'https://www.sogou.com/'

#2.发起请求,get的返回值是一个响应对象
response = requests.get(url)

#3.获取响应数据,text属性返回的是字符串形式的响应数据
page_text = response.text
host_list = response.json()#转换json类型
page_data = response.content #获取二进制响应数据

response.text #获取响应字节
#4,持久化存储
with open('./sogou.html','w',encoding='utf-8') as fp:
    fp.write(page_text)
 

2.2简易的网页采集器

url = 'https://www.sogou.com/web?query=人民币'
response = requests.get(url)
page_text = response.text
with open('./人民币.html','w',encoding='utf-8') as fp:
    fp.write(page_text)

2.2.1上述代码出现的问题:

  • 出现了乱码
  • 数据的量级不够
2.2.2处理乱码
import requests
url = 'https://www.sogou.com/web?query=人民币'
response = requests.get(url)
#修改响应数据的编码格式
response.encoding = 'utf-8'#进行编码转义
page_text = response.text
with open('./人民币.html','w',encoding='utf-8') as fp:
    fp.write(page_text)
2.2.3处理数据量级问题
- 遇到了对应的反爬机制
    - 反爬机制:UA检测
    - 反反爬策略:UA伪装
    - UA伪装的实现:
        - 1.定义一个字典
        - 2.在字典中进行相关请求头信息的伪装
        - 3.将该字典作用到get方法的headers参数中即可
    - UA检测被作用到了大量的网站中,因此日后,爬虫程序编写中一定要直接加上UA的操作
	#伪装请求头
    headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}
response = requests.get(url,headers=headers)#UA伪装
import requests
url = 'https://www.sogou.com/web?query=人民币'

headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}
response = requests.get(url,headers=headers)#UA伪装

#修改响应数据的编码格式
response.encoding = 'utf-8'

page_text = response.text#获取响应数据
with open('./人民币.html','w',encoding='utf-8') as fp:
    fp.write(page_text)
2.2.4最终实现

使用请求参数的动态化

#参数动态化
wd = input('enter a key word:')
#query是接受输入信息变量通过https://www.sogou.com/web?query="人民币"  传递
param = {  
    'query':wd#
}
response = requests.get(url,headers=headers,params=param)#UA伪装

实现原理:

- 1.定义一个字典
- 2.字典中的键值就是url携带的参数
- 3.将字典作用到get方法的params参数中
  • 代码实现
import requests
url = 'https://www.sogou.com/web'

headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}

#参数动态化
wd = input('enter a key word:')
#query是接受输入信息变量通过https://www.sogou.com/web?query="人民币"  传递
param = {  
    'query':wd
}
response = requests.get(url,headers=headers,params=param)#UA伪装

#修改响应数据的编码格式
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,'爬取成功!!!')

5.动态加载的数据

image-20191202144836586

如何判定是否是动态加载

#产生动态加载的情况
ajax,#能获取到原生的数据
js只能拦截到函数 需要手动获取返回值
  • 概念:通过其他/另一个请求请求到的数据
  • 特性:可见非可得
  • 判定相关的页面数据是否为动态加载的数据?
    • 基于抓包工具定位到浏览器地址栏url对应的请求数据包,进行局部搜索:
      • 搜索到:这组被搜索的数据不是动态加载的,可以直接爬取
      • 没有搜到:这组数据是动态加载的,不可以直接爬取。
  • 如何捕获动态加载的数据?
    • 基于抓包工具进行全局搜索,最终可以定位到动态加载数据对应的数据包。
    • 从数据包可以提取出url和数据

通过使用特定的套路 也就是捕获数据 进行请求的返回加载

xhr查看ajax对应的数据包

局部搜索

image-20191206205247647

全局搜索 点击随便一个包全局搜索 ctrl+f 全局搜索
局部搜索 点击response页面数据进行查询

2.3案例动态数据简单练习

需求:爬取豆瓣电影的详情数据
  • 分析:https://movie.douban.com/j/chart/top_list
    • 更多的电影数据是通过将滚轮滑动到底部后发起了ajax请求请求到的电影数据
    • 对ajax请求的url进行捕获
    • 对ajax请求的url进行请求发送
import requests
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}
url = 'https://movie.douban.com/j/chart/top_list'
fp = open('./movieData.txt','a+',encoding='utf-8')

数据的获取xhr浏览器的开发者工具
for i in range(0,10):
    param = {
        'type': '13',
        'interval_id': '100:90',
        'action': '',
        'start': str(i*20),  #指定开始序号
        'limit': '20', #  限制每次获取条数
    }
    response = requests.get(url=url,params=param,headers=headers)
    #json()将json串进行序列化
    movie_list = response.json()
    for dic in movie_list:
        name = dic['title']
        score = dic['score']
        fp.write(name+':'+score+'\n')
    print('第{}页数据爬取成功!'.format(i))
fp.close()
        
肯德基餐厅查询
  • 分析:

    • 动态加载数据
  • 动态加载数据

    • 概念:通过其他/另一个请求请求到的数据(ajax)
    • 特性:可以在网页上看见名但是获取不到数据
    • 判定相关的页面数据是否为动态加载的数据?
      • 基于抓包工具定位到浏览器地址栏url对应的请求数据包,进行局部搜索:
        • 搜索到:这组被搜索的数据不是动态加载的,可以直接爬取
        • 没有搜到:这组数据是动态加载的,不可以直接爬取。
    • 如何捕获动态加载的数据?
      • 基于抓包工具进行全局搜索,最终可以定位到动态加载数据对应的数据包。
import requests
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}
data = {
    'cname': '',
    'pid': '',
    'keyword': '广州',
    'pageIndex': '1',
    'pageSize': '10',
}
url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword'
response = requests.post(url=url,headers=headers,data=data)
pos_data = response.json()
pos_data

药监总局数据爬取,爬取的是每一家企业的详情数据

import requests
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}
#获取企业id
ids = [] #存储所有企业的id
url = 'http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsList'
for page in range(1,6):
    data = {
        'on': 'true',
        'page': str(page),
        'pageSize': '15',
        'productName': '',
        'conditionType': '1',
        'applyname': '',
        'applysn': '',
    }
    company_datas_json = requests.post(url=url,headers=headers,data=data).json()
    for dic in company_datas_json['list']:
        _id = dic['ID']
        ids.append(_id)
        
detail_url = 'http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsById'       
for _id in ids:
    data = {
    'id':_id
    }
    company_json = requests.post(url=detail_url,headers=headers,data=data).json()
    print(company_json['epsName'],company_json['epsProductAddress'])

2.4get请求和post请求的区别

get是param ?参数 get(param=param)
post是data 请求体里面的参数 post(data=data)
url = 'https://www.sogou.com/web'

headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}

#参数动态化
wd = input('enter a key word:')
param = {
    'query':wd#查询寻找指定页面
}
response = requests.get(url,headers=headers,params=param)#UA伪装

#修改响应数据的编码格式
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,'爬取成功!!!')

cmd命令

shift+右键点击 进入cmd

urllib 低版本的requests

1.不能进行ua伪装

#ua伪装
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
} 

2.请求头不一样

3.可以直接进行爬去数据的存储

使用方法

import urllib
url = 'http://duanziwang.com/usr/uploads/2019/02/3334500855.jpg'
urllib.request.urlretrieve(url=url,filename='./2.jpg')
#url 指定图片路径地址 filename 图片路径地址

6.浏览器开发者工具

抓包工具中response中显示的页面源码和开发者工具的Element选项卡显示的页面源码的区别是什么?

Elements

等待数据全部加载完毕之后显示的所有数据 (包含动态加载数据)

Response

显示的内容仅仅是当前一个请求请求到的数据(不包含动态加载的数据)
posted @ 2019-12-06 23:08  strawberry*  阅读(494)  评论(0)    收藏  举报