urllib是爬虫常用的一个库,通过他我们能爬取浏览器上的数据,而爬虫则是我们模仿浏览器去爬取数据的一种称号,即将自己假扮成浏览器去拿取数据
=========================================================================
#使用urllib获取百度首页的源码
import urllib.request
#(1)定义一个url :你要访问的页面:baidu.com
url = 'http://www.baidu.com/?tn=59044660_1_hao_pg&H123Tmp=nunew11'
#(2)模拟浏览器给服务器发送请求
response = urllib.request.urlopen(url)
#(3)获取响应中的页面的源码
#read方法 返回的是字节形式二进制数据
#二进制==》字符串 解码 decode('编码格式')
content = response.read().decode('utf-8')
#(4)打印数据
print(content)
注意:要用http而不是https,
原因:https相较于http的区别:
1、https的端口是443,而http的端口是80,且两者的连接方式不同;
2、http传输是明文的,而https是用ssl进行加密的,https的安全性更高;
3、https是需要申请证书的,而http不需要。 本文操作环境:Windows7系统、Dell G3电脑。
运行结果(截取部分):
=========================================================================
前言: 通过urllib.request()获取的对象是类型是HttpReponse型的,针对这种类型,有六种常见的读取方法
一个类型:HttpResponse
六个方法:
read(): 读取所有字节
read(n): 读取n个字节
readline(): 读取一行
readline(): 按行读取,并且读取所有行
getcode(): 返回状态码
getur(): 返回url地址
getheaders(): 获取一个状态信息
具体实验代码:
import urllib.request
url = 'https://www.baidu.com'
#模拟浏览器给服务器发送请求
response = urllib.request.urlopen(url)
#一个类型和六个方法
# print(type(response))
# 读取多少个字节
# content = response.read()
# print(content)
#读取多少个字节
# content = response.read(5)
# print(content)
#读取一行
# content = response.readline()
# print(content)
# content = response.readlines()
# print(content)
#返回状态码
# print(response.getcode())
#返回的url地址
# print(response.geturl())
#获取是一个状态信息
# print(response.getheaders())
# 一个类型:HttpResponse
# 六个方法:read readline readlines getcode geturl getheaders
=========================================================================
前言:接下来到了我最兴奋的下载了(滑稽),通过urlretrieve()下载
这里我们将通过网页,图片和视频的下载,教大家如何下载,但是只适用于那些没有任何没有反爬虫的网站
方法介绍:urlretrieve(url,filename),其中url是我们获取资源的网址,而filename是我们下载好的资源的名字
如何获取资源的地址:
以获取百度的html文件为例子,百度的网页地址是:http://www.baidu.com
那么我们就直接使用这个url即可
获取http://www.baidu.com的html文件:
import urllib.request #下载网页 url_page = "http://www.baidu.com" urllib.request.urlretrieve(url_page,"baidu.html")
下载结果:
运行HTML文件:
同理我们还可以获取图片资源和视频资源
获取图片资源
1.我们打开百度,搜素你要找的图片,然后按下F12进入编辑者模式,查看图片的src
然后我们将src的地址输入到网站,查看这张图片是否是存在的
然后依葫芦画瓢,将上文中的url改为src的url,file的文件格式又.html改为.jpg
import urllib.request
# 下载图片
url_image="https://img1.baidu.com/it/u=2378119578,1413173279&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=508"
urllib.request.urlretrieve(url_image,"周杰伦.jpg")
视频的下载方式同理(下面用一下一个动漫网站)
视频下载
然后对src进行测试
接着将url改为上述的url地址,并将file的格式改为.mp4等视频格式
import urllib.request
#下载地址
url_video = "https://v6.bdxiguavod.com/9419a4d3395a54752a4e6cb7ff991170/62d6e45e/video/tos/cn/tos-cn-v-3506/00e32bf5691142d287fd4a706947905f/"
urllib.request.urlretrieve(url_video,"hhh.mp4")
下载时间有点长,就不展示了
=========================================================================
首先我们需要知道为什么要进行请求头的定制:请求头是最常见的反爬手段,定制请求头是为了应付反爬。
如何再浏览器中找到请求头:
如何再urllib中定制请求头(再这里我们只需要用到请求头中的User-Agent):
import urllib.request
url = "https://www.baidu.com"
#url的组成
#https://www.baidu.com/s?wd=周杰伦
#http/https www.baidu.com 80/443 s wd=周杰伦 #
# 协议 主机 端口号 路径 参数 瞄点
#UA反爬
headers ={
# "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.66 Safari/537.36 Edg/103.0.1264.44"
"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.66 Safari/537.36 Edg/103.0.1264.44"
}
#因为urlopen方法中不能存储字典,所有headers不能直接传递过去
#请求对象的定制
#注意 因为参数顺序的问题,不能直接写url和headers 中间还有一个data 用关键参数传参
request = urllib.request.Request(url=url,headers=headers)
response = urllib.request.urlopen(request)
content = response.read().decode("utf-8")
print(content)
运行成功
注意urllib请求头的定制的方法有三个参数:url,data,headers
=========================================================================
我们平常百度某要东西是都在浏览器里面输入关键字进行搜素,而在urllib中我们同样油类似的方法对我们的爬虫文件进行指定搜素
首先我们想看看浏览器是怎么搜素的:
所以我们只需要对wd这个参数进行进行传参即可,而在urllib的库里面有一个方法可以完成这一需求,get请求的方法:quote()
import urllib.request
#https://www.baidu.com/s?wd=%E5%91%A8%E6%9D%B0%E4%BC%A6
#需求:获取https://www.baidu.com/s?wd=周杰伦的网页代码
# 寻找url
url = "https://www.baidu.com/s?wd="
# 第一个反爬UA
headers={
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.66 Safari/537.36 Edg/103.0.1264.44'
}
# 编码转换
name=urllib.parse.quote("周杰伦")
# 组装url
url=url+name
# print(url)
# 请求对象的定制
request = urllib.request.Request(url=url, headers=headers)
# 向服务器发请求
response = urllib.request.urlopen(request)
#获取响应信息
content=response.read().decode("utf-8")
# 打印响应信息
print(content)
但我们要爬取多个参数时,urllib的get请求也给我们提供了urlencode()方法
#urlencode应用场景:多个参数的时候
# import urllib.parse
#
# data={
# 'wd' : '周杰伦',
# 'sex': '男'
# }
# urlencode= urllib.parse.urlencode(data)
# print(urlencode)
import urllib.request
import urllib.parse
url ='https://www.baidu.com/s?'
data={
'wd' : '周杰伦',
'sex': '男',
'location':'中国台湾'
}
new_data = urllib.parse.urlencode(data)
headers={
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.66 Safari/537.36 Edg/103.0.1264.44'
}
url=url+new_data
print(url)
request = urllib.request.Request(url=url, headers=headers)
response = urllib.request.urlopen(request)
content = response.read().decode("utf-8")
print(content)
=========================================================================
我们打开百度翻译并用英文输入法输入egg,可以看到,我们输入发egg被输出到sug文件的kw参数上
因此我们需要对kw参数传参,而这需要用post请求才能完成
import urllib.request
import urllib.parse
url='https://fanyi.baidu.com/sug'
headers={
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.66 Safari/537.36 Edg/103.0.1264.44'
}
data={
'kw':'spider'
}
#post请求的参数,必须进行编码
data = urllib.parse.urlencode(data).encode("utf-8")
#定制请求对象
request = urllib.request.Request(url=url, data=data, headers=headers)
#向浏览器发送请求
response= urllib.request.urlopen(request)
#获取响应信息
content = response.read().decode("utf-8")
#我们所请求到的参数时json格式,因此要进行json转
#字符串==》json对象
import json
obj = json.loads(content)
print(obj)
#post请求必须编码
#编码之后必须调用encode方法
#参数方正请求对象定制的方法中
=========================================================================
1.post请求的参数必须编码+转码,也即编码之后,必须调用encode方法:
data = urllib.parse.urlencode(data).encode('utf-8')
但get请求的参数只需要进行编码即可,也即:
data = urllib.parse.urlencode(data)
2.post请求的参数放在请求对象的定制过程中,而不是拼接字符串:
request = urllib.request.Request(url = url,data = data,headers = headers)
response = urllib.request.urlopen(request)
但get请求的参数使用字符串拼接在url上:
url = base_url + uni_data
request = urllib.request.Request(url = url,headers = headers)
response = urllib.request.urlopen(request)
=========================================================================
直接上代码
import urllib.request
import urllib.error
url = 'http://www.baidu.com1'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.66 Safari/537.36 Edg/103.0.1264.44'
}
try:
request = urllib.request.Request(url=url, headers=headers)
responce = urllib.request.urlopen(request)
content = responce.read().decode("utf-8")
print(content)
except urllib.error.HTTPError:
print('系统正在升级')
except urllib.error.URLError:
print("你输入错误")
第一个错误是HTTPError,这是HTTP请求的错误,我们通过urllib.error.HTTPError这个类型进行匹配,捕捉后对错误进行处理即可
第二个错误是URLError,这是把url书写错误后的错误,我们通过urllib.error.URLError这个类型进行匹配,捕捉后同样处理错误。
=========================================================================
什么时handler处理器:
handler处理器是urllib库中继urlopen()方法之后又一种模拟浏览器向服务器发起请求的方法或技术。
它的意义在于使用handler处理器,能够携带代理ip,这为对抗反爬机制提供了一种策略(很多的网站会封掉短时间多次访问的ip地址)。
下面是handler处理器的具体使用方法,其中不含代理ip的部分,代理ip这部分将在下一篇笔记中介绍。
import urllib.request
url="https://www.baidu.com/s?word=ip"
headers={
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.66 Safari/537.36 Edg/103.0.1264.44'
}
request=urllib.request.Request(url=url,headers=headers)
# 1.获取handler对象
handler=urllib.request.HTTPHandler()
# 2.=获取opener对象
opener=urllib.request.build_opener(handler)
# 3.调用open方法
response=opener.open(request)
content=response.read().decode("utf-8")
print(content)
代码的步骤很清晰,我们可以简化整个过程为三个步骤:首先通过urllib库新建一个handler对象,而后通过urllib库的build_opener()方法新建一个opener对象,其中build_opener()要传入handler对象,最后通过opener的open()方法,获取响应,传参是我们的request定制请求对象。
=========================================================================
代理IP地址一般是说代理服务器的IP地址,就是说你的电脑先连接到代理IP,然后通过代理服务器上网,网页的内容 通过代理服务器,传回你自己的电脑。代理IP就是一个安全保障,这样一来暴露在公网的就是代理IP而不是你的IP了!
我们通过代理ip能够防止自己的ip在爬取内容的时候暴露,这样一方面提高了保密性,最重要的点是通过代理ip,我们可以应对ip被封这一反爬机制了!
国内高匿免费HTTP代理IP - 快代理
import urllib.request
url="https://www.baidu.com/s?word=ip"
headers={
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.49'
}
#编写IP地址
proxies={
'http':'202.55.5.209:8090'
}
request=urllib.request.Request(url=url,headers=headers)
# handler build_opener open
# response=urllib.request.urlopen(request)
# 通过handler处理器传入ip地址
handler=urllib.request.ProxyHandler(proxies=proxies)
opener=urllib.request.build_opener(handler)
response=opener.open(request)
content=response.read().decode("utf-8")
with open('daili.html','w',encoding='utf-8')as fp:
fp.write(content)
=========================================================================
所谓代理池,就是很多的ip在一起的一个结构,在这个结构里,我们能够在每一次请求中使用不同的ip地址,从而减少同一个ip的使用频率,以降低ip被封掉的风险,对抗反爬机制!
如何实现代理池
import urllib.request
url="https://www.baidu.com/s?word=ip"
headers={
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Safari/537.36 Edg/103.0.1264.49'
}
import random
# 建立多个代理
proxies=[
{'http':'202.55.5.209:8090'},
{'http':'47.56.69.11:8000'},
{'http':'112.14.47.6:52024'}
]
# 通过随机选择来使用某个代理
proxies=random.choice(proxies)
request=urllib.request.Request(url=url,headers=headers)
handler=urllib.request.ProxyHandler(proxies)
opener=urllib.request.build_opener(handler)
open=opener.open(request)
content=open.read().decode("utf-8")
print(content)
# with open('daili.html','w',encoding='utf-8')as fp:
# fp.write(content)
=========================================================================
pip install lxml==4.6.2 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
如果下载失败,可以看看你的有没有关闭,没有关闭可能会导致下载失败
下载xpath的zip文件
链接:https://pan.baidu.com/s/1-e-NAcjTi7yuVp7TU0wStA
提取码:rh1z
无需解压,直接拖入到控制程序页面中,xpth插件就会自动安装到浏览器上了
xpath是一种筛选html或者xml页面元素的【语法】
html文件名字定为xxx.html
Title
- 北京
- 上海
- 深圳
- 武汉
#导入lxml库
from lxml import etree
#xpath解析
# 1.本地文件 extree.parse
# 2.服务器响应的数据 extree.html
# 解析本地文件
tree=etree.parse('070_尚硅谷_urllib_xpath的基本使用.html')
# 查找ul下面的li
# li_list=tree.xpath('//ul/li')
# 查找带有id的li
# li_list =tree.xpath('//ul/li[@id]/text()')
# 查找带有id=l1的li
# li_list =tree.xpath('//ul/li[@id="l1"]/text()')
# 查找带有id=l1的li且带有class属性值的li
li_list =tree.xpath('//ul/li[@id]/@class')
# 判断列表的长度+
print(li_list)
print(len(li_list))
import urllib.request
url="https://www.baidu.com/"
headers={
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.66 Safari/537.36 Edg/103.0.1264.44'
}
request=urllib.request.Request(url=url,headers=headers)
response=urllib.request.urlopen(request)
content=response.read().decode("utf-8")
# print(content)
from lxml import etree
# 解析服务器响应的文件
tree=etree.HTML(content)
# 获取想要的文件
result=tree.xpath('//input[@id="su"]/@value')
print(result)
=========================================================================
jsonpath是什么:
jsonpath是一种简单的方法来提取给定JSON文档的部分内容。
为什么要学习jsonpath:
因为有时候我们拿到的数据是以json为格式的数据,此时我们不再能够使用之前学习的xpath对内容进行解析,因此我们需要一种方法来解析json格式的数据,它就是jsonpath!
jsonpath的安装
pip install jsonpath -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
jsonpath的基本使用:
强调:就jsonpath只能处理本地的json文件,不能直接处理服务器的响应
首先编写一个json文件(文件名命名为jsonpath.json)
{"store":{
"book": [
{"category":"修道",
"author": "六道",
"title": "坏蛋是怎样练成的",
"price": 8.95
},
{"category":"修改",
"author": "天蚕土豆",
"title": "斗破苍穹",
"price": 12.99
},
{"category":"修真",
"author": "唐家三少",
"title": "斗罗大陆",
"jsbn": "0-0",
"price": 8.99
}
],
"bicycle": {
"author": "天蚕土豆",
"color": "黑色",
"price": 12
}
}}
然后我们在进行jsonpath的基本使用
jsonpath与xpath的语法表格
XPath | JSONPath | 描述 |
/ | $ | 根元素 |
. | @ | 当前元素 |
/ | . or [] | 当前元素的子元素 |
.. | n/a | 当前元素的父元素 |
// | .. | 当前元素的子孙元素 |
* | * | 通配符 |
@ | n/a | 属性的访问字符 |
jsonpath的代码
# 导入库
import jsonpath
import json
# 打开json文件,编码格式为utf-8
#这里要注意,我们调用函数之前,要先导入json库和jsonpath库;此外,我们通过json.load()函数导入我#们的json文件,这个函数的传参不是文件名,而是一个文件对象。
#这里多解释一下,也就是说,我们传参是:json.load(文件对象),而不是json.load('store.json'),后#者是一个字符串,会报错,至于这个文件对象,我们可以直接用open()函数创建,也可以在外面先用open函#数新建一个文件对象,之后将对象传入,二者均可。
obj=json.load(open('jsonpath.path','r',encoding='utf-8'))
#第一行的/是根元素的意思,也就是说在jsonpath中,每一句jsonpath语言都要以一个$符号开头,后面的 #部分按照上面与xpath对照进行理解即可。(n/a表示该项不存在)
# 书店所有书的作者
# authou_list=jsonpath.jsonpath(obj,'$.store.book[0].author')
# print(authou_list)
# 所有的作者
# authou_list=jsonpath.jsonpath(obj,'$..author')
# print(authou_list)
# store下面的所有元素
# authou_list=jsonpath.jsonpath(obj,'$.store.*')
# print(authou_list)
# store下面的所有的钱
# authou_list=jsonpath.jsonpath(obj,'$.store..price')
# print(authou_list)
#第三本书
# book=jsonpath.jsonpath(obj,'$..book[2]')
# print(book)
# 最后一本书
# book=jsonpath.jsonpath(obj,'$..book[(@.length-1)]')
# print(book)
# 前两本书
# book=jsonpath.jsonpath(obj,'$..book[0,1]')
# book=jsonpath.jsonpath(obj,'$..book[:2]')
# print(book)
# 过滤出所有带有jsbn的书
# book=jsonpath.jsonpath(obj,'$..book[?(@.jsbn)]')
# print(book)
# 过滤出价格低于10的书
# book=jsonpath.jsonpath(obj,'$..book[?(@.price>10)]')
# print(book)
# 所有的元素
allElements=jsonpath.jsonpath(obj,'$..')
print(allElements)
=========================================================================
BS4全称是Beatiful Soup,它提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能,解析的对象是本地html文件和服务器的响应html文件
pip install bs4 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
创建本地html文件取名为bs4.html
Title
- 张桑
- 李桑
- 王桑
敬礼敬礼
1
敬礼敬礼
哈哈哈
hhh
from bs4 import BeautifulSoup
# 通过解析本地文件将bs4的基础语法进行讲解
# 默认打开的文件的编码格式是gbk 所以打开文件是要指定默认编码
soup = BeautifulSoup(open('bs4.html',encoding='utf-8'),'lxml')
# print(soup)
# 1.find
# print(soup.findAll)
# 返回第一个符合条件的数据
# print(soup.find('a'))
# 根据title的值找到对应的标签对象
# print(soup.find('a',title='a2'))
# 根据class的值找到对应的标签对象
# print(soup.find('a',class_="a1"))
# 2.find_all
# 返回一个列表,并且返回所有的a标签
# print(soup.find_all('a'))
# rg想获取的是多个标签的数据,那么需要在find_all的参数中添加的是列表的数据
# print(soup.find_all(['a','span']))
# limit的作用是查找前几个数据
# print(soup.find_all('li',limit=2))
# 3.select(推荐x`)
#select方法返回的是一个列表,并且返回多个数据
# print(soup.select('a'))
# 可以通过.代表class 我们把这种叫做类选择器
# print(soup.select('.a1'))
# 属性选择器
# 查找li标签中带有id的标签
# print(soup.select('li[id]'))
# 查到li标签中id为2的标签
# print(soup.select('li[id="2"]'))
# 层级选择器
# 后代选择器
# 找到div下面的li
# print(soup.select('div li'))
# 子代选择器
# 某标签的第一子标签
#注意:在好多的计算机语言中 如果不加空格会出现不输出内容的错误 但是在bs4中不会出现这种错误
# print(soup.select('div>ul>li'))
#节点信息
# 获取节点内容
# obj=soup.select('#d1')[0]
# 如果标签对象中 只有内容 那么string和get_text()都可以使用
# 如果标签对象中 除了内容还有标签 那么string就获取不到数据 而get_text()是可以获取数据
# 我们一般情况下 推荐使用get_text()
# print(obj.string)
# print(obj.get_text())
# 节点的属性
# ogj=soup.select('#p1')[0]
# neme是标签的名字
# print(ogj.name)
# 将属性值左右作为一个字典返回
# print(ogj.attrs)
# 获取节点的属性
ogj=soup.select('#p1')[0]
# print(ogj.attrs.get('class'))
# print(ogj.get('class'))
print(ogj['class'])
from bs4 import BeautifulSoup
soup = BeautifulSoup(content,'lxml')
服务器的响应应当用上述的格式进行书写:使用Beautifulsoup()函数,传入两个参数,第一个参数是服务器的响应的内容,第二个参数是'lxml’这个固定的参数。
=========================================================================
selenium是一个自动化测试工具,支持Firefox,Chrome等众多浏览器 在爬虫中的应用主要是用来解决JS渲染的问题。
爬虫,selenium能够模拟真人打开浏览器,因此可以更好的获取我们需要的数据。(有时候,使用urllib库模拟浏览器的时候,会被服务器识别,返回的数据有所缺失,因此我们的确需要selenium做爬虫)
自动化小工具,例如可以帮我们操作一些浏览器的交互等等(释放双手)。
pip install selenium==3.4 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
谷歌浏览器工具下载
首先我们需要了解我们的谷歌浏览器的版本号
不用一一对应,只需要前几位数差不多就可以,下载完成后放入python同级目录下
打开京东商城
# 1.导入selenium
from selenium import webdriver
# 创建浏览器操作对象
path='chromedriver.exe'
browser = webdriver.Chrome(path)
# 3.访问网站
# url='https://www.baidu.com'
# browser.get(url)
url='https://www.jd.com/'
browser.get(url)
#获取网页源码
content=browser.page_source
print(content)
导入selenium库,初始化了浏览器操作对象。导入时格式是 from selenium import webdriver,导入后,我们可以创建一个字符串变量path,path的值是我们之前安装浏览器工具的路径,如果安装在与此python文件同级目录下,则直接输入其名称即可,否则要使用绝对路径!
最后用webdriver.Chrome()函数,传入路径,创建一个浏览器操作对象browser(名字可以自定义),
定义需要打开的网页的地址,之后使用get()函数,模拟真人打开浏览器并传入url,与此同时,我们的browser对象也与这个url建立了绑定,后续获取源码或者节点的信息都需要通过这个browser对象。最后,通过page_source函数,获取当前url的网页的源码。
from selenium import webdriver
from selenium.webdriver.common.by import By
path='chromedriver.exe'
browser=webdriver.Chrome(path)
url='https://www.baidu.com'
browser.get(url)
content = browser.page_source
# print(content)
#元素控制
# (1) 根据id属性的属性值找到对象_重要:
button=browser.find_element(By.ID, 'su')
print(button)
# (2) 根据name属性的属性值找到对象:
button = browser.find_element(By.NAME,'wd')
print(button)
# (3) 根据xpath的语句找到对象_重要:
button = browser.find_element(By.XPATH,'//input[@id = "su"]')
print(button)
# (4) 根据标签的名称找到对象
button = browser.find_element(By.TAG_NAME,'input')
print(button)
# (5) 根据CSS选择器找到对象,相当于bs4的语法_重要:
button = browser.find_element(By.CSS_SELECTOR,'#su')
# (6) 根据链接元素查找对象:
button = browser.find_element(By.LINK_TEXT,'新闻')
所谓的定位元素,就是指我们通过一些方法把页面上的元素与实际的代码中的对象(变量)进行绑定,以便于后续通过操作这些对象来获取元素信息、实际控制或操作页面上的元素(如果学过前端js、安卓的朋友可能比较理解这样的模式)。这些上面展示了六种定位元素的办法,其中比较重要的是前三种和第五种,即id、name、xpath语句、CSS选择器这四种方式,其他两种仅作为了解即可。
from selenium import webdriver
from selenium.webdriver.common.by import By
path='chromedriver.exe'
browser=webdriver.Chrome(path)
url='https://www.baidu.com'
browser.get(url)
#元素信息以及交互
# 根据id来找到对象
input=browser.find_element(By.ID, 'su')
# (1) get_attribute()函数获取标签的指定属性的属性值
# 传参是属性的名称,例如class、id等,返回这些属性的属性值
print(input.get_attribute('class'))
# (2) tag_name函数获取元素对应的标签的名称,例如元素是input标签,返回值就是input
print(input.tag_name)
# (3) text函数获取标签的文本,文本指的是标签尖括号的内容:
# 例如: xxx 于是获取的结果是xxx
print(input.text)
定位到id值是su的input表单元素之后,我们把这个元素与变量input进行绑定,而后通过操作input,我们能够获取关于这个表单元素的信息,其中重要的信息有两个:一个是元素的属性值,则可以通过get_attribute()函数获取,这个函数的传参是属性的名称,比如class、id等等,返回的是该属性的属性值;另一个是标签内的文本,这可以通过text属性获取。
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
path='chromedriver.exe'
browser=webdriver.Chrome(path)
url='https://www.baidu.com'
browser.get(url)
time.sleep(2)
# 获取文本对象
input=browser.find_element(By.ID,'kw')
# 在文本框输入周杰伦
input.send_keys('周杰伦')
time.sleep(2)
# 获取按钮对象
button=browser.find_element(By.ID,'su')
# 点击按钮
button.click()
time.sleep(2)
# 滑到底部
js_bottom='document.documentElement.scrollTop=100000'
browser.execute_script(js_bottom)
time.sleep(2)
# 获取下一页
next=browser.find_element(By.XPATH,'//a[@class="n"]')
next.click()
# 回到上一页
browser.back()
time.sleep(2)
# 回去
browser.forward()
time.sleep(2)
# 退出
browser.quit()
=========================================================================
之前学的selenium库,是真实打开了浏览器,但是优缺点:速度很慢,有时候我们需要更高速的获得数据或其他事情,因此我们需要了解两种无界面浏览器的操作:
下载连接 提取码:ysbd
下载完成后放入同级的文件下
最后,导入phantomjs并创建浏览器操作对象
from selenium import webdriver
from selenium.webdriver.common.by import By
path='phantomjs.exe'
browser=webdriver.Phantomjs(path)
后续操做和selenium的操作一毛一样
首先创建浏览器操作对象(进行封装)
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
def handless_browser():
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
# path这里要改成自己的谷歌浏览器的路径:
path = r'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
chrome_options.binary_location = path
browser = webdriver.Chrome(chrome_options=chrome_options)
return browser
browser = handless_browser()
url='https://www.baidu.com'
browser.get(url)
=========================================================================
它是一个Python第三方库,处理URL资源特别方便,可以完全取代之前学习的urllib库,并且更加精简代码量(相较于urllib库)。
pip install bs4 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
首先我们先想想用urllib的向服务器发起请求的步骤,首先是导入库,然后创建url对象,接着通过urllib.request.urlopen()向服务器发起请求,同理Requests的步骤也是这样子
import requests
url='http://www.baidu.com'
response=requests.get(url)
导入requests库,创建url,使用response接受服务器的响应
Requests的一个类型和六个方法:
import requests
url='http://www.baidu.com'
response=requests.get(url)
# print(type(response))
# 一个类型和六个属性
# Response类型
#设置响应的编码格式
# response.encoding='utf-8'
# 以字符串的形式返回网页源代码
# print(response.text)
# 返回一个url地址
print(response.url)
# 返回二进制的数据
print(response.content)
# 返回相应的状态码
print(response.status_code)
# 返回响应头
print(response.headers)
requests的get请求与urllib的请求方式有些许不同,那就是没有请求对象的定制
import requests
url='https://www.baidu.com/s?'
headers={
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.66 Safari/537.36 Edg/103.0.1264.44'
}
data={
'wd':'北京'
}
# url:请求路径
# params:参数
# kwargs:字典
response=requests.get(url=url,params=data,headers=headers)
print(response.text)
总结:
1.参数使用params进行传递
2.参数无需urlencode编码
3.不需要请求对象的定制
4.请求资源路径的?可以加也可以不加
requests的post请求与urllib的请求方式也有不同,不仅没有请求对象的定制而且也没有参数的编码和转码的操作
import requests
url='https://fanyi.baidu.com/sug'
headers={
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.66 Safari/537.36 Edg/103.0.1264.44'
}
data={
'wd':'北京'
}
# url:请求路径的地址
# data:请求参数
# kwargs:字典
response=requests.post(url=url,data=data,headers=headers)
content=response.text
import json
obj=json.loads(content,encoding="utf-8")
print(obj)
总结:
1.post请求不需要编解码
2.post请求的参数是data
3.不需要请求对象的定制
回忆urllib库代理ip,我们需要创建handler处理器,还要定义opener对象,但requests库中,我们只需要把代理ip作为一个普通的参数,传入requests.get()/requests.post()函数即可(简直太方便了!)
import requests
url='https://www.baidu.com/s?word=IP'
headers={
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.66 Safari/537.36 Edg/103.0.1264.44'
}
data={
'wd':'北京'
}
proxies={
'http':'202.55.5.209:8090'
}
response=requests.get(url=url,headers=headers,proxies=proxies)
content=response.text
print(content)
总结一下resquests库与urllib库的区别:
1.resquests库是一个特征六个属性,urllib是一个特征六个方法
2.requests库的get和post请求不需要请求对象的定制,而urllib需要
3.requests库的代理ip是直接传入的,代理ip作为一个参数传入,而urllib不经需要使用handler还要创建opener对象
=========================================================================
Scrapy是适用于Python的一个快速、高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试
spiders
spiders可以理解为代表了我们人的操作,我们在操作scrapy的时候,实际上就是以spiders的身份在操作,初始的url是我们定义的。
引擎
引擎是scrapy框架的中枢,从图中可以看出,引擎与所有的其他组件交互,并且交互大多带有指令性的操作,可以理解成一个指挥官。
调度器
调度器,顾名思义,它是用来做调度的,简单的说就是它会把所有请求的url放入一个队列中,每一次会从队列中取出一个url,这个过程叫做调度。
下载器
下载器,是用来下载数据的,它下载的是原始数据,可以理解为网页源码,这些源数据通过引擎再次交给我们用户spiders做进一步解析处理。(下载器沟通因特网,数据来源也是因特网)
管道
管道的工作是下载图片、文件,它的工作与调度器下载源数据不同,它下载的是经过解析后的具体的图片、文件等数据。
用一句话来描述scrapy框架的工作过程
首先,spiders想要在某个url对应的网页下下载图片,于是spiders向引擎递交url,之后引擎把url放入调度器排队;当这个url排到队首的时候,调度器取出这个url请求,交给引擎;这时候引擎把请求给下载器,下载器访问因特网,拿到源数据,交给引擎;引擎再把源数据给spiders。经过这一波操作,源数据被spiders拿到。之后spiders解析数据,并把里面的url和需要下载的数据分离,并一起交给引擎,引擎把url和需下载的数据分别交给调度器和管道,调度器继续重复上述操作,管道下载文件。
pip install scrapy -i https://pypi.douban.com/simple
1.win+r输入cmd,创建爬虫的项目
2.打开spider文件,并创建要爬取的网页的文件
3.创建好的的文件的项目结构
Spiders文件夹:这文件夹我们不陌生,因为每一次新建scrapy爬虫项目后,我们都需要终端进入Spiders文件夹,生产爬虫文件。在Spiders文件夹下,又有两个文件,一个是_init_.py文件,一个是baidu.py。_init_.py文件是我们创建项目时默认生成的一个py文件,我们用不到这个py文件,因此我们可以忽略它,另一个baidu.py文件是我们爬虫的核心文件,后续的大部分代码都会写入这个文件,因此它是至关重要的py文件。
_init_.py文件:它和上面提到的Spiders文件夹下的_init_.py一样,都是不被使用的py文件,无需理会。
items.py文件:这文件定义了数据结构,这里的数据结构与算法中的数据结构不同,它指的是爬虫目标数据的数据组成结构,例如我们需要获取目标网页的图片和图片的名称,那么此时我们的数据组成结构就定义为 图片、图片名称。后续会专门安排对scrapy框架定义数据结构的学习。
middleware.py文件:这py文件包含了scrapy项目的一些中间构件,例如代理、请求方式、执行等等,它对于项目来说是重要的,但对于我们爬虫基础学习来说,可以暂时不考虑更改它的内容。
pipelines.py文件:这是我们之前在工作原理中提到的scrapy框架中的管道文件,管道的作用是执行一些文件的下载,例如图片等,后续会安排对scrapy框架管道的学习,那时会专门研究这个py文件。
settings.py文件:这文件是整个scrapy项目的配置文件,里面是很多参数的设置,我们会偶尔设计到修改该文件中的部分参数,例如下一部分提到的ROBOTS协议限制,就需要进入该文件解除该限制,否则将无法实现爬取。
4.然后我们输入scrapy crawl baidu运行spiders下的baidu.py
=========================================================================
什么是robots协议:
robots协议也叫robots.txt,是一种存放于网站根目录下的ASCII编码的文本文件,它通常告诉网络搜索引擎的漫游器(又称网络蜘蛛),此网站中的哪些内容是不应被搜索引擎的漫游器获取的,哪些是可以被漫游器获取的。也被称为君子协议
打开settings.py文件,把 ROBOTSTXT_OBEY = True 这句代码''解除''注释:
在使用scrapy框架的时候,我们在拿不到数据时,可以考虑是否是robots协议起到了作用,如果是这样,那就把 ROBOTSTXT_OBEY = True 这句代码注释即可!
=========================================================================
打开spider项目下的baidu.py
name='baidu'就相当于我们启动爬虫的名命对象,也就是中的baidu
response的值,而这个response的值就是服务器给我们的响应。针对这个response响应,有下面的基础操作:
def parse(self, response):
# (1) response.text属性:获取的是字符串形式的数据
content_str = response.text
print(content_str)
# (2) response.body属性:获取的是二进制形式的数据
content_b = response.body
print("====================")
print(content_b)
# (3) response.xpath()函数可以直接使用xpath解析
# (4) response.extract() 提取selector对象的属性值
# (5) response.extract_first() 提取selector列表的第一个数据
pass
- response.xpath(xpath语句传入):这种方式是对response进行xpath解析,我们在括号内传入xpath语法对应的语句即可,要注意的是,普通的xpath解析,返回的是一个列表,但是在scrapy框架中的xpath解析,返回的是selector对象列表,针对selector对象列表,我们需要进一步的处理,才能真正拿到数据。
- response.extract():这种处理,承接了上面的操作,当我们拿到了selector对象列表,通过再执行.extract()函数,即可把selector对象列表转成普通的列表,进而获取数据。
- response.extract_first():这是第二种方法的加强版本,可以直接拿到转成的普通列表的第一个元素,在一些情况下更方便。