B站视频链接:https://www.bilibili.com/video/BV1FJ411L7Hn
爬虫
一.基本指令
import requests
#1.定义URL
url='https://www.baidu.com'
#2.发起get请求
res=requests.get(url)
#3.获取响应结果
res.status_code #200代表成功
res.url #请求的url地址
res.content#b'...' 二进制文本流
res.content.decode('utf-8')
res.text #获取响应的内容
res.headers #响应头信息#{'Cache-Control': 'private, no-cache, no-store, proxy-revalidate, no-transform', 'Connection': 'keep-alive', 'Content-Encoding': 'gzip', 'Content-Type': 'text/html', 'Date': 'Mon, 13 Jan 2020 02:11:01 GMT', 'Last-Modified': 'Mon, 23 Jan 2017 13:24:45 GMT', 'Pragma': 'no-cache', 'Server': 'bfe/1.0.8.18', 'Set-Cookie': 'BDORZ=27315; max-age=86400; domain=.baidu.com; path=/', 'Transfer-Encoding': 'chunked'}
res.request.headers#请求的头信息#{'User-Agent': 'python-requests/2.22.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}
二.GET请求
#1.定义url
url='https://www.xicidaili.com/nn'
#2.自定义请求头信息--从浏览的网页中获取
headers={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362'
}
res=requests.get(url=url,headers=headers)
#3.响应成功后把响应内容写入文件中
code=res.status_code
if code==200:
with open('./test.html','w',encoding='utf-8') as fp:
fp.write(res.text)
三.POST请求
#1.定义url
u='https://fanyi.baidu.com/sug'
#2.定义请求信息头
headers={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362'
}
#3.post发送的数据
data={'kw':'你好'}
#4.发送请求
res=requests.post(url=u,headers=headers,data=data)
#5.接受返回数据
code=res.status_code
if code==200:
print('请求成功')
data=res.json() #数据是json格式的
if data['errno']==0:
print('响应成功')
print(data)
print(data['data'][0]['k']) #返回数据中,data list中第一个字典
v=data['data'][0]['v']
print(v.split(';')[-2])
四.主动添加-携带cookie
#1.定义url
u='https://fanyi.baidu.com/sug'
#2.定义请求信息头
headers={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362',
'cookie':'' #浏览器中获取cookie信息
}
#3.post发送的数据
data={'kw':'你好'}
#4.发送请求
res=requests.post(url=u,headers=headers,data=data)
#5.接受返回数据
code=res.status_code
if code==200:
print('请求成功')
data=res.json() #数据是json格式的
if data['errno']==0:
print('响应成功')
print(data)
print(data['data'][0]['k']) #返回数据中,data list中第一个字典
v=data['data'][0]['v']
print(v.split(';')[-2])
五.python自动获取cookie信息
使用requests中的session方法
#1.定义URL
url='http://' #最终请求目标地址
login_url='http://' #登录后-登录请求的URL//Headers-General-URL
#2.请求头信息
headers={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362'
}
#3.使用session方法
'''
如果需要爬虫程序主动记录并携带cookie,那么在使用requests前需先调用session方法
并且使用session方法返回的对象发送请求即可
'''
req=requests.session()
#4.发起登录请求
##登录时的数据//Form Data
data={
'account':'',
'password':'',
'remember':'',
'url_back':''
}
##
res=req.post(url=login_url,headers=headers,data=data)
#5.判断状态并写入
code=res.status_code
if code==200:
#发起新请求,去获取目标数据
res=req.get(url=url,headers=headers)
with open('test.html','w') as fp:
fp.write(res.text)
六.Xpath解析数据
#1.【在python代码中解析字符串】
from lxml import etree
#1.1 获取源代码
text='''
#访问网页-源代码
'''
#1.2 使用etree解析html字符串
html=etree.HTML(text)
#1.3 提取数据
r=html.xpath('/html/body/li/a/text()') #获取指定标签body下的li标签下的数据
print(r)
#获取页面所有li标签下的数据 :r=html.xpath('//li/a//text()')
#获取指定标签下的li数据:r=html.xpath('//div[@class='teacher']//li/a/text()')
#2.【读取一个html文件并解析】
###先把网页代码粘贴到html文件中
html=etree.parse('./test.html', etree.HTMLParser())
r=etree.tostring(html)
print(r.decode('utf-8'))
七.Xpath实战登录
import requests
from lxml import etree
#封装类。进行网站的登录和订单的获取
class Lmonkey():
loginurl=''
orderurl=''
headers={
'User-Agent':''
}
#请求对象
req=None
#token口令
token=''
#订单号
ordercode=0
#初始化方法
def __init__(self):
#请求对象的初始化
self.req = requests.session()
if self.getlogin():
if self.postlogin():
self.getorder()
#get 登录页面 获取_token
def getlogin(self):
#1.get请求 login页面,设置cookie,获取_token
res=self.req.get(url=self.loginurl,headers=self.headers)
if res.status_code==200:
print('get登录页面请求成功')
html=etree.HTML(res.text)
self.token=html.xpath('//input[@name="_token"]/@value')[0]
print('token获取成功')
return True
else:
print('请求错误')
#post 请求登录 设置cookie
def postlogin(self):
uname=input('手机号:')
passw=input('密码:')
data={
'_token':self.token,
'username':uname,
'password':passw
}
#发起post请求
res=self.req.post(url=self.loginurl,headers=self.headers,data=data)
if res.status_code==200 or res.status_code==302:
print('登录成功')
#请求订单数据
return True
#get 请求账户中心 获取默认订单号
def getorder(self):
#3.get请求,账户中心,获取默认订单号
pass
res=self.req.get(url=self.orderurl,headers=self.headers)
if res.status_code==200:
print('账户中心请求成功,正在解析数据')
html=etree.HTML(res.text)
r=html.xpath('//div[@class="avatar-content"]//small/@text()')
print(r)
self.ordercode=r
obj=Lmonkey()
#1.get请求 login页面,设置cookie,获取_token
#2.post请求 提交登录数据,进行登录,并设置cookie
#3.get请求,账户中心,获取默认订单号
八.beautiful soup
1.基本语法
from bs4 import BeautifulSoup
#1.定义html文档内容
html_doc='''
<html><head><title abc='123'>The Dormouse's story</title></head><body>
<p class='title'><b>The Dormouse's story</b></p>
<p class='story'>Once upon a time there was three little sisters; and their names were
<a herf='http://example.com/elsie' class='sister' id='link1'>Elsie</a>,
<a herf='http://example.com/lacie' class='sister' id='link2'>Lacie</a> and
<a herf='http://example.com/tillie' class='sister' id='link3'>Tillie</a>;
and they lived at the botom of a well.</p>
</ class='story'>...</p>
'''
#2.创建一个BeautifulSoup对象,建议手动指定解析器:
soup=BeautifulSoup(html_doc,'lxml')
#2.1 通过tag标签对象获取文档数据
r=soup.title #title标签(元素)
r=soup.title['abc']#结果123
r=soup.p #第一个p标签结果--<p class='title'><b>The Dormouse's story</b></p>
r=soup.p['class']#p元素的class属性--['title']
r=soup.p.b#p标签下的b标签--<b>The Dormouse's story</b>
r=soup.title.text #获取title下的文本--结果The Dormouse's story
r=soup.p.parent.name#p元素的父节点的标签--body
#2.2 通过搜索获取页面中的元素(使用find和find_all方法进行查找
'''
- find和find_all可以有多个搜索条件叠加,比如find('a',id='link3',class_='sister')
- find 返回的是一个bs4.element.Tag对象,这个对象可以进一步进行搜索。如果有多个满足的结果,find只返回第一个;如果没有,返回None
- find_all 返回的是一个由bs4.element.Tag对象组成的list,不管找到几个或是没找到,都是list
'''
soup.find(id='link3') #id为link3的元素
'''
<a herf="http://example.com/tillie" class='sister' id='link3'>Tillie</a>
soup.find_all('a')#所有a元素
[<a herf="http://example.com/elsie" class='sister' id='link1'>Elsie</a>,
<a herf="http://example.com/lacie" class='sister' id='link2'>Lacie</a> and
<a herf="http://example.com/tillie" class='sister' id='link3'>Tillie</a>]
'''
x=soup.find(class_='story')
x.get_text() #仅可见文本内容
#'Once upon a time there was three little sisters; and their names were\nElsie,\nLacie and\nTillie;\nand and they lived at the botom of a well.'
#2.3 css选择器
soup.select('title') #通过tag查找
soup.select('html head title') #通过tag逐层查找
soup.select('.sister') #通过class查找
soup.select('#link1,#link2') #通过id查找
soup.select('p #link1') #组合查找
soup.select('html body p') #通过空格 层级关系获取元素
soup.select('a,title') #通过逗号,并列关系获取元素
soup.select('head>title') #查找直接子标签
soup.select('p>#link1')
soup.select('p>a:nth-of-type(2)')#nth-of-type是css选择器
soup.select('#link1~.sister') #查找兄弟节点(向后查找)
soup.select('#link1+.sister')
soup.select('a[href="http://example.com/1"]') #通过属性查找
soup.select('a[href^="http://example.com/"]') #^以xx开头
soup.select('a[href*=".com/"]') #*包含
soup.select('[name]') #查找包含指定属性的标签
soup.select_one('.sister') #查找第一个元素
2.bs4实战
2.1 原始代码
#--学习猿地-猿圈
'''
分析爬取的数据
数据源地址:http://www,lmonkey.com/t
数据内容:文章标题,文章的链接,作者,发布时间
工具:python,requests,bs4
'''
import requests,json
from bs4 import BeautifulSoup
#1.定义请求的URL和请求头
url='http://www,lmonkey.com/t'
headers={
'user-agent':''
}
#2.发送请求
res1=requests.get(url=url,headers=headers)
#3.判断请求是否成功,并获取请求源代码
if res1.status_code==200:
#4.解析数据
soup=BeautifulSoup(res1.text,'lxml')
#---获取页面中所有文章
divs=soup.find_all('div',class_='list-group-item list-group-item-action p-60')
varlist=[]
for i in divs:
r=i.find('div,class_="topic_title"')
if r: #如果r结果为真,打印内容
vardict={'title':r.text.split('\n')[0],
'url':i.a['href'],
'author':i.strong.a.text,
'pubdate':i.span['title']
}
varlist.append(vardict)
print(varlist)
#5.写入数据
with open('./yq.json','w') as fp:
json.dump(varlist,fp)
2.2 优化代码
#封装类
class Bs4Yq():
#定义属性:url&请求头
url='http://www,lmonkey.com/t'
headers={
'user-agent':""
}
#响应源代码的存放位置
res2_html = None
#存储解析后的json数据
varlist=[]
#初始化方法
def __init__(self):
#发起一个请求
res2=requests.get(self.url,headers=self.headers)
if res2.status_code==200:
self.res2_html=res2.text
if self.ParseData():
self.WriteJson()
print('数据成功,写入文件')
else:
print('请求失败')
#解析html数据
def ParseData(self):
soup=BeautifulSoup(self.res2_html,'lxml')
try:
#---获取页面中所有文章
divs=soup.find_all('div',class_='list-group-item list-group-item-action p-60')
for i in divs:
r=i.find('div,class_="topic_title"')
if r: #如果r结果为真,打印内容
vardict={'title':r.text.split('\n')[0],
'url':i.a['href'],
'author':i.strong.a.text,
'pubdate':i.span['title']
}
self.varlist.append(vardict)
return True
except:
return False
#写入json数据
def WriteJson(self):
if self.varlist !=[]:
try:
with open('./yq.json', 'w') as fp:
json.dump(self.varlist,fp)
return True
except:
return False
else:
print('无法获取当前的解析数据')
Bs4Yq() #调用
九.正则表达式
正则表达式:一种规则(由各类字符组成),使用这种规则能对文本内容完成搜索/匹配/替换的功能
正则表达式的组成
普通字符:大小写,数字,符号
转义字符:\w \W \d \D \s \S...
特殊字符:. * ? + $ ^ [] () {}
匹配模式:I U ...
1.使用方法
import re
#定义字符串
vars='iloveyou521tosimida'
#定义正则表达式
reg='\d'
#调用
res=re.findall(reg,vars)
2.re模块的相关函数
- re.match()
- 从头开始匹配
- 要么第一个就符合,要么不符合
- 匹配成功则返回match的对象,否则返回none
- 可以使用group()/span()方法
res=re.match(reg,vars) res.group() #获取一个返回的数据结果 res.groups() #获取多个数据结果 res.span() #获取结果的下标区间
- re.search()
- 从字符串开头到结尾进行搜索式匹配
- 匹配成功则返回match的对象,否则返回none
- 可以使用group()/span()方法
- match()和search()方法的区别:
- match() 是从字符串的开头进行匹配,如果开始就不符合正则要求,则匹配失败返回none
- search() 是从字符串开始位置一直搜索到字符串的最后,如果在整个字符串都没有匹配到,则失败返回none
- re.findall()
- 按照正则表达式的规则在字符串中匹配所有符合规则的元素,返回一个列表,如果没有找到则返回空列表
- re.finditer()
- 按照正则表达式的规则在字符中匹配所有符合规则的元素,返回一个迭代器
res=re.finditer(reg,var) res1=list(res) print(res1)
- 按照正则表达式的规则在字符中匹配所有符合规则的元素,返回一个迭代器
- re.sub() 搜索替换
- 参数
- pattern:正则表达式的规则,匹配需要被替换的字符串
- repel:替换后的字符串
- string:被替换的原始字符串
import re varstr='' reg='' res=re.sub(reg,'替换内容',varstr)
- 参数
- compile()
- 定义正则表达式模式
- 可以将正则表达式定义为“正则对象”,使用正则对象直接操作
- 大量数据适用这种方法
reg=re.compile('\d{3}') res=reg.findall(string=vars)
3.正则表达式的定义和规则
- (1)普通字符:大小写,数字,符号
- (2)转义字符:\w \W \d \D \s \S...
reg='\w' #单个的 字母/数字/下划线
reg='\W' #单个的 非字母/数字/下划线
reg='\d' #单个的 数字
reg='\D' #单个的 非数字
reg='\s' #单个的 空格符/制表符
reg='\S' #单个的 非空格符/制表符
reg='\w\w\w\w\d' #组合使用
- (3)特殊字符:. * ? + $ ^ [] () {}
reg='.' #单个的 任意字符 除了换行符之外
reg='\w*' #* 代表匹配任意次数
#特点:
#--如果在匹配的开始处符合要求,则一直向后匹配,直到不符合匹配规则的结束,并返回前面符合规则的.
#--如果在匹配的开始处,则直接返回,匹配到的次数为0
reg='\w+' #+ 至少匹配一次
reg='\w+?' #? 拒绝贪婪==前面的匹配规则只要达成则返回
reg='\w{4}' #{匹配次数} ;{2,5}匹配2-5次
reg='[a-z]' #[] 匹配范围 #[a-z,A-Z,0-9,_]==\w
reg='\w(\d{4})' #() 代表子组,括号中的表达式首先作为整个正则的一部分,零位会把符合小括号中的内容单独提取
reg='^1\d{10}$' #^ 定义开头(开头是个1;$定义结尾(结尾是数字
reg=''
reg=''
- (4)匹配模式:I U ...
vars='iLOVEyou'
reg='[a-z]{5,10}' #小写字母,连续5-10个
res=re.search(reg,vars,re.I)
#用re.I模式忽略大小写
4.正则实战
import requests,re,json
#1.
url=''
headers={
'user-agent':''
}
#2.
res=requests.get(url,headers=headers)
#3.判断并获取数据
if res.status_code==200:
res_html=res.text
#4.数据解析
reg=''
arr=re.findall(reg,res_html)
titlelist=[i.strip() for i in arr] #去除空格
reg1=''
authorlist=re.findall(reg1,res_html)
reg2=''
datelist=re.findall(reg2,res_html)
#5.压缩数据
data=list(zip(titlelist,authorlist,datelist))
#6.1常规方式 处理数据
datalist=[]
for i in data:
res={'title':i[0],'author':i[1],'date':i[2]}
datalist.append(res)
#6.2其他方法
datalist=[{'title':i[0],'author':i[1],'date':i[2]} for i in data]
#7.数据入库
with open('./data.json','w',encoding='utf-8') as fp:
json.dump(datalist,fp)
网友评论