1. 爬虫基础
目录
爬虫基础
1.简介
爬虫:通过编写程序模拟浏览器上网,然后让其去互联网上抓取数据的过程
应用分类:
1.通用爬虫:抓取一整页面源码内容
2.聚焦爬虫:抓取页面中局部的指定数据
3.增量式:监测网站数据更新的情况。
4.分布式
2.requests:模拟浏览器上网
编码流程:
1.指定url
2.发起请求
3.获取响应数据
4.持久化存储
requests 基本使用
import requests
# 请求路径
url = 'https://www.sogou.com/'
# get请求返回响应对象
response = requests.get(url=url)
# 获取相应数据
page_text = response.text #text返回的是字符串形式的相应数据
print(page_text)
# 储存数据
with open('./sogou.html','w',encoding='utf-8') as fp:
fp.write(page_text)
异常访问请求
- 异常的访问请求:
- 非浏览器发起的请求。
- 网站的后台是如何监测请求是否为异常请求?
- 请求头信息:User-Agent
- UA:请求载体的身份标识
- 反爬机制:UA监测
- 反反爬策略:UA伪装
抓包工具(浏览器检查) -- Network中 -- 请求头有本机的User-Agent
# 制作一个简易的网页采集器 -- 搜狗搜索
import requests
url = 'https://www.sogou.com/web'
word = input('输入搜索关键字:')
# 请求参数
params = {
'query':word
}
# User-Agent伪装
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36'
}
response = requests.get(url=url,params=params,headers=headers)
filename = word+'.html'
with open(filename,'w',encoding='utf-8') as fp:
fp.write(response.text)
获取图片数据
import requests
# 网址
url = 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fuserimage5.360doc.com%2F14%2F0601%2F02%2F14256129_201406010211550401.jpg&refer=http%3A%2F%2Fuserimage5.360doc.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1621499086&t=21d6a3fded64dd6af2dba9b6507e5d45'
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36'
}
response = requests.get(url=url,headers=headers)
# 获取图片的batys数据:content
json_data = response.content
# 保存
with open('舒畅.jpg','wb') as fp:
fp.write(json_data)
3.动态加载数据
流程:
- 动态加载数据
- 概念:通过对浏览器地址栏的url发起请求获取不到的数据
- 动态加载数据的监测
- 基于抓包工具进行局部搜索
- 如何捕获动态加载数据?
- 基于抓包工具进行全局搜索,定位动态加载数据对应的数据包,从数据包中可以提取
- url
- 请求方式
- 请求参数
- 请求头信息
示例1:get请求
# 豆瓣电影数据
import requests
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36',
}
url = 'https://movie.douban.com/j/chart/top_list'
# get请求携带的参数
params = {
'type': '25',
'interval_id': '100:90',
'action':'' ,
'start': '0',
'limit': '20',
}
# 获取响应的数据
json_data = requests.get(url=url,headers=headers,params=params).json()
print(json_data)
示例2:post请求
# 肯德基线下门店查询
# http://www.kfc.com.cn/kfccda/storelist/index.aspx
import requests
url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword'
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36'
}
# 获取前5页的数据
for index in range(1,6):
# post请求携带的参数:
data = {
'cname': '',
'pid': '',
'keyword': '北京',
'pageIndex': index,
'pageSize': 10,
}
# 获取请求数据
response = requests.post(url=url,data=data,headers=headers)
json_data = response.json()['Table1']
for i in json_data:
# 打印点名 -- 地址
print(i['storeName'],i['addressDetail'])
示例3:多次请求联合获取数据
# 药监总局网站 http://scxk.nmpa.gov.cn:81/xk/
# 查询公司详细信息:
import requests
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36'
}
list_id = []
# 1.获取公司的id地址
url = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsList'
# post请求携带数据
data = {
'on': 'true',
'page': 1,
'pageSize': 15,
'productName': '',
'conditionType': 1,
'applyname': '',
}
# 发送post请求获取响应数据
json_data = requests.post(url,data=data,headers=headers).json()['list']
for i in json_data:
list_id.append(i['ID'])
# 2.基于公司id获取获取公司的详细信息
# 公司的详细信息地址
url = 'http://scxk.nmpa.gov.cn:81/xk/itownet/portalAction.do?method=getXkzsById'
for id in list_id:
# post请求携带参数
data = {
'id':id
}
# 发送post请求获取响应数据
json_data = requests.post(url,data,headers).json()
print('>>>',json_data['epsName'])
4.数据解析
1.数据解析作用: 实现聚焦爬虫
2.数据解析方式:
1.正则
2.bs4
3.xpath
4.pyquery
3.原理:
- 数据解析的通用原理
- html是用作与数据展示。
- 展示的数据在哪?
- 标签的属性中
- 标签中间
- 原理:
- 1.标签定位
- 2.内容提取
4.测试页面数据:
text.html
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>测试bs4</title>
</head>
<body>
<div>
<p>百里守约</p>
</div>
<div class="song">
<p>李清照</p>
<p>王安石</p>
<p>苏轼</p>
<p>柳宗元</p>
<a href="http://www.song.com/" title="赵匡胤" target="_self">
<span>this is span</span>
宋朝是最强大的王朝,不是军队的强大,而是经济很强大,国民都很有钱</a>
<a href="" class="du">总为浮云能蔽日,长安不见使人愁</a>
<img src="http://www.baidu.com/meinv.jpg" alt="" />
</div>
<div class="tang">
<ul>
<li><a href="http://www.baidu.com" title="qing">清明时节雨纷纷,路上行人欲断魂,借问酒家何处有,牧童遥指杏花村</a></li>
<li><a href="http://www.163.com" title="qin">秦时明月汉时关,万里长征人未还,但使龙城飞将在,不教胡马度阴山</a></li>
<li><a href="http://www.126.com" alt="qi">岐王宅里寻常见,崔九堂前几度闻,正是江南好风景,落花时节又逢君</a></li>
<li><a href="http://www.sina.com" class="du">杜甫</a></li>
<li><a href="http://www.dudu.com" class="du">杜牧</a></li>
<li><b>杜小月</b></li>
<li><i>度蜜月</i></li>
<li><a href="http://www.haha.com" id="feng">凤凰台上凤凰游,凤去台空江自流,吴宫花草埋幽径,晋代衣冠成古丘</a></li>
</ul>
</div>
</body>
</html>
bs4 基本使用
1.安装:
pip install bs4
2.使用流程
- bs4基本使用流程:
1.实例化一个BeautifulSoup对象,把即将被解析的页面源码数据加载到该对象中
2.调用BeautifulSoup对象的属性和方法实现标签定位和数据提取
3.BeautifulSoup对象实例化
方式1: BeautifulSoup(fp,'lxml'):用来解析本地存储的网页文件
方式2: BeautifulSoup(page_text,'lxml'):用来解析网络中请求到的数据
4.解析本地存储的网页文件
from bs4 import BeautifulSoup
# 获取本地的文件句柄
fp = open('./test.html','r',encoding='utf-8')
# 实例化BeautifulSoup对象
soup = BeautifulSoup(fp,'lxml')
# 1.标签定位
#soup.tagName(标签名称):可以将第一次出现的该标签定位到
print(soup.div) # 获得一个对象
# 2.属性定位:find(tagName,attrName(属性名称)_='attrValue')
# 注意属性名称后有下划线
print(soup.find('div',class_='song')) # 获得一个对象
print(soup.findAll('div',class_='song')) # 获得对象列表
# 3.选择器定位
print(soup.select('#feng')) # 获取id='feng'的标签对象列表
# 4.层级选择器:>表示一个层级,空格可以表示多个层级
print(soup.select('.tang li > a')) # 获取class='tang'的标签里面的对象列表
# 5.获取标签文本
a_tag = soup.select('#feng')[0]
print(a_tag.string) # string -- 取直系文本
div_tag = soup.select('.song')[0]
print(div_tag.text) # text -- 取所有文本
# 6.获取标签属性
a_tag = soup.select('#feng')[0]
print(a_tag)
print(a_tag['href'])
5.解析网络中请求到的数据
爬取网络小说
import requests
from bs4 import BeautifulSoup
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36'
}
url = 'https://www.shicimingju.com/book/sanguoyanyi.html'
# 获取响应数据
response = requests.get(url)
# 如果获取的数据乱码,指定编码集 utf-8 或 gbk
response.encoding = 'utf-8'
page_text = response.text
# print(page_text)
fp = open('三国.text','w',encoding='utf-8') # 文件对象,保存小说数据
# 实例化BeautifulSoup对象
soup = BeautifulSoup(page_text,'lxml')
# 定位到小说章节标签
tag = soup.select('.book-mulu > ul > li >a')
# print(tag)
# 获取小说章节名称和路径
for i in tag:
# 获取文章路径
new_url = 'https://www.shicimingju.com'+i['href']
# 获取小说章节名称
title = i.string
# print(new_url,title)
# 发起get请求获取数据
response = requests.get(new_url,headers=headers)
response.encoding = 'utf-8' # 解决乱码
p_text = response.text
# print(article)
# 实例化BeautifulSoup对象
soup = BeautifulSoup(p_text, 'lxml')
# 定位文章内容标签
# article_tag = soup.select('.chapter_content')[0] # 两者都可以
article_tag = soup.find('div',class_='chapter_content') #
# 获取文章内容
article_text = article_tag.text
# 保存数据(标题和内容)
fp.write(title+'\n'+article_text+'\n')
print(title,'保存成功')
xpath 基本使用
1.安装:
pip install lxml
2.使用流程
- 编码流程 :
1.实例化一个etree类型的对象,把即将被解析的页面源码数据加载到该对象中
2.调用xpath方法结合着不同形式的xpath表达式进行标签定位和数据提取
3.etree 对象实例化
1. etree.parse(filePath) -- 用来解析本地存储的网页文件
2. etee.HTML(page_text) -- 用来解析网络中请求到的数据
4.解析本地存储的网页文件
from lxml import etree
# 实例化对象
tree = etree.parse('./test.html')
# 1.标签定位
#最左侧的/:必须从根节点逐层往下定位标签
#最左侧的//:从任意位置定位指定标签
tag = tree.xpath('/html/head/title')
tag = tree.xpath('/html//title')
tag = tree.xpath('//title')
# 2.属性定位
tag = tree.xpath('//div[@class="tang"]')
print(tag)
# 3.索引定位:索引时从1开始
tag = tree.xpath('//div[@class="tang"]/ul/li[3]')
print(tag)
# 4.取文本:/text()--取直系文本 //text()--取所有
# 获取的都是列表数据 -- 索引取值
div_tag = tree.xpath('//div[@class="tang"]//text()')
print(''.join(div_tag))
# 5.取属性:/@attrName(属性名) -- 获取的也是列表数据
a = tree.xpath('//a[@id="feng"]/@href')[0]
print(a)
5.解析网络中请求到的数据
爬取图片
# 网址: 'https://pic.netbian.com/4kmeinv/'
import requests
from lxml import etree
import os
# 创建储存图片的文件夹
dirname = 'image'
# 判断文件夹是否存在,如果不存在新建目录
if not os.path.exists(dirname):
os.mkdir(dirname)
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36'
}
url = 'https://pic.netbian.com/4kmeinv/index_%d.html'
# 爬取多张页数据
for i in range(1,10):
if i == 1:
new_url = 'https://pic.netbian.com/4kmeinv/'
else:
new_url = format(url%i)
response = requests.get(new_url,headers=headers)
response.encoding = 'gbk' # 防止乱码
page_text = response.text
# print(page_text)
# 实例化对象
tree = etree.HTML(page_text)
# 取出li标签对象列表
li_list = tree.xpath('//*[@id="main"]/div[3]/ul/li')
# print(li_list)
# 获取图片地址和名称
for i in li_list:
title = i.xpath('./a/b/text()')[0] + '.jpg'
src = 'https://pic.netbian.com' + i.xpath('./a/img/@src')[0]
# print(title,src)
# 获取图片详细数据,保存图片
response = requests.get(src,headers=headers)
img_data = response.content # batys流数据
# 拼接文件路径
filepath = dirname + '/' + title
with open(filepath,'wb') as fp:
fp.write(img_data)
print(title,'保存成功')