跳至主要內容

HeChuangJun约 8902 字大约 30 分钟

架构

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/open in new window

快速上手
http://cn.python-requests.org/zhopen in new window 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数据之间的相互转换.

JSONPython
objectdict
arraylist
stringstr
number(int)int, long
number(real)float
trueTrue
falseFalse
nullNone
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币open in new window)进行爬取网页,获取有用信息解释

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/open in new window)
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.nameopen in new window
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. 节点信息
    (1).获取节点内容:适用于标签中嵌套标签的结构

    ​ obj= soup.select('#d1')[0]print(obj.string)

    1. obj.string
    2. obj.get_text()【推荐】

    如果标签对象中 只有内容 那么string和get_text()都可以使用

    如果标签对象中 除了内容还有标签 那么string就获取不到数据 而get_text()是可以获取数据

    #我们一般情况下推荐使用get_text

    (2).节点的属性
    tag.nameopen in new window 获取标签名
    eg:tag = find('li)

    ​ print(tag.nameopen in new window)

    tag.attrs将属性值作为一个字典返回

    (3)获取节点属性
    obj.attrs.get('title')【常用】

    obj.get('title')

应用实例:1.股票信息提取(
2.中华英才网-旧日版
3.腾讯公司招聘需求抓取(https://hropen in new window,tencent.com/index.phpopen in new window)

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.htmlopen in new window

(2)谷歌驱动和谷歌浏览器版本之间的映射表
http://blog.csdn.net/huilanopen in new window 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-toolsopen in new window

解决方案:http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted下载twisted对应版本的wh1文件open in new window(如我的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交给调度器处理

1.png
1.png

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.comopen in new window
(2)scrapy shell http://www.baidu.comopen in new window
(3)scrapy shell "http://www.baidu.comopen in new window'
(4)scrapy shell "www.baidu.comopen in new window"
语法:
(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 是否跟进 就是按照提取连接规则进行提取

2.png
2.png
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.pyopen in new window
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:9999open in new window'

​ 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,
}