Python爬虫学习
Python的文件操作
序列化与反序列化
通过文件操作,我们可以将字符串写入到一个本地文件。但是如果是一个对象(列表、字典、元组等),就无法直接写入到一个文件中,需要对这个对象进行序列化,然后才能写入到文件里。
设计一套协议,按照某种规则,把内存中的数据转换为字节序列,保存到文件,这就是序列化;反之,从文件的字节序列恢复到内存中,就是反序列化
Python中提供了
JSON
这个模块来实现数据的序列化与反序列化
使用JSON实现序列化
JSON提供了dump和dumps方法,将一个对象进行序列化
dumps()
方法的作用是把对象转换成字符串,它本身不具备将数据写入到文件的功能
# 对象的序列化
import json
#(1)创建一个文件
fp = open('test.txt','w')
#(2)定义一个列表
fruit_list = ['apple','peach']
# 将Python对象变成json字符串
fruit = json.dumps(fruit_list)
fp.write(fruit)
# 关闭文件
fp.close()
---------------------------------------------
# 用with语句来打开文件
fruit_list = ['apple','peach']
color_tuple = ('puple',99,'blue',100,fruit_list)
color = json.dumps(color_tuple)
with open('test.txt','a') as src_file:
src_file.write(color)
----------------------------------------------
#dump:在将对象转换为字符串的同时,指定一个文件的对象,然后把转换后的字符串写入到这个文件里
fp = open('text.txt','w')
name_list = ['zs','ls']
# 相当于names = json.dumps(name_list)和fp.write(names)
json.dump(name_list,fp)
fp.close()
Urllib
1.Urlib库使用
url.request.urlopen()
:模拟浏览器向计算机发送请求response
:服务器返回的数据response
的数据类型是HttpResponse
-
读取url的页面源码
read()
:字节形式读取二进制 扩展:read(5)
返回前5个字节`readline()
:读取一行readlines()
:一行一行读取直至结束getcode()
:获取状态码geturl()
:获取urlgetheaders()
:获取headers
-
urllib.request.urlretrieve(path,filename)
可以请求网页、请求图片和请求视频
2.请求对象的定制
-
UA介绍:User Agent中文名为用户代理,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU类型、浏览器及版本。
-
语法:
request = urllib.request.Request()
3.编解码
1.get请求方式
urllib
get请求的urllencode()
import urllib.parse
import urllib.request
base_url = 'https://www.baidu.com/s?'
data = {
'wd': '周杰伦',
'sex': '男',
'location': '中国台湾省'
}
new_data = urllib.parse.urlencode(data)
# 请求资源路径
url = base_url + new_data
# UA
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 '
'Safari/537.36 Edg/107.0.1418.35 '
}
# 请求对象的定制
request = urllib.request.Request(url=url,headers=headers)
# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
#print(content)
2.post请求方式
- 注意post请求的参数是不会拼接在url的后面,而是需要放在请求对象定制的参数中
- 注意事项:
post请求需要的是字节型,一定要进行编码。
编码之后必须调用encode方法
# 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/107.0.0.0 '
'Safari/537.36 Edg/107.0.1418.35 '
}
data = {
'kw': 'spider'
}
# post请求的参数必须要进行编码
# urllencode函数将字符串以URL编码
data = urllib.parse.urlencode(data).encode('utf-8')
# post请求的参数 是不会拼接在url的后面,而是需要放在请求对象定制的参数中
request = urllib.request.Request(url=url, data=data, headers=headers)
# 模拟服务器向服务器发送请求
response = urllib.request.urlopen(request)
# 获取响应的数据
content = response.read().decode('utf-8')
# 字符串-->json对象(反序列化)
import json
obj = json.loads(content)
print(obj)
4.ajax的get请求方式
# 下载豆瓣电影前10页的数据
# (1)请求对象的定制
# (2)获取响应的数据
# (3)下载数据
import urllib.parse
import urllib.request
# 获得get请求的方法
def create_request(page):
base_url = 'https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action='
data = {
'start': (page - 1) * 20,
'limit': 20
}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.35'
}
data = urllib.parse.urlencode(data)
url = base_url + data
request = urllib.request.Request(url=url, headers=headers)
return request
# 获取返回数据的方法
def get_content(request):
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
return content
# 下载数据到本地
def down_load(page, content):
with open(f'douban{page}.json', 'w', encoding='utf-8') as fp:
fp.write(content)
# 程序的入口
if __name__ == '__main__':
start_page = int(input('请输入起始页:'))
end_page = int(input('请输入结束页:'))
for page in range(start_page, end_page + 1):
request = create_request(page)
content = get_content(request)
down_load(page, content)
5.ajax的post请求
import urllib.request
import urllib.parse
def create_request(page):
base_url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname'
data = {
'cname': '北京',
'pid': '',
'pageIndex': page,
'pageSize': '10'
}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.35'
}
# url编码
data = urllib.parse.urlencode(data).encode('utf-8')
# 获得request请求
request = urllib.request.Request(url=base_url, data=data, headers=headers)
return request
def get_content(request):
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
return content
def down_load(page, content):
with open(f'kfc{page}.json', 'w', encoding='utf-8') as fp:
fp.write(content)
if __name__ == '__main__':
start_page = int(input('请输入起始页:'))
end_page = int(input('请输入结束页:'))
for page in range(start_page, end_page):
request = create_request(page)
content = get_content(request)
down_load(page,content)
6.URLError/HTTPError
简介:1.HTTPError类是URLError类的子类
2.导入的包urllib.error.HTTPError urllib.error.URLError
3.http错误:http错误是针对浏览器无法连接到服务器而增加出来的错误提示,引导并告诉浏览者该页是哪里出现了问题
4.通过urllib发送请求的时候,有可能会发送失败,这个时候如果想让你的代码更加健壮,可以通过try-except进行异常捕获,异常有两类,URLError\HTTPError
7.Handler处理器
前言:urllib.request.urlopen(url)
不能定制请求头
urllib.request.Request(url,headers,data)
可以定制请求头
- Hander可以定制更高级的请求头(动态cookie和代理不能使用请求对象的定制)
import urllib.request
url = 'https://www.baidu.com'
headers = {
'User-Agent': 'Moz2illa/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.35'
}
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)
8.代理服务器
代码配置代理
- 创建
Request
对象 - 创建
ProxyHandler
对象 - 用
handler
对象创建opener对象 - 使用
opener.open
函数发送请求
import urllib.request
url = 'http://www.baidu.com/s?wd=ip'
headers = {
'User-Agent': 'Moz2illa/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.35'
}
# 请求对象的定制
request = urllib.request.Request(url=url, headers=headers)
proxies = {
'http':'118.24.219.151:16817' #代理ip
}
# (1)获取handler对象
handler = urllib.request.ProxyHandler(proxies=proxies)
# (2)获取opener对象
opener = urllib.request.build_opener(handler)
# (3)调用open方法
response = opener.open(request)
# (4)读取返回内容
content = response.read().decode('utf-8')
# (5)保存
with open('Proxy.html', 'w', encoding='utf-8') as fp:
fp.write(content)
解析
1.xpath
1.导入lxml.etree
from lxml import etree
2.解析本地文件:etree.parse()
html_tree = etree.parse('xx.html')
3.解析服务器响应文件: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
案例1:demo.html和xpath.py
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>Title</title>
</head>
<body>
<ul>
<li id="one" class="city">北京</li>
<li id="two">上海</li>
<li id="tech">深圳</li>
<li id="hot">武汉</li>
</ul>
<ul>
<li>大连</li>
<li>沈阳</li>
<li>哈尔滨</li>
</ul>
</body>
</html>
from lxml import etree
# xpath解析本地文件
tree = etree.parse('demo.html')
# 查找所有有id属性的li标签
li_list = tree.xpath('//ul/li[@id]/text()')
print(li_list)
# print(len(li_list))
# 查找到id=""标签中的内容
# text()获取标签中的内容
te_list = tree.xpath('//ul/li[@id="one"]/text()')
print(te_list)
# 查找到id为one的li标签的class的属性值
li = tree.xpath('//ul/li[@id="one"]/@class')
print(li)
# 查询id中包含l的li标签
ct_list = tree.xpath('//ul/li[contains(@id,"e")]/text()')
print(ct_list)
# 查找id中以t开头的Li标签
st_list = tree.xpath('//ul/li[starts-with(@id,"t")]/text()')
print(st_list)
案例2:在网站上爬取图片素材
# 页码分析
# 第三页:https://sc.chinaz.com/tupian/diqiutupian_3.html
# 第一页:https://sc.chinaz.com/tupian/diqiutupian.html (注意不是_1)
import urllib.request
from lxml import etree
def create_request(page):
if (page == 1):
url = 'https://sc.chinaz.com/tupian/diqiutupian.html'
else:
# url = 'https://sc.chinaz.com/tupian/diqiutupian_'+str(page)+'.html'
url = f'https://sc.chinaz.com/tupian/diqiutupian_{page}.html'
# print(url)
headers = {
'User-Agent': 'Moz2illa/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.35 '
}
request = urllib.request.Request(url=url, headers=headers)
return request
def get_content(request):
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
return content
def down_load(content):
# 下载图片
# urllib.request.urlretrieve('图片地址','文件名称')
tree = etree.HTML(content)
name_list = tree.xpath('//div[@class="container"]//img/@alt')
src_list = tree.xpath('//div[@class="container"]//img/@data-original')
# print(len(name_list),len(src_list))
for i in range(len(name_list)):
name = name_list[i]
src = src_list[i]
# 加上https头
url = 'https:' + src
# 用空格替换_s,因为_s是缩略图
url = url.replace('_s', '')
# print(name,url)
urllib.request.urlretrieve(url=url, filename='./source/' + name + '.jpg')
# //div[@class="container"]//img/@data-original
if __name__ == '__main__':
st_page = int(input('请输入起始页码:'))
ed_page = int(input('请输入结束页码:'))
for page in range(st_page, ed_page + 1):
# (1)请求对象的定制
request = create_request(page)
# (2)获取网页的源码
content = get_content(request)
# (3)解析源码并下载图片
down_load(content)
2JsonPath
(1)jsonpath安装及使用方法
-
pip安装:
pip install jsonpath
-
jsonpath的使用:只能解析本地文件,和xpath用法上有区别
obj = json.load(open('json文件','r',encoding = 'utf-8')) ret = jsonpath.jsonpath(obj,'jsonpath语法')
(2)jsonpath写法对比
3.BeautifulSoup
- 和lxml一样,是一个html的解析器,主要功能也是解析和提取数据
(1) 安装和创建
- 安装 :
pip install bs4
- 导入:
from bs4 import BeautifulSoup
- 创建对象
- 服务器响应的文件生成对象
soup = BeautifulSoup(response.read().decode,'lxml')
- 本地文件生成对象
soup = BeautifulSoup(open('1.html'),'lxml')
- 服务器响应的文件生成对象
(2) 节点定位
1.根据标签名查找节点
soup.a 【注:只能找到第一个a】
soup.a.attrs 【查找标签a的属性和属性值】
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的参数中添加的是列表的数据
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(后代选择器) eg:div p
element>element(子代选择器) eg:div>p
element,element eg:div,p
(3) 节点信息
1.获取节点内容:适用于标签中嵌套标签的结构
obj.get_text()
2.节点的属性
tag.name 获取标签名
tag.attrs 将属性作为一个字典返回
3.获取节点属性
obj.attrs.get('title') 【常用】
obj.get('title')
obj['title']
Selenium
1.selenium的安装
- 操作edge浏览器驱动下载地址(注意要和edge浏览器版本保持一致)
https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
- pycharm下载selenium
pip install selenium
2.selenium的使用步骤
(1) 导入 :from selenium import webdriver
(2) 创建edge浏览器操作对象
# 创建浏览器操作对象
path = 'msedgedriver.exe'
# 尝试传参
s = Service(path)
brower = webdriver.Edge(service=s)
(3) 访问网址
url = 'https://www.jd.com/'
brower.get(url)
# page_source获取网页源码
content = brower.page_source
标签:Python,list,request,爬虫,urllib,page,content,url,cnblog
From: https://www.cnblogs.com/epochal/p/girl.html