架构
python 3.7.6 +requests 2.23.0 + beautifulsoup4 4.8.2 + lxml 4.5.0
开发工具 pycharm2019
requests 介绍与安装
requests 是一个优雅而简单的 Python HTTP请求库requests 的作用是 发送请求获取响应数据
requests 安装:在终端(命令行工具)运行这个简单命令即可
pip install requests
注意:
如果你要安装Python虚拟环境中,先进入虚拟机环境再执行上述命令
如果系统中既安装了Python2 又安装了 Python3,需要安装Python3环境中:pip3 install requests
官方文档
http://cn.python-requests.org/zh_cN/latest/
快速上手
http://cn.python-requests.org/zh c/latest/user/quickstart.html
requests使用步骤
# 1.导入模块import requests
# 2.发送请求,获取响应
headers ={
"User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36
}
data ={
'wd':'北京'
}
#url请求资源路径
#params 参数
#kwargs 字典
response =requests.get(url=url,params=data,headers=headers)
response = requests.get('http://www.baidu.com')
参数使用params传递
参数无需urlencode编码
不需要请求对象的定制
请求资源路径中的?可以加也可以不加
# print(response)
# 3。获取响应数据
# print(response.encoding) # IS0-8859-1 二进制转换字符使用的编码
response.encoding='utf8'
print(response.text) # 响应体 str类型
print(response.content.decode()) # respones.content:响应体 bytes类型
response的属性以及类型
类型 type(response) models.Response
r.text 获取网站源码
r.encoding 访问或定制编码方式
r.url 获取请求的ur1
r.content 响应的字节类型 二进制数据
r.status_code 响应的状态码
r.headers 响应的头信息
# urllib
(1)一个类型以及六个方法
(2)get请求
(3)post请求百度翻译
(4)ajax的get请求
(5)ajax的post请求
(6)cookie登陆 微博
(7)代理
# requests
(1)一个类型以及六个属性
(2)get请求
(3)post请求
(4)代理
(5)cookie 验证码
requests.post()
百度翻译:
eg:
import requests
post_url='http://fanyi.baidu.com/sug'
headers={
'user-Agent': Mozilla/5.0 (windows NT 10.0; win64; x64)Applewebkit/537.36(KHTML,like Gecko)chrome/68.0.3440.106 safari/537.36'
}
data ={
'kw': 'eye
}
r=requests.post(url=post url,headers=headers,data=data)
post请求 是不需要编解码
post请求的参数是
data不需要请求对象的定制
get和post区别?
get请求的参数名字是paramspost请求的参数的名字是data
请求资源路径后面可以不加?
不需要手动编解码
不需要做请求对象的定制
session =requests.session()
# 验证码的url的内容
response_code =session.get(code url)
# 注意此时要使用二进制数据因为我们要使用的是图片的 下载
content code = response code.content
# wb的模式就是将二进制数据写入到文件
with open('code.jpg',"wb')as fp:
fp.write(content code)
# 获取了验证码的图片之后 下载到本地 然后观蔡验证码 观察之后 然后在控制台输入这个验证码 就可以将这个值给
# code的参数 就可以登陆
code_name = input('请输入你的验证码')
**建议使用ddddor库,免费**
# 点击登陆
url_post = 'https://so.gushiwen.cn/user/login.aspx?from=http%3a%2f%2fso.gushiwen.cn%2fuser%21
data_post={
'VIEWSTATE':viewstate,
VIEWSTATEGENERATOR':viewstategenerator,
from':"http://so.gushiwen.cn/user/collect.aspx'
email:'595165358@qq.com',
pwd" :action'
code': code_name
'denglu':'登录'
}
response_post= session.post(url = url, headers = headers, data = data_post)
content_post =response_post.text
with open('gushiwen.html','w',encoding= " utf-8')as fp:
fp.write(content post)
BeautifulSoup 介绍与安装
BeautifulSoup4 是一个可以从HTML或XML文件中提取数据的Python库
Beautifulsoup4 安装
pip install bs4
安装 lxml
pip install lxml
BeautifulSoup对象介绍与创建
Beautifulsoup对象
Beautifulsoup对象:代表要解析整个文档树它支持 遍历文档树 和 搜索文档树 中描述的大部分的方法
创建 Beautifulsoup 对象
# 1.导入模块
from bs4 import BeautifulSoup
#2.创建BeautifulSoup对象
soup = BeautifulSoup("<html>data</html>")
print(soup)
警告问题
/usr/local/lib/python3.7/site-packages/bs4/ initpy:181:UserWarning: No parser was explicitlyspecified, so I'm using the best available HTMLparser for this system("lxml"). This usually isn't aproblem, but if you run this code on another system,or in a different virtual environment, it may use adifferent parser and behave differently.
解决警告问题
# 指定解析器
soup = BeautifulSoup("<html>data</html>",'lxml')
find方法的作用:搜索文档树
find(self,name=None,attrs={l,recursive=True,text=None, **kwargs)
参数
name:标签名
attrs:属性字典
recursive:是否递归循环查找
text:根据文本内容查找
返回
查找到的第一个元素对象
#4.查找title标签
title = soup.find('title')
print(title)#
5。查找a 标签
a= soup.find('a')
print(a)
# 查找所有的a标签
a_s= soup.find_all('a')
print(a_s)
二。根据属性进行查找查找id为link1的标签
方式1:通过命名参数进行指定的
a= soup.find(id='link1')
print(a)
#方式2:使用attrs来指定属性字典,进行查找
a= soup.find(attrs={'id':'link1'})
print(a)
# 三,根据文本内容进行查找
text = soup.find(text='Elsie')
print(text)
# Tag对象
print(type(a)) #<class 'bs4.element.Tag'>
print('标签名',a.name)
print('标签所有属性 (键和值)',a.attrs)
print('标签文本内容",a.text)
Tag 对象介绍
Tag对象对应于原始文档中的XML或HTML标签
Tag有很多方法和属性,可用 遍历文档树 和 搜索文档树
以及获取标签内容
Tag 对象常见属性
name:获取标签名称
attrs:获取标签所有属性的键和值
text:获取标签的文本字符串
#4。使用正则表达式,提取json字符串
json_str= re.findall(r'\[.+\]',text)print(json_str)[0]
正则表达式
1.正则表达式是是一种字符串匹配的模式(pattern),在爬虫中主要用于从某个字符串中提取符合某种条件的子串.
2.常见语法:·0 \d \w*+?
3.re.findall()查找字符串所有与正则匹配的子串,返回一个列表,如果没有找到返回空列表
4.re.findall()如果正则中没有分组,返回与整个正则匹配的子串,如果正则中有分组,只返回与分组匹配的子串,分组两边的正则是用于定位的.
5.正则中使用r原串,就是为了消除转移符(\)的影响,也就是匹配的字符串中,有多少个转移符,r原串的正则中写几个\就可以了
Json模块
json模块是Python自带的模块,用于json与python数据之间的相互转换.
JSON | Python |
---|---|
object | dict |
array | list |
string | str |
number(int) | int, long |
number(real) | float |
true | True |
false | False |
null | None |
json字符串 => json.loads(s) => Python类型数据
json格式的文件对象=>json.load(fp)=> Python类型数据
python类型数据 =>json.dumps(obj) => json字符串
Python类型数据以json格式写入文件 => json.dump(obj, fp) => json格式文件
#3。python类型转换为json字符串
json_str=json.dumps(python_dict)
print(json_str)
# 输出:{"provinceName":"1u7f8elu56fd", "currentConfirmedcount":1115312,"confirmedcount”: 1465066}
#ensure_ascii:指定False,返回结果中可以包含非ASCII字符
json_str:json.dumps(python_dict,ensure_ascii=False)
print(json_str)
#输出:{"provinceName":"美国”,"currentConfirmedCount":1115312,"confirmedCount": 1465066)
爬虫介绍
如果我们把互联网比作一张大的蜘蛛网,那一台计算机上的数据便是蜘蛛网上的一个猎物,而爬虫程序就是一只小蜘蛛,沿着蜘蛛网抓取自己想要的数据
解释
1:通过一个程序,根据ur1(http://www.taobao.co币)进行爬取网页,获取有用信息解释
2:使用程序模拟浏览器,去向服务器发送请求,获取响应信息
爬虫核心?
1.爬取网页:爬取整个网页 包含了网页中所有得内容
2.解析数据:将网页中你得到的数据 进行解析
3.难点:爬虫和反爬虫之间的博弈
爬虫的用途?
数据分析/人工数据集
社交软件冷启动
舆情监控
竞争对手监控
爬虫分类
通用爬虫
实例
百度、360、google、sougou等搜索引擎---伯乐在线
功能
访问网页->抓取数据->数据存储->数据处理->提供检索服务robots协议
一个约定俗成的协议,添加robots.txt文件,来说明本网站哪些内容不可以被抓取,起不到限制作用
自己写的爬虫无需遵守
网站排名(SEO)
1.根据pagerank算法值进行排名(参考个网站流量、点击率等指标)
2.百度竞价排名
缺点
1.抓取的数据大多是无用的
2.不能根据用户的需求来精准获取数据
聚焦爬虫
功能
根据需求,实现爬虫程序,抓取需要的数据设计思路
1.确定要爬取的ur1
如何获取ur1
2.模拟浏览器通过http协议访问ur1,获取服务器返回的htm1代码
如何访问
3.解析htm1字符串(根据一定规则提取需要的数据)
如何解析
反爬手段
User-Agent
User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引、浏览器语言、浏览器插件等。
代理IP
西次代理
快代理
什么是高匿名、匿名和透明代理?它们有什么区别?
1.使用透明代理,对方服务器可以知道你使用了代理,并且也知道你的真实IP。
2.使用匿名代理,对方服务器可以知道你使用了代理,但不知道你的真实IP。
3.使用高匿名代理,对方服务器不知道你使用了代理,更不知道你的真实IP。
验证码访问
打码平台
云打码平台
超级喁
动态加载网页
网站返回的是js数据 并不是网页的真实数据
selenium驱动真实的浏览器发送请求
数据加密
分析js代码
urllib库使用
urllib.request.urlopen()模拟浏览器向服务器发送请求
response服务器返回的数据
response的数据类型是HttpResponse
字节-->字符串 解码decode
字符串-->字节 编码encode
read() 字节形式读取二进制 扩展:read(5)返回前几个字节
readline() 读取一行
readlines() 一行一行读取 直至结束
getcode() 获取状态码
getur1()获取ur1
getheaders()获取headers
urllib.request.urlretrieve()
请求网页
请求图片
请求视频
使用urllib来获取百度首页的源码
import urllib.request
#(1)定义一个url 就是你要访问的地址
url = 'http://www.baidu.com
#(2)模拟浏览器向服务器发送请求response响应
response =urllib.request.urlopen(url)
#3)获取响应中的页面的源码content 内容的意思
# read方法返回的是字节形式的二进制数据
# 我们要将二进制的数据转换为字符串
# 二进制--》字符串 解码 decode('编码的格式')
content =response.read().decode('utf-8')
#(4)打印数据
print(content)
#一个类型和六个方法
# response是HTTPResponse的类型
# print(type(response))
# 按照一个字节一个字节的去读
# content =response.read()
# print(content)
# 返回多少个字节
# content =response.read(5)
# print(content)
#content =response.readline()
#print(content)
#content =response.readlines()
#print(content)
# 返回状态码 如果是200了 那么就证明我们的逻辑没有错
# print(response.getcode())
# 返回的是url地址
# print(response.geturl())
# 获取是一个状态信息
print(response.getheaders())
# 一个类型 HTTPResponse
#六个方法 read readline readlines getcode geturl getheaders
# 下载网页
# url_page = 'http://ww.baidu.com'
# url代表的是下载的路径
# filename文件的名字
# 在python中 可以变量的名字也可以直接写值
# urllib.request.urlretrieve(url_page,'baidu.html')
#下载图片
url_img = 'https://img1.baidu.com/it/u=3004965690,40892345938.jpg'
urllib.request.urlretrieve(url= url_img,filename='lisa.jpg')
response = urllib.request.urlopen(url)
content =response.read().decode('utf8')
print(content)
headers ={
"User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64;x64)AppleWebKit/537.36 (KHTML
}
# 因为urlopen方法中不能存储字典所以headers不能传递进去
# 请求对象的定制
#注意 因为参数顺序的问题 不能直接写url 和headers 中间还有data 所以我们需要关键字传参
request =urllib.request.Request(url=url,headers=headers)
response = urllib.request.urlopen(request)
content =response.read().decode("utf8')
print(content)
# 请求参数urlencode urlencode应用场景:多个参数的时候 ,在有中文的时候,或者get的?后面的参数
import urllib.parse
data ={
'wd':'周杰伦",
'sex':'男'
}
#将周杰伦三个字变成unicode编码的格式
#我们需要体赖于
#urllib.parsename = urllib.parse.quote('周杰伦')
a= urllib.parse.urlencode(data)
print(a)
3.post请求方式
eg:百度翻译
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 (KHTMLlike Gecko)Chrome/74.0.3729.169 Safari/537.36'
}
keyword = input('请输入您要查询的单词')
data ={
'kw' : keyword
}
# post请求的参数 必须要进行编码
data =urllib.parse.urlencode(data).encode('utf-8')
总结:post和get区别?
get请求方式的参数必须编码,参数是拼接到ur1后面,编码之后不需要调用encode方法
# post的请求的参数 是不会拼接在url的后面的 而是需要放在请求对象定制的参数中
request = urllib.request.Request(url=url,headers=headers,data=data)
response =urllib.request.urlopen(request)
print(response.read().decode('utf-8'))
# post请求方式的参数 必须编码,编码之后 必须调用encode方渚
data =urllib.parse.urlencode(data).encode('utf-8')
# 参数是放在请求对象定制的方法中 request=urllib.request.Request(url=url,data=data,headers=headers)
#(3)数据下载到本地
# open方法默认情况下使用的是gbk的编码 如果我们要想保存汉字 那么需要在open方法中指定编码格式为utf-8
# encoding ='utf-8'
# fp = open('douban.json','w',encoding='utf-8')
# fp.write(content)
with open('douban1.json','w',encoding='utf-8')as fp:
fp.write(content)
11.URLError\HTTPError
简介:1.HTTPError类是URLError类的子类
2.导入的包urllib.error.HTTPError urllib.error.URLError
3.http错误:http错误是针对浏览器无法连接到服务器而增加出来的错误提示。引导并告诉浏览者该页是哪里出了问题。
4.通过ur11ib发送请求的时候,有可能会发送失败,这个时候如果想让你的代码更加的健壮,可以通过try-except进行捕获异常,异常有两类,URLError\HTTPError
try:
request =urllib.request.Request(url= url, headers = headers)
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
print(content)
except urllib.error.HTTPError:
print('系统正在升级。。。')
except urllib.error.URLError:
print('我都说了 系统正在升级。。。')
#cookie中携带着你的登陆信息如果有登陆之后的cookie 那么我们就可以携带着cookie进入到任何页面
cookie":'TWM=24c44910ba98d188fced94ba0da5960e;SUBP=0033WrSXqPxfM725Ws9j9gMF55529P9判断当前# #referer路径是不是由上一个路径进来的……一般情况下 是做图片防盗键
"referer':"https://weibo.cn/
Handler处理器
定制更高级的请求头(动态cookie和代理不能使用请求对象的定制)
eg:
import urllib.request
url ='http://www.baidu.com'
headers={
'User -Agent':'Mozilla/5.0(Windows NT 10.0;Win64;x64)AppleWebKit /537.36(KHTML,likeGecko)Chrome /74.0.3729.169safari / 537.36'
}
request =urllib.request.Request(url=url,headers=headers)
handler = urllib.request.HTTPHandler()
opener = urllib.request.build opener(handler)
response =opener.open(request)
print(response.read().decode('utf-8'))
with open('daili.html','w',encoding='utf-8')as fp
fp.write(content)
# 代理池、***快代理***
cookie库能干啥:通过handler登陆会自动的保存登录之后的cookie
cookie库配置
创建一个cookie]ar对象
使用cookiejar对象,创建一个handler对象
使用handler创建一个opener
通过opener登录
handler会自动的保存登录之后的cookie
代理服务器
代理的常用功能?
突破自身IP访问限制,访问国外站点。
访问一些单位或团体内部资源
扩展:某大学FTP(前提是该代理地址在该资源的允许访问范围之内),使用教育网内地址段免费代理服务器,就可以用于对教育网开放的各类FTP下载上传,以及各类资料查询共享等服务。
提高访问速度
扩展:通常代理服务器都设置一个较大的硬盘缓冲区,当有外界的信息通过时,同时也将其保存到缓冲区中,当其他用户再访问相同的信息时, 则直接由缓冲区中取出信息,传给用户,以提高访问速度。
隐藏真实IP
扩展:上网者也可以通过这种方法隐藏自己的IP,免受攻击。
代码配置代理
创建Reugest对象
创建ProxyHandler对象
用handler对象创建opener对象
使用opener.open函数发送请求
eg:
import urllib.request
url="http://www.baidu.com/s?wd=ip"
headers ={
'User - Agent':'Mozilla/5.0(windows NT 10.0;Win64;x64)AppleWebkit / 537.36(KHTML,likeGecko)chrome /74.0.3729.169safari /537.36'
}
request = urllib.request.Request(url=url,headers=headers)
proxies ={'http':'117.141.155.244:53281'}
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)
proxies_pool =[
{'http':'118.24.219.151:16817'}
{'http':'118.24.219.151:16817'}
]
import random
proxies =random.choice(proxies_pool)
解析
Xpath
xpath使用:
注意:提前安装xpath插件
(1)打开chrome浏览器
(2)点击右上角小圆点
(3)更多工具
(4)扩展程序
(5)拖拽xpath插件到扩展程序中
(6)如果crx文件失效,需要将后缀修改zip
(7)再次拖拽
(8)关闭浏览器重新打开
(9)ctrl+ shift + x
(10)出现小黑框
1.安装lxml库
pip install lxml -i https://pypi.douban.com/simple
2.导入lxml.etree
from lxml import etree
3.etree.parse() 解析本地文件
html tree = etree.parse('xx.html')
4.etree .HTML() 服务器响应文件
html tree =etree.HTML(response.read().decode('utf-8")
4.html tree.xpath(xpath路径)
xpath基本语法:
1.路径查询
//:查找所有子孙节点,不考虑层级关系
/:找直接子节点
2.谓词查询
//div[@id]
//div[@id="maincontent”]
3.属性查询
//@class
4.模糊查询
//div[contains(@id, "he”)]
//div[starts-with(@id, "he")]
5.内容查询
//div/h1/text()
6.逻辑运算
//div[@id="head" and @class="s_down"]
//title | //price
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul>
<li>北京</li>
<li>上海</li>
<li>深圳</l1>
<li>武汉</li>
</u1>
<ul>
<li>大连</li>
<li>锦州</li>
<li>沈阳</1i>
</ul>
</body>
</html>
from lxml import etree
# xpath解析
# (1)本地文件etree.parse
#(2)服务器响应的数据 response.read().decode('utf-8')*****etree.HTML()
# xpath解析本地文件
tree = etree.parse('070_尚硅谷_爬虫_解析_xpath的基本使用.html')
#tree.xpath('xpath路径')
# 查找ul下面的li
li_list = tree.xpath('//body/ul/li')
# 查找所有有id的属性的li标签
# text()获取标签中的内容并
# li_list=tree.xpath('//ul/li[@id]/text()')
#找到id为l1的li标签注意引号的问题
# li_list = tree.xpath('//ul/li[@id="11"]/text()')
#查找到id为l1的li标签的class的属性值
li = tree.xpath("//ul/li[@id="11"]/@class')
# 查询id中包含l的li标签
li list = tree.xpath('//ul/li[contains(@id,"l")]/text()')
#查询id的值以l开头的li标签
li_list = tree.xpath('//ul/li[starts-with(@id,"c")]/text()')
li_list = tree.xpath('//ul/li[@id="11"]/text()| //u1/li[@id="12"]/text()')
# 判断列表的长度
print(li_list)
print(len(li_list))
# 获取网页源码
content = response.read().decode('utf-8')
# 解析网页源码 来获取我们想要的数据
from lxml import etree
# 解析服务器响应的文件
tree = etree.HTML(content)
# 荻取想要的数据
result = tree.xpath('//input[@id="su"]/@value')
print(result)
JsonPath
jsonpath的安装及使用方式
pip安装:
pip install jsonpath
jsonpath的使用:
obj= json.load(open('json文件','r',encoding='utf-8'))
ret = jsonpath.jsonpath(obj,'jsonpath语法')
作业:1.股票信息提取(http://quote.stockstar.com/)
2.boos直聘
3.中华英才
4.汽车之家
Beautifulsoup
Beautifulsoup简称:bs4
Beautifulsoup,和lxml一样,是一个htm1的解析器,主要功能也是解析和提取数据
优缺点?
缺点:效率没有1xml的效率高
优点:接口设计人性化,使用方便
2.安装以及创建
1.安装
pip install bs4
2.导入
from bs4 import Beautifulsoup
3.创建对象
服务器响应的文件生成对象
soup = Beautifulsoup(response.read().decode(),'lxml')
本地文件生成对象
soup= Beautifulsoup(open('1.html'),'lxml')
注意:默认打开文件的编码格式gbk所以需要指定打开编码格式
soup = Beautifulsoup(open('075_尚硅谷_爬虫_解析_bs4的基本使用.html',encoding='utf-8'),'lxml')
3.节点定位
1.根据标签名查找节点
soup.a 【注】只能找到第一个a
soup.a.name
soup.a.attrs
2.函数
(1).find(返回一个对象)
find('a'):只找到第一个a标签
find('a',title='名字')
find('a',class='名字')
(2).find_all(返回一个列表)
find_all('a') 查找到所有的a
find_all(['a','span'])返回所有的a和span
find_all('a',limit=2) 只找前两个a
(3).select(根据选择器得到节点对象)【推荐】
1.element
eg:p
2..class
eg:.firstname
3.#id
eg:#firstname
4.属性选择器
[attribute]
eg:li=soup.select('li[class]')
[attribute=value]
eg:li = soup.select('li[class="hengheng1"]')
5.层级选择器
element element
div p
element>element
div>p
element,element
div,p
eg:soup = soup.select('a,span')
print(soup.select("div>ul>li'))
节点信息
(1).获取节点内容:适用于标签中嵌套标签的结构 obj= soup.select('#d1')[0]print(obj.string)
- obj.string
- obj.get_text()【推荐】
如果标签对象中 只有内容 那么string和get_text()都可以使用
如果标签对象中 除了内容还有标签 那么string就获取不到数据 而get_text()是可以获取数据
#我们一般情况下推荐使用get_text
(2).节点的属性
tag.name 获取标签名
eg:tag = find('li) print(tag.name)
tag.attrs将属性值作为一个字典返回
(3)获取节点属性
obj.attrs.get('title')【常用】obj.get('title')
应用实例:1.股票信息提取(
2.中华英才网-旧日版
3.腾讯公司招聘需求抓取(https://hr,tencent.com/index.php)
Selenium
1.什么是selenium?
(1)selenium是一个用于web应用程序测试的工具。
(2)selenium 测试直接运行在浏览器中,就像真正的用户在操作一样。
(3)支持通过各种driver(firfoxpriver,IternetExplorerDriver,OperaDriver,chromeDriver)驱动真实浏览器完成测试。
(4)selenium也是支持无界面浏览器操作的。
2.为什么使用selenium?
模拟浏览器功能,自动执行网页中的js代码,实现动态加载
3.如何安装selenium?
(1)操作谷歌浏览器驱动下载地址
http://chromedriver.storage.googleapis.com/index.html
(2)谷歌驱动和谷歌浏览器版本之间的映射表
http://blog.csdn.net/huilan same/article/details/51896672
(3)查看谷歌浏览器版本
谷歌浏览器右上角-->帮助-->关于
(4)pip install selenium
4.selenium的使用步骤?
(1)导入:from selenium import webdriver
(2)创建谷歌浏览器操作对象:
path =谷歌浏览器驱动文件路径.为了方便直接放在根目录
browser =webdriver.Chrome(path)
#(1)导入selenium
from selenium import webdriver
#(2)创建浏览器操作对象
path ='chromedriver.exe
browser = webdriver.Chrome(path)
#(3)访问网站
url ='https://ww.baidu.com'
browser.get(url)
# page_source获取网页源码
content =browser.page_sourceprint(content)
selenium的元素定位?
元素定位:自动化要做的就是模拟鼠标和键盘来操作来操作这些元素,点击、输入等等。操作这些元素前首先要找到它们,webpriver提供很多定位元素的方法
方法:1.find_element_by_id
eg:button=browser.find_element_by_id('su')
2.find_elements_by_name
eg:name_=_browser.find_element_by_name('wd')
3.find_elements_by_xpath
eg:xpath1=browser.find_elements_by_xpath('//input[@id="su"]')
4.find_elements_by_tag_name
eg:names=browser.find_elements_by_tag_name('input')
5.find_elements_by_css_selector
eg:my_input_=_browser.find_elements_by_css_selector('#kw')[0]
6.find_elements_by_link_text
eg:browser.find_element_by_link_text("新闻")
访问元素信息
获取元素属性
.get_attribute('class')
获取元素文本
.text
获取标签名
.tag_name
交互
点击:click()
输入:send_keys()
后退操作:browser.back()
前进操作:browser.forword()
模拟Js滚动:
js='document.body.scrollTop=100000'
js='document .documentelement.scrollTop=100000'
browser.execute_script(js)执行js代码
获取网页代码:page_source
from selenium import webdriver
# 刨建渕览器对象
path ='chromedriver.exe'
browser = webdriver.Chrome(path)
# urI
url='https://ww.baidu.combrowser.get(url)
import time
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()
time.sleep(2)
#回到上一页browser .back()
time.sleep(2)
# 回去
browser.forward()
time.sleep(3)
#退出
browser.quit( )
Phantomjs
1.什么是Phantomjs?
(1)是一个无界面的浏览器
(2)支持页面元素查找,js的执行等
(3)由于不进行css和gui渲染,运行效率要比真实的浏览器要快很多
2.如何使用Phantomjs?
(1)获取PhantomJs.exe文件路径path
(2)browser =webdriver.PhantomIs(path)
(3)browser.get(url)
扩展:保存屏幕快照:browser.save_screenshot('baidu.png')
phantomjs.exe放在项目根目录
from selenium import webdriver
path='phantomjs.exe'
browser =webdriver.PhantomJS(path)
url = 'https://www.baidu.com'
browser.get(url)
browser.save_screenshot('baidu.png')
import time
time.sleep(2)
input =browser.find_element_by_id('kw')
input.send_keys('昆凌')
time.sleep(3)
browser.save screenshot("kunling.png')
3.Chrome handless
1.系统要求:
Chrome
Unix\Linux 系统需要 chrome >= 59
Windows 系统需要 chrome>=60
Python3.6
Selenium==3.4.*
ChromeDriver==2.31
配置:
from selenium import webdriver
from selenium.webdriver.chrome.options import options
chrome options = options()
chrome options.add_argument('--headless )
chrome options.add_argument('--disable-gpu')
path = r'c:\Program Files(x86)\Google\chrome\Application\chrome.exe'
chrome_options.binary_location = path
browser = webdriver.chrome(chrome_options=chrome_options)
browser.get('http://www.baidu.com/')
browser.save_screenshot('baidu.png')
scrapy
Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。
安装scrapy: pip install scrapy
安装过程中出错: 如果安装有错误!!!! pip install scrapy
building 'twisted.test.raiser'extensionerror: Microsoft Visual C++ 14.0 is required, Get it with "Microsoft Visual C++
Build Tools":http://landinghub.visualstudio.com/visual-cpp-build-tools
解决方案:http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted下载twisted对应版本的wh1文件(如我的Twisted-17.5.0-cp36-cp36m-win amd64.wh1),cpp后面是python版本,amd64代表64位,
运行命令:pip install C:\Users...\Twisted-17.5.0-cp36-cp36m-win-amd64.whl
pip install scrapy
如果再报错
python -m pip install --upgrade pip
如果再报错 win32
1.scrapy项目的创建以及运行
1.创建scrapy项目:
终端输入 scrapy startproject 项目名称
注意:项目的名字不允许使用数字开头也不能包会中文
2.项目组成:
spiders
__init__.py
自定义的爬虫文件·py ---》由我们自己创建,是实现爬虫核心功能的文件
__init__.py
items .py ---》定义数据结构的地方,是一个继承自scrapy.Item的类
middlewares.py ---》中间件代理
pipelines.py ---》管道文件,里面只有一个类,用于处理下载数据的后续处理
默认是300优先级,值越小优先级越高(1-1000)
settings.py ---》配置文件 比如:是否遵守robots协议,user-Agent定义等
3.创建爬虫文件:
(1)跳转到spiders文件夹 cd 目录名字/目录名字/spiders
(2)scrapy genspider 爬虫名字 网页的域名
eg:scrapy genspider baidu http://www.baidu.com
一般情况下不需要添加http协议 因为start_urls的值是根据allowed domains
修改的 所以添加了http的话 那么start_urls就需要我们手动去修改了
爬虫文件的基本组成:
继承scrapy.spider类
name = 'baidu' ==> 运行爬虫文件时使用的名字
allowed_domains ==> 爬虫允许的域名,在爬取的时候,如果不是此域名之下的ur1,会被过滤掉
start_urls ==> 声明了爬虫的起始地址,可以写多个ur1,一般是一个
parse(self,response)---》解析数据的回调函数
response.text---》响应的是字符串
response.body---》响应的是二进制文件
response.xpath()-》xpath方法的返回值类型是selector列表
extract() -》提取的是selector对象的是data
extract_first() -》提取的是selector列表中的第一个数据
import scrapy
class Baiduspider(scrapy.Spider):
# 爬虫的名字 用于运行爬虫的时候 使用的值
name ='baidu
# 允许访问的域名
allowed domains =['http://ww.baidu.com']
# 起始的url地址 指的是第一次要访问的域名
# start_urls 是在allowed_domains的前面添加一个http://
# 在 allowed_domains的后面添加一个/
start_urls =['http://http://www.baidu.com/']
# 是执行了start_urls之后 执行的方法
# 方法中的response 就是返回的那个对象
# 相当于 response =urllib.request.urlopen()
# response =requests.get()
def parse(self, response):
pass
3.运行爬虫代码
scrapy crawl 爬虫的名字
scrapy crawl baidu
D:\Users\lijingAction\Desktop\尚硅谷爬虫视频录制\python爬虫\代码\Python爬虫scrapy baidu 091scrapy baidu 09l\spiders>scrapy genspider baidu http://www.baidu.com
settings.py
注释掉君子协议
# ROBOTSTXT_0BEY=True
scrapy架构组成
(1)引擎 ---》自动运行,无需关注,会自动组织所有的请求对象,分发给下载器
(2)下载器 ---》从引擎处获取到请求对象后,请求数据
(3)spiders ---》spider类定义了如何爬取某个(或某些)网站。包括了爬取的动作(例如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item)。 换句话说,spider就是您定义爬取的动作及分析某个网页(或者是有些网页)的地方。
(4)调度器 ---》有自己的调度规则,无需关注
(5)管道(Item pipeline)---》最终处理数据的管道,会预留接口供我们处理数据当Item在spider中被收集之后,它将会被传递到Item pipeline,一些组件会按照一定的顺序执行对Item的处理。每个item pipeline组件(有时称之为“Item pipeline”)是实现了简单方法的Python类。他们接收到Item并通过它执行一些行为,同时也决定此Item是否继续通过pipeline,或是被丢弃而不再进行处理。
以下是item pipeline的一些典型应用:
1.清理HTML数据
2.验证爬取的数据(检查item包含某些字段)
3.查重(井丢弃)
4.将爬取结果保存到数据库中
scrapy工作原理
1、引擎向spiders要ur
2、引擎将要爬取的url给调度器
3、调度器会将url生成请求对象放入到指定的队列中
4、从队列中出队一个请求
5、引擎将请求交给下载霞进行处理
6、下载路发送请求获取互联网教据
7、下载器将数据返回给引肇
8、引革将数据再次给到spiders
9、spiders通过xpath解析该数据,得到数据或者url
10、spiders将数据或者url给到引肇
11、引|擎判断该数据还是ur,是数据,交给管道(itempipeline)处理,是ur交给调度器处理

scrapy shell
Scrapy终端,是一个交互终端,供您在未启动spider的情况下尝试及调试您的爬取代码。 其本意是用来测试提取数据的代码,不过您可以将其作为正常的Python终端,在上面测试任何的Python代码。
该终端是用来测试XPath或css表达式,查看他们的工作方式及从爬取的网页中提取的数据。在编写您的spider时,该终端提供了交互性测试您的表达式代码的功能,免去了每次修改后运行spider的麻烦。-旦熟悉了scrapy终端后,您会发现其在开发和调试spider时发挥的巨大作用。
安装ipython
安装:pip install ipython
简介:如果您安装了 IPythonscrapy终端将使用 IPython(替代标准Pthon终端)。IPython 终端与其他相比更为强大,提供智能的自动补全,高亮输出,及其他特性。
3.应用:
(1)scrapy shell www.baidu.com
(2)scrapy shell http://www.baidu.com
(3)scrapy shell "http://www.baidu.com'
(4)scrapy shell "www.baidu.com"
语法:
(1)response对象
response.body
response.text
response.url
response.status
(2)response的解析:
response.xpath()(常用)
extract_first()
提取seletor列表中的第一个值
如果提取不到值 会返回一个空值
返回第一个解析到的值,如果列表为空,此种方法也不会报错,会返回一个空值
xpath()
css() -个selector对象可以再次的去使用xpath或者css方法
使用xpath路径查询特定元素,返回一个selector列表对象
response.url
http://www.baidu.com
response.status
200
response.xpath( //input[@id="su"]/@value’)
[<Selector xpath=’//inputl@id="su"]/@value'data=’百度一下’>]
a = response. xpath('//input[@id="su"]/@value’)
a
[<Selector xpath=’//input[@id="su"]/@value’ data='百度一下’>]
a. extract_first()
’百度一下’
response.css( #su::attr("value”)’)
[<Selector xpath="descendant-or-self::*[@id =’su’]/@value" data=’百度一下’>]
a=response.css( #su::attr("value”)’)
3.yield
1.带有 yield 的函数不再是一个普通函数,而是一个生成器generator,可用于迭代
2. yield 是一个类似 return 的关键字,迭代一次遇到yield时就返回yield后面(右边)的值。重点是:下一次迭代时,从上一次迭代遇到的yield后面的代码(下一行)开始执行
3.简要理解:yield就是 return 返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后(下一行)开始
案例:
1.当当网
2.电影天堂
(1)yield(2).管道封装(3).多条管道下载 (4)多页数据下载
(1)一个item包含多级页面的数据
4.MysqI
(1)下载(https://dev.mysal.com/downloads/windows/installer/5.7.html)
(2)安装(https://ingyan.baidu.com/album/d7130635f1c77d13fdf475df.html)
5.pymysql的使用步骤
1.pip install pymysql
2.pymysql.connect(host,port,user,password,db,charset)
3.conn.cursor()
4.cursor.execute()
6.Crawlspider
继承spider.scrapy
独门秘笈
crawlspider可以定义规则,再解析html内容的时候,可以根据链接规则提取出指定的链接,然后再向这些链接发送请求
所以,如果有需要跟进链接的需求,意思就是爬取了网页之后,需要提取链接再次爬取,使用crawlspider是非常合适的
提取链接
链接提取器,在这里就可以写规则提取指定链接
scrapy.linkextractors.LinkExtractor(
allow=(), #正则表达式,提取符合正则的链接 常用
deny =(), #(不用)正则表达式 不提取符合正则的链接
allow domains =() #(不用)允许的域名
deny domains =(),#(不用)不允许的域名
restrict_xpaths=(),#xpath,提取符合xpath规则的链接 常用
restrict css=() #提取符合选择器规则的链接) 常用
)
4.模拟使用
正则用法:1inks1 =LinkExtractor(allow=r'list 23 d+\.html')
xpath用法:links2 = LinkExtractor(restrict xpaths=r'//div[@class="x"]')
css用法:links3 =LinkExtractor(restrict css='.x')
5.提取连接
link.extract links(response)
In [3]: link = LinkExtractor(allow=r’/book/1188 d+\.html’)
link
scrapy.linkextractors.lxmlhtml.LxmlLinkExtractor at 0xlf4b7bf04a8
link.extract links (response)
6.注意事项
【注1】ca1lback只能写函数名字符串,callback='parse item
【注2】在基本的spider中,如果重新发送请求,那里的callback写的是callback=self.parse item【注.稍后看】follow=true 是否跟进 就是按照提取连接规则进行提取

7.Crawlspider案例
需求:读书网数据入库
1.创建项目:scrapy startproject dushuproject
2.跳转到spiders路径 cddushuproject\dushuproject\spiders
3.创建爬虫类:scrapy genspider -t crawl read www.dushu.com
4.items
5.spiders
6.settings
7.pipelines
数据保存到本地
数据保存到mysql数据库
read.py文件
import scrapy
from scrapy.linkextractors
import LinkExtractorfrom scrapy.spiders import CrawlSpider, Rule
from scrapy readbook 101.items import ScrapyReadbook101Item
class Readspider(Crawlspider):
name ="read'
allowed_domains =['www. dushu. com']
start_urls =['https://ww.dushu.com/book/1188_1.html']
rules =(
Rule(LinkExtractor(allow=r'/book/1188-\d+.html'),
callback='parse_item',
follow=True
),
def parse item(self, response):
item ={}
#item['domain_id']= response.xpath('//input[@id="sid"]/@value').get()
#item['name']= response.xpath('//div[@id="name"]').get()
#item['description']= response,xpath('//div[@id="description"]').get()
img_list =response.xpath('//div[@class="bookslist"]//img')
for img in img list:
name = img.xpath('./@data-original').extract_first()
src = img.xpath('./@alt').extract_first()
book =ScrapyReadbookt01Item(name=name,src=src)
return item
items.py文件
# Define here the models for your scraped items并
# See documentation in:# https://docs,scrapy,org/en/latest/topics/items.html
import scrapy
class ScrapyReadbook101Item(scrapy.Item):
# define the fields for your item here like.#name = scrapy.Field()
name = scrapy.Field()
src =scrapy.Field()
settings.py文件
ITEM PIPELINES {
'scrapy_readbook_101.pipelines.ScrapyReadbook101Pipeline': 300
# MysqlPipeline
'scrapy_readbook_101.pipelines.MysqlPipeline':301
}
DB HOST ='192.168.231.130# 端口号是一个整数
DB PORT = 3306
DB USER = 'root'
DB PASSWROD=1234
DB_NAME ='spider01'
DB CHARSET ='utf-8'
pipelines.py文件
class ScrapyReadbook101Pipeline:
def open_spider(self,spider):
self.fp =open('book.json','w',encoding='utf-8')
def process item(self, item, spider):
self.fp.write(str(item))
return item
def close_spider(self,spider):
self.fp.close()
class MysqlPipeline:
def open_spider(self,spider):
settings =get_project_settings()
self.host = settings['DB HOST']
self.port =settings['DB_PORT']
self.user =settings['DB USER']
self.password =settings['DB_PASSWROD']
self.name =settings['DB NAME']
self.charset =settings['DB_CHARSET']
self.connect()
def connect(self):
self.conn = pymysql.connect(
host=self.host,
port=self.port,
user=self.user,I
password=self.password,db=self.name,
charset=self.charset
}
Self.cursor = self.conn.cursor()
def process item(self, item, spider):
sql = 'insert into book(name,src) values("{}",“{}")'.format(item['name'],item{
# 执行sql语句
self.cursor.execute(sql)
#提对self.conn.commit()
return item
def close_spider(self,spider):
self.cursor.close()
self.conn.close()
9.日志信息和日志等级
(1)日志级别:
CRITICAL:严重错误
ERROR :一般错误
警告WARNING:
INFO:一般信息
DEBUG:调试信息
默认的日志等级是DEBUG
只要出现了DEBUG或者DEBUG以上等级的日志
那么这些日志将会打印
(2)settings.py文件设置:
默认的级别为DEBUG,会显示上面所有的信息
在配置文件中 settings.py
LOG FILE :将屏幕显示的信息全部记录到文件中,屏幕不再显示,注意文件后缀一定是.log
LOG LEVEL :设置日志显示的等级,就是显示哪些,不显示哪些
10.scrapy的post请求
(1)重写start_requests方法:
def start_requests(self)
(2)start requests的返回值:
scrapy.formRequest(url=url,headers=headers, callback=self.parse item, formdata=data)
ur1:要发送的post地址
headers:可以定制头信息
callback:回调函数
formdata: post所携带的数据,这是一个字典
11.代理
(1)到settings.py中,打开一个选项
DOWNLOADER MIDDLEWARES ={
postproject.middlewares.Proxy': 543,
}
(2)到middlewares.py中写代码
def process request(self, request, spider):
request.meta['proxy']='https://113.68.202.10:9999'
return None
class TestpostSpider(scrapy.spider):
name = 'testpost'
allowed domains =['https://fanyi.baidu.com/sug']
# post请求 如果没有参数 那么这个请求将没有任何意义
#所以start urls 也没有用了
# parse方法也没有用了
#start urls=['https://fanyi.baidu.com/sug/']
#def parse(self, response):
#pass
def start requests(self):
url='https://fanyi.baidu.com/sug'
data ={
'kw': 'final'
}
yield scrapy.FormRequest(url=url,formdata=data,callback=self.parse_second)
def parse_second(self,response)
content = response.text
obj= json.loads(content,encoding='utf-8')
print(obj)
middlewares.py文件
class RandomUserAgentMiddleware(object):
def process request(self, request, spider):
request.headers.setdefault("User Agent", UserAgent (). random)
settings.py文件
DOWNLOADER MIDDLEWARES={
scrapy test.middlewares.ScrapyTestDownloaderMiddleware’: 543,
}
# 代理服务
proxyserver = 'xxxxx'
#代理隧道验证信息
proxyUser ="H25X8780PF55HSBD"
proxyPass="AED98499BE02B4B3"
#for Python2
proxyAuth ="Basic "+ base64.b64encode(proxyUser ++ proxyPass)
class ProxyMiddleware (object):
def process request(self, request, spider):
request.meta["proxy"]= proxyServer
request.headers["Proxy Authorization"]= proxyAuth
settings.py
DOWNLOADER MIDDLEWARES=(
scrapy test.middlewares.RandomUserAgentMiddleware’:543,
scrapy test.middlewares.ProxyMiddleware’: 542,
}