1 requests库的深度应用
网页信息采集
import requests
if __name__=="__main__":
url=""
#将参数封装到字典中
kw=input("enter a word:")
param:{
'query':kw
}
#UA:User-Agent(请求载体的身份标识)
#UA伪装:让爬虫对应的请求载体身份标识伪装成一款浏览器
#UA伪装:将对应的User-Agent封装到一个字典中
headers:{
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.0'
}
requests.get(url=url,params=param,headers=headers)
page_text=requests.text
filename=kw+'html'
#保存为文件
with open(filename,'w',encoding='utf-8') as fp:
fp.write(page_text)
print('保存成功!')
重点:
反爬机制:
UA检测:相关的门户网站通过检测请求该网站的载体身份来辨别该请求是否为爬虫程序,如果是,则网站数据请求失败。因为正常用户对网站发起的请求的载体一定是基于某一款浏览器,如果网站检测到某一请求载体身份标识不是基于浏览器的,则让其请求失败。因此,UA检测是我们整个课程中遇到的第二种反爬机制,第一种是robots协议。
反反爬策略:
UA伪装:通过修改/伪装爬虫请求的User-Agent来破解UA检测这种反爬机制。
破解百度翻译
-post请求(携带了参数)
-响应数据是json数据
AJAX
AJAX = Asynchronous JavaScript and XML(AJAX = 异步 JavaScript 和 XML。)。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 是一种用于创建快速动态网页的技术。
通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。
import requests
import json
if __name__=="__main__":
#1.指定url
post_url='https://fanyi.baidu.com/sug'
#2.UA伪装
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:87.0) Gecko/20100101 Firefox/87.0'
}
#3.post请求参数处理
data={
'kw':'dog'
}
#4.发送请求
response=requests.post(url=post_url,data=data,headers=headers)
#5.获取响应数据
dic_obj=response.json()
#6.持久化存储
fp=open('./dog.json','w',encoding='utf-8')
json.dump(dic_obj,fp=fp,ensure_ascii=False)
print('over')
方法:
json()
json.dump() 主要用来将python对象写入json文件
数据解析概述
数据解析分类
-
正则
-
bs4
-
xpath(***)
数据解析原理概述
-
解析的局部文本内容都会在标签之间或者标签对应的属性中进行存储
-
1.进行指定标签的定位
-
2.标签或者标签对应的属性中存储的数据进行提取
正则表达式
图片爬取
import requests
if __name__=="__main__":
url="https://doge.zzzmh.cn/wallpaper/origin/b0fced9bf8864e88bb35b437b72f0c14.jpg"
#content 返回二进制形式的图片数据
# text(字符串) content(二进制) json() (
img_data=requests.get(url=url).content
with open ('./test.jpg','wb') as fp:
fp.write(img_data)
壁纸网站下载壁纸
import requests
import re
import os
if __name__=="__main__":
if not os.path.exists('./bizhi'):
os.mkdir('./bizhi')
url="https://bz.zzzmh.cn/favorite"
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}
page_text=requests.get(url=url,headers=headers).text
#print(page_text)
# use the focus crawler to crawl all wallpapers
ex='<div class="v-image__image v-image__image--cover" style="background-image: url("(.*?);); background-position:.*?</div>'
image_url=re.findall(ex,page_text,re.S)
#print(image_url)
for src in image_url:
image_data=requests.get(url=src,headers=headers).content
image_name=src.split('/')[-1]
imgpath='./bizhi'+image_name
with open(imgpath,'wb') as fp:
fp.write(image_data)
print(image_name,"ok!!!!!!")
要点:
使用正则表达式来匹配当前页面下的所有图片
添加分页操作:1.设置通用url 2.利用for循环改变页码的值
bs4进行数据解析
原理:
- 实例化一个BeautifulSoup对象,并且将页面源码数据加载到该对象中
- 通过调用BeautifulSoup对象中相关的属性或者方法进行标签定位和数据提取
对象的实例化:
- 将本地的html文档中的数据加载到该对象中
- 将互联网上获取的页面源码加载到该对象中
基础使用
使用流程:
- 导包:from bs4 import BeautifulSoup
- 使用方式:可以将一个html文档,转化为BeautifulSoup对象,然后通过对象的方法或者属性去查找指定的节点内容
(1)转化本地文件:
- soup = BeautifulSoup(open('本地文件'), 'lxml')
(2)转化网络文件:
- soup = BeautifulSoup('字符串类型或者字节类型', 'lxml')
(3)打印soup对象显示内容为html文件中的内容
基础巩固:
(1)根据标签名查找
- soup.a 只能找到第一个符合要求的标签
(2)获取属性
- soup.a.attrs 获取a所有的属性和属性值,返回一个字典
- soup.a.attrs['href'] 获取href属性
- soup.a['href'] 也可简写为这种形式
(3)获取内容
- soup.a.string
- soup.a.text
- soup.a.get_text()
【注意】如果标签还有标签,那么string获取到的结果为None,而其它两个,可以获取文本内容
(4)find:找到第一个符合要求的标签
- soup.find('a') 找到第一个符合要求的
- soup.find('a', title="xxx")
- soup.find('a', alt="xxx")
- soup.find('a', class_="xxx")
- soup.find('a', id="xxx")
(5)find_all:找到所有符合要求的标签
- soup.find_all('a')
- soup.find_all(['a','b']) 找到所有的a和b标签
- soup.find_all('a', limit=2) 限制前两个
(6)根据选择器选择指定的内容
select:soup.select('#feng')
- 常见的选择器:标签选择器(a)、类选择器(.)、id选择器(#)、层级选择器
- 层级选择器:
div .dudu #lala .meme .xixi 下面好多级
div > p > a > .lala 只能是下面一级
【注意】select选择器返回永远是列表,需要通过下标提取指定的对象
实战
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import requests
from bs4 import BeautifulSoup
headers={
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36',
}
def parse_content(url):
#获取标题正文页数据
page_text = requests.get(url,headers=headers).text
soup = BeautifulSoup(page_text,'lxml')
#解析获得标签
ele = soup.find('div',class_='chapter_content')
content = ele.text #获取标签中的数据值
return content
if __name__ == "__main__":
url = 'http://www.shicimingju.com/book/sanguoyanyi.html'
reponse = requests.get(url=url,headers=headers)
page_text = reponse.text
#创建soup对象
soup = BeautifulSoup(page_text,'lxml')
#解析数据
a_eles = soup.select('.book-mulu > ul > li > a')
print(a_eles)
cap = 1
for ele in a_eles:
print('开始下载第%d章节'%cap)
cap+=1
title = ele.string
content_url = 'http://www.shicimingju.com'+ele['href']
content = parse_content(content_url)
with open('./sanguo.txt','w') as fp:
fp.write(title+":"+content+'\n\n\n\n\n')
print('结束下载第%d章节'%cap)
Xpath
最常用且最高效便捷的一种解析方式。通用性。
xpath解析原理
- 实例化一个etree的对象,且需要将被解析的页面源码数据加载到该对象中。
- 调用etree对象中的xpath方法结合xpath表达式实现标签的定位和内容的捕获。
如何实例化一个etree对象
-
本地
- etree.parse(filePath)
-
网络
- etree.HTML(‘page_text’)
-
xpath(‘xpath表达式’)
xpath的表达式
层级定位:
#找到class属性值为song的标签
//div[@class="song"]
层级&索引定位:
#找到class属性值为tang的div的直系子标签ul下的第二个子标签li下的直系子标签a
//div[@class="tang"]/ul/li[2]/a
逻辑运算:
#找到href属性值为空且class属性值为du的a标签
//a[@href="" and @class="du"]
模糊匹配:
//div[contains(@class,"ng")]
//div[starts-with(@class,"ta")]
取文本:
# /表示获取某个标签下的文本内容
# //表示获取某个标签下的文本内容和所有子标签下的文本内容
//div[@class="song"]/p[1]/text()
//div[@class="tang"]//text()
取属性:
//div[@class="tang"]//li[2]/a/@href
图片解析
import requests
from lxml import etree
url = 'http://pic.netbian.com/4kmeinv/'
headers = {
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
}
response = requests.get(url=url,headers=headers)
#获取页面原始编码格式
print(response.encoding)
page_text = response.text
tree = etree.HTML(page_text)
li_list = tree.xpath('//div[@class="slist"]/ul/li')
for li in li_list:
img_url = 'http://pic.netbian.com'+li.xpath('./a/img/@src')[0]
img_name = li.xpath('./a/img/@alt')[0]
img_name = img_name.encode('iso-8859-1').decode('gbk')
print(img_url,img_name)