初识爬虫
什么是爬虫
- 通过编写程序模拟浏览器上网,然后去互联网上爬取数据的过程
爬虫的分类
- 通用爬虫
- 爬取互联网中的一整张页面数据
- 聚焦爬虫
- 抓取页面中的局部数据
- 增量式爬虫
- 用来检测网站数据的更新情况,以便爬取到网站最新更新出来的数据
反爬机制
UA检测:门户网站通过检测请求载体的身份标识判定改请求是否为爬虫发起的请求
反反爬策略
UA伪装:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36
爬虫违法吗?
爬取数据的行为风险的提现
- 爬虫干扰了被访问网站的正常运营
- 爬虫抓取了受法律保护的特定类型的数据或信息
规避风险
- 严格最受网站设置的robots协议
- 在规避反爬措施的同事,要优化自己的代码,避免干扰网站的正常运行
- 在使用,传播抓取的的信息时,应审查所抓取的内容,如果发现属于用户的个人信息,隐私或者他人商业秘密时,应及时停止并删除
robots协议:文本协议
- 没有什么硬性限制,只是大家默认遵守的一个协议(防君子不防小人协议)
- 例:https://www.bilibili.com/robots.txt
requests模块的基本使用
python中封装好的基于网络请求的模块,用来模拟浏览器发请求
requests模块的环境安装
pip install requests
requests模块的编码流程
- 指定URL
- 发起请求
- 获取响应数据
- 持久化存储
import requests # 指定url url = 'https://www.bilibili.com' # 请求发送get:get返回值是一个响应对象 response = requests.get(url=url) # 获取响应数据 page_txt = response.text # 返回的是字符串形式的响应数据 # 持久化存储 with open('批站.html','w',encoding='utf-8') as p: p.write(page_txt)
实现一个可以指定数据请求的功能
import requests keyword = input('你要搜索的内容') # url请求参数动态化 # url = 'https://search.bilibili.com/all?keyword=' url = 'https://search.bilibili.com/all' params = { 'keyword':keyword } # 在请求中需要将请求参数对应的字典作用到params这个get方法的参数中 URL拼接 response = requests.get(url=url, params=params) # 获取响应数据 page_txt = response.text FileName = keyword + '.html' with open(FileName,'w',encoding='utf-8') as p: p.write(page_txt)
上面功能可能出现 编码问题,ua防爬机制
import requests keyword = input('你要搜索的内容') # url请求参数动态化 # url = 'https://search.bilibili.com/all?keyword=' url = 'https://search.bilibili.com/all' params = { 'keyword':keyword } headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36' } # 请求发送get:get返回值是一个响应对象 response = requests.get(url=url, params=params, headers=headers) # 修改响应数据的编码格式 response.encoding = 'utf-8' # 获取响应数据 page_txt = response.text FileName = keyword + '.html' with open(FileName,'w',encoding='utf-8') as p: p.write(page_txt)
爬取基于ajax动态加载的数据
基于抓包工具实现动态加载数据的检测
- 先捕获网站请求后所有的数据包
- 在数据包中定位到地址栏所对应的请求数据包,在response选项卡对应的数据中进行局部搜索(页面中的某一组内容)
- 可以搜到:爬取的数据不是动态加载的
- 没有搜索到:爬取的数据不是动态加载的
- 如何定位动态加载的数据在哪个数据包
- 进行全局搜索
例: 爬取豆瓣电影详情数据
import requests # 爬取豆瓣影评中的详情数据:https://movie.douban.com/typerank?type_name=%E7%88%B1%E6%83%85&type=13&interval_id=100:90&action= # 分析:当滚动条滑动到页面底部的时候,页面发生了刷新(ajax请求) # 真实的地址 基于ajax请求的真实网址 url = 'https://movie.douban.com/j/chart/top_list' start = input("开始>>> ") limit = input("结尾>>> ") # ajex 请求参数 dic = { 'type': '13', 'interval_id': '100:90', 'action': '', 'start': start, 'limit': limit, } headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36' } response = requests.get(url=url, params=dic, headers=headers) # 只有确认获取到的数据时json字符串,才能使用json方法 page_text = response.json() # 返回的是序列化好的实例对象 for i,dic in enumerate(page_text,1): moves = f"{i} 电影: {dic['title']} >>>> 评分: {dic['score']} " print(moves)
# http://www.kfc.com.cn/kfccda/storelist/index.aspx # 需求分析 ajax请求 POST请求 import requests # 获取ajax请求url url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword' address = input('请输入城市: ') data = { 'cname': '', 'pid': '', 'keyword': address, 'pageIndex': '1', 'pageSize': '10', } headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36' } # post 使用data response = requests.post(url=url, headers=headers, data=data) page_text = response.json() for dic in page_text['Table1']: print(f"{dic['storeName']} {dic['addressDetail']}") # 只获取了第一页
进阶
import requests url = 'http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsList' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36' } for page in range(1,6): data = { 'on': 'true', 'page': str(page), 'pageSize': '15', 'productName': '', 'conditionType': '1', 'applyname': '', } response = requests.post(url=url, headers=headers, data=data) page_text = response.json() for dic in page_text['list']: # 嵌套获取内层数据 url2 = 'http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsById' data2 = { 'id': dic['ID'], } response2 = requests.post(url=url2, headers=headers, data=data2) page2_text = response2.json() txt_name = f"法定代表人:{page2_text['businessPerson']} 社会信用代码:{page2_text['businessLicenseNumber']} 许可项目: {page2_text['certStr']}\n" with open('名单.txt','a',encoding='utf-8') as f: f.write(txt_name)

浙公网安备 33010602011771号