Python学习
1.pycharm一些常用设置
设置通用代码模板
2.注释
单行注释:#
多行注释: ‘’’ ‘’‘’
3.变量类型
Number(数字) : int(有符号整形)、long(长整型,也可以代表八进制和十六进制)、float(浮点型)、complex(复数)
布尔类型:True、Flase
String(字符串)
List(列表)
Tuple(元祖)
Dictionary(字典)
- 1
- 2
- 3
- 4
- 5
- 6
使用
# 变量类型的基本使用
# int
money = 5000
# float
money2 = 1.2
# boolean 布尔
sex = True
gender = False
# String 字符串 使用的单引号或者双引号
s = "111"
# 单引号和双引号的嵌套
s4 = '"嵌套"'
print(s4)
s5 = "'嘿嘿嘿'"
print(s5)
# list 列表
name_list = ['周杰伦','复活科比']
print(name_list)
# tuple 元组
age_tuple =(18,19,20)
print(age_tuple)
# dict 字典
# 应用场景 :scrapy框架使用
person = {"key":"value","age":18}
print(person["key"])
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
4.查看变量数据类型
使用type方法判断变量的数据类型
a = 1
print(a)
print(type(a))
# float
b = 2.5
print(b)
print(type(b))
# boolean
c = True
print(c)
print(type(c))
# String
d = "中国"
print(d)
print(type(d))
# List
e = ["str",111]
print(e)
print(type(e))
# Dist
f = {"a":"aaa","b":222}
print(f)
print(type(f))
# Tuple
g = (1,2,3,4,5)
print(g)
print(type(g))
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
5.类型转换
# 字符串中特殊字符类型不能被转换
# 转换成整形
# str ---> int
str = '123'
print(type(str))
num = int(str)
print(type(num))
# float --> int
a = 1.23
print(type(int(a)))
# boolean --> int False = 0 True = 1
b = True
print(type(int(b)))
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
6.赋值运算符
d,e,f = 1,2,3
print(d)
- 1
- 2
7.逻辑运算符
# 逻辑运算符 and:与 or:或 not:非
# and:都成立为True
# or:一个成立为True,两个都不成立为False
# not:逻辑非,成立的为False,不成立的True
- 1
- 2
- 3
- 4
8.输入输出
输出
# 普通输出
print("1111")
# 格式化输出
# scrapy框架的时候 excel文件 mysql redis
age = 22
name = '张三'
print("我的年龄是:"+str(age))
# %s 代表着字符串 %d 代表着数值
print("我的名字是:%s,我的年龄是:%d" % (name,age))
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
输入
# 输入
code = input('请输入验证码:')
print("我的验证码是:%s" %code)
- 1
- 2
- 3
9.if语句
age = 22
if age>18:
print("你成年啦!")
score = int(input('请输入成绩:'))
if score>=90:
print("优秀")
elif score>=80:
print("良好")
elif score>=70:
print("及格")
else:
print("不及格")
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
10.for循环语句
# 循环字符串
# range(5)
# range(1,6)
# range(1,10,3)
# 循环一个列表
s = 'china'
# i是字符串中的字符变量(c、h、i、n、a)
# s是代表的是要遍历的数据
# range(5) 0~4 左闭右开区间(0,5)
# for i in range(5):
# print(i)
# range(1,6)
# for i in range(1,6):
# print(i)
# range(1,10,3)
# i=i+3 只要小于<10 步长
# for i in range(2,10,3):
# print(i)
# 循环一个列表
a_list = ['zs','ls','ww']
for i in range(0,len(a_list)):
print(i)
# len() 判断列表中元素的个数
print(len(a_list))
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
11.字符串高级
获取长度:len | len函数可以获取字符串的长度 |
---|---|
查找内容:find | 查找指定内容在字符串中是否存在,如果存在就返回该内容在字符串中第一次出现的开始位置索引值,如果不存在,则返回-1. |
判断:startswith,endswith | 判断字符串是不是以谁谁谁开头/结尾计算 |
出现次数:count | 返回 str在start和end之间 在 mystr里面出现的次数 |
替换内容:replace | 替换字符串中指定的内容,如果指定次数count,则替换不会超过count次。 |
切割字符串:split | 通过参数的内容切割字符串 |
修改大小写:upper,lower | 将字符串中的大小写互换 |
空格处理:strip | 去空格 |
字符串拼接:join | 字符串拼接 |
# len 判断长度
s = 'china'
print(len(s))
# 查找指定内容在字符串中是否存在,如果存在就返回该内容在字符串中第一次出现的开始位置索引值,如果不存在,则返回-1.
s1 = 'china'
print(s1.find('c'))
# 判断字符串是不是以谁谁谁开头/结尾计算
s2 = 'china'
print(s2.startswith('c'))
print(s2.endswith('c'))
# 返回 str在start和end之间 在 mystr里面出现的次数
s3 = 'aaabbb'
print(s3.count('a'))
# 替换字符串中指定的内容,如果指定次数count,则替换不会超过count次。
s4 = 'cccddd'
print(s4.replace('c','f'))
# 通过参数的内容切割字符串
s5 = '1#2#3#4#5'
print(s5.split('#'))
# 将字符串中的大小写互换
s6 = 'aBcD'
print(s6.upper())
print(s6.lower())
# 去空格
s7 = ' ddad '
print(len(s7.strip()))
# 字符串拼接
s8 = 'a'
print(s8.join('hello'))
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
12.列表高级
1.添加
# append 默认在列表的最后添加数据
food_list = ['老八秘制小汉堡','小鸡炖蘑菇']
print(food_list)
food_list.append('五花肉')
print(food_list)
# insert index的值就是你想插入数据的那个下标
char_list = ['a','c','d']
print(char_list)
char_list.insert(1,'b')
print(char_list)
# extend 可以迭代数据
num_list = [1,2,3]
num1_list = [4,5,6]
num_list.extend(num1_list)
print(num_list)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
2.修改
# 修改
city_list = ['北京','武汉','重庆']
print(city_list)
# 将列表中的元素的值修改
city_list[2] = '大连'
print(city_list)
- 1
- 2
- 3
- 4
- 5
- 6
3.查找
# 查找 in判断某一个元素是否在某一个列表中
food2_list = ['老八秘制小汉堡','小鸡炖蘑菇','东北乱炖']
# 判断一下在控制台输入的数据是否在列表中
fond = input('请输入您想吃的食物')
if fond in food2_list:
print("在")
else:
print("不在")
# not in 判断某一个元素不在某一个列表中
ball_list = ['篮球','台球']
ball = input("请输入您喜欢的球类:")
if ball not in ball_list:
print("不在")
else:
print('在')
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
4.删除
- del:根据下标进行删除
- pop:删除最后一个元素
- remove:根据元素的值进行删除
# 删除
# del
a_list = [1,2,3,4,5]
print(a_list)
# 根据下标删除列表中的元素
del a_list[2]
print(a_list)
# pop:删除最后一个元素
b_list = [1,2,3,4,5]
print(b_list)
b_list.pop()
print(b_list)
# remove:根据元素的值进行删除
c_list = [1,2,3,4,5]
print(c_list)
c_list.remove(1);
print(c_list)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
13.元组高级
a_tuple = (1,2,3,4)
print(a_tuple[0])
# 元祖是不可以修改里面的内容
# a_tuple[0] = 2 是错误的
# 1.元组和列表的区别是列表可以修改,元组不能修改
a_list = [1,2,3,4]
print(a_list[0])
a_list[0] = 5
print(a_list[0])
# 2.当元组中只有一个元素的时候,那么他是整型数据
b_tuple = (5)
print(type(b_tuple))
# 定义只有一个元素的元组,需要在唯一元素后面写一个逗号
c_tuple = (5,)
print(type(c_tuple))
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
14.切片
切片是指对操作的对象截取其中一部分的操作。字符串、列表、元组都支持切片操作
切片的语法:[起始:结束:步长],也可以简化使用[起始:结束]
s = 'hello world'
# 在切片中直接写一个下标
print(s[0]) #h
# 起始:结束,不包含结束,左闭右开
print(s[0:4]) #hell
# 起始:,代表起始开始到末尾
print(s[1:]) #ello world
# :结尾,从头到结尾
print(s[:4]) #hell
# 起始:结束:步长 到下标为6的位置结束,每次增长2个
print(s[0:6:2]) # hlo
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
15.字典高级
查询
# 定义一个字典
person = {'name':'张三','age':'22'}
# 访问person的name
print(person['name'])
# 获取一个不存在的key
# print(person['sex']) # errorKey
# 第二种获取方法 person.get('name')
print(person.get('name'))
# 使用.get获取一个不存在的key不会报错会给一个None
print(person.get('key')) # None
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
修改
person2 = {'name':'李四','age':'23'}
# 修改之前的字典
print(person2.get('name'))
# 修改name的值为法外狂徒
person['name'] = '法外狂徒'
print(person['name'])
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
添加
person3 = {"name":'老大'}
# 如果使用变量名字['键'] = 数据时,这个键如果在字典中不存在 那么就会变成新增元素
person3['age'] = '18'
print(person3['age'])
- 1
- 2
- 3
- 4
删除
# 删除
# del
# (1)删除字典中指定的某一个元素
person4 = {'name':"老马",'age':18}
# 删除前
print(person4)
del person4['age']
# 删除后
print(person4)
# (2)删除整个字典
# del person4
# print(person4)
# clear
# (3) 清空字典 但是保留字典对象
person4.clear()
print(person4) # {} 删除整个字典但是不删除结构
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
遍历
# 遍历
person5 = {"name":"杨松","age":23,"sex":"男"}
# (1) 遍历字典的key
# 字典.keys()
for key in person5.keys():
print(key)
# (2) 遍历字典的value
for val in person5.values():
print(val)
# (3) 遍历字典的key和value
for key,val in person5.items():
print(key,val)
for key in person5.items():
print(key)
# (4) 遍历字典的项/元素
for item in person5.items():
print(item)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
16.函数
函数的定义与调用
# 定义函数
def f():
print("欢迎")
# 调用函数
f()
- 1
- 2
- 3
- 4
- 5
- 6
函数参数的使用
# 使用函数计算1和2的和
def add(a,b):
print(a+b)
# 位置参数
add(3,4)
# 关键字传参
add(b = 100,a = 200)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
函数返回值
def add(a,b):
return a+b
c = add(3,4)
print(c)
- 1
- 2
- 3
- 4
- 5
17.文件
文件的打开与关闭
# 文件的打开与关闭
# open(文件路径,访问模式)
# 模式:w 可写
# r 可读
f = open('test.txt','w')
f.write("hello world")
# 文件夹是不可以创建的,需要手动创建
f = open("demo/text.txt","w")
f.write("hello python")
# 文件的关闭
fp = open("demo/a.txt",'w')
fp.write("hello")
fp.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
文件路径
绝对路径:绝对位置,完整地描述了目标的所在地,所有目录层级关系是一目了然的。
- 例如:
E:\python
,从电脑的盘符开始,表示的就是一个绝对路径。
相对路径:是从当前文件所在的文件夹开始的路径。
test.txt
,是在当前文件查找test.txt
文件./test.txt
,也是当前文件夹中查找test.txt
文件,./
表示的是当前文件夹../test.txt
,从当前文件夹的上一级文件夹里查找test.txt
文件。../
表示的是上一级文件夹demo/test.txt
,在当前文件夹里查找demo
这个文件夹,并在这个文件夹里查找test.txt
文件
文件的读写
# 写数据
# write方法
fp = open("demo/test.txt","a")
fp.write("hello world,I am here\n"*5)
fp.close()
# 如果再运行这段代码,可以覆盖代码
# 想在执行之后追加数据,更改模式 a
# 如果模式变为了a 那么就会执行追加的操作
# 读数据
fp = open("demo/test.txt", "r")
# 默认情况下,read是一字节一字节的读,效率比较低
content = fp.read()
print(content)
# readline读取一行数据
content = fp.readline()
print(content)
# readlines可以按照行来读取 但是会将所有的数据都读取到,并且以一个列表的形式返回
# 而列表的元素是一行一行的数据
content = fp.readlines()
print(content)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
18.文件的序列化和反序列化
通过文件操作,我们可以将字符串写入到一个本地文件。但是,如果是一个对象(例如列表、字典、元组等),就无法直接写入到一个文件里,需要对这个对象进行序列化,然后才能写入到文件里。
设计一套协议,按照某种规则,把内存中的数据转换为字节序列,保存到文件,这就是序列化,反之,从文件的字节序列恢复到内存中,就是反序列化。
Python中提供Json这个模块用来实现数据的序列化和反序列化。
- 对象—–>字节序列 === 序列化
- 字节序列—–>对象 ===反序列化
JSON模块
JSON是一种轻量级的数据交换标准。JSON的本质是字符串。
使用JSON实现序列化
JSON提供了dump和dumps方法,将一个对象进行序列化。
dumps方法的作用是把对象转换成字符串,它本身不具备将数据写入到文件的功能。
# fp = open("demo/test.txt",'w')
# # 默认情况我们只能将字符串写入文件中
# fp.write("hello world")
# fp.close()
# fp = open('test.txt','w')
# name_list = ['zhangsan','lisi']
# # 列表不能写入文件中 如果想写入到文件,那么必须使用序列化操作
# fp.write(name_list)
# 序列化的2种方式
# dumps()
# (1) 创建一个文件
fp = open('demo/test.txt','w')
# (2) 定义一个列表
name_list = ['zhangsan','lisi']
# (3) 导入json模块到该文件
import json
# 序列化
# 将python对象变成json字符串
# 我们在使用scrapy框架的时候,该框架会返回一个对象 我们要将对象写入到文件中,就要使用json.dumps
names = json.dumps(name_list)
# 将names写入到文件中
fp.write(names)
fp.close()
# dump
# 在将对象转换为字符串的同时,指定一个文件的对象,然后把转换后的字符串写入到这个文件里
import json
fp = open("demo/test.txt", 'w')
name_list = ['zss', 'ls']
import json
json.dump(name_list,fp)
fp.close()
# 反序列化
# 将json字符串变成一个python对象
fp = open("demo/test.txt",'r')
content = fp.read()
print(content)
# <class 'str'>
print(type(content))
# loads 加载字符串
# 反序列化json对象为python对象
result = json.loads(content)
# 转换之后
print(result)
# <class 'list'>
print(type(result))
fp.close()
# load 加载文件
fp = open("demo/test.txt",'r')
content = json.load(fp)
print(content)
print(type(content))
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
19.异常
try:
可能出现异常的代码
except 异常的类型
友好的提示
try:
fp=open("demo/s.txt",'r')
fp.read()
except FileNotFoundError:
print('系统正在升级,请稍后')
- 1
- 2
- 3
- 4
- 5
20.Urllib
一、反爬手段
User‐Agent:
User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。
代理IP
西次代理
快代理
什么是高匿名、匿名和透明代理?它们有什么区别?
1.使用透明代理,对方服务器可以知道你使用了代理,并且也知道你的真实IP。
2.使用匿名代理,对方服务器可以知道你使用了代理,但不知道你的真实IP。
3.使用高匿名代理,对方服务器不知道你使用了代理,更不知道你的真实IP。
验证码访问
- 打码平台
- 云打码平台
- 超级🦅
动态加载网页 网站返回的是js数据 并不是网页的真实数据
selenium驱动真实的浏览器发送请求
数据加密
分析js代码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
1.Urllib库的使用
基本使用
# 使用urllib来获取百度首页的源码
# (1) 定义一个url 就是你要访问的地址
import urllib.request
url = "http://www.baidu.com"
# (2) 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(url)
# (3) 获取响应中的页面的源码
# read方法 返回的是字节形式的二进制数据
# 我们要将二进制的数据转换为字符串
# 二进制===>字符串 === 解码 decode('编码格式')
content = response.read().decode("utf-8")
# (4) 打印数据
print(content)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
2.一个类型和六个方法
# 一个类型 HTTPResponse
# 六个方法 read()、readline()、readlines()、getcode()、geturl()、getheaders()
import urllib.request
url = "http://www.baidu.com"
# 模拟浏览器向服务器发送请求
resp = urllib.request.urlopen(url)
# 一个类型和六个方法 <class 'http.client.HTTPResponse'>
# print(type(resp))
# 按照一个字节一个字节读取
# content = resp.read()
# print(content)
# resp.read(数字) 代表返回多少个字节 b'<!DOC'
# content = resp.read(5)
# print(content)
# readline() :读取一行
# content = resp.readline()
# print(content)
# readlines() :读取多行
# content = resp.readlines()
# print(content)
# 返回状态码 如果是200 那么证明我们的逻辑没有错
# print(resp.getcode())
# 返回的是url地址
# print(resp.geturl())
# 获取是一个状态信息
print(resp.getheaders())
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
3.下载
# 下载网页
import urllib.request
url_page = 'http://www.baidu.com'
# url代表的是下载的路径,filename文件的名字
urllib.request.urlretrieve(url_page,"baidu.html")
# 下载图片
url_img = 'https://t7.baidu.com/it/u=1595072465,3644073269&fm=193&f=GIF'
urllib.request.urlretrieve(url_img,'bg.jpg')
# 下载视频
video_url = 'http://pgcvideo-cdn.xiaodutv.com/2882354867_1584684956_2018031615444820180316174016.mp4?authorization=bce-auth-v1%2Fc308a72e7b874edd9115e4614e1d62f6%2F2018-03-16T09%3A41%3A04Z%2F-1%2F%2Fe45da341e8dc544862d72871e3b949a9d3d36e3d651e4925e5778d961e3f6db1&responseCacheControl=max-age%3D8640000&responseExpires=Sun%2C+24+Jun+2018+17%3A41%3A04+GMTmp4&time=1657632635&xcode=829989cc93c9530b4ac98bacb4c3d44877e7bc56c0ecf6ed&_=1657548647900'
urllib.request.urlretrieve(video_url,'yyds.mp4')
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
4.请求对象的定制
UA介绍:User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本。浏览器内核、浏览器渲染引擎、浏览器语言、浏览器插件等
# url的组成
# http/https(更加安全)
# 协议 主机 端口号 路径 参数 锚点
# http 80
# https 443
# mysql 3306
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"
}
# 因为urlopen方法中不能存储字典 所以headers不能传递进去
# 请求对象的定制
# 注意 因为参数的顺序问题,不能直接写url和headers,中间还有data,所以我们需要关键字传参
request = urllib.request.Request(url=url,headers=headers)
resp = urllib.request.urlopen(request)
content = resp.read().decode("utf-8")
print(content)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
5.编解码
1、get请求方式:urllib.parse.quote()
# 需求: 获取https://www.baidu.com/s?wd=周杰伦 的网页源码
import urllib.request
url = "https://www.baidu.com/s?wd=%E5%91%A8%E6%9D%B0%E4%BC%A6"
# 请求对象的定制为了解决反爬的第一种手段
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"
}
# 将周杰伦三个字变成unicode编码的格式
# 我们需要依赖于urllib.parse
name = urllib.parse.quote("周杰伦")
print(name)
request = urllib.request.Request(url=url,headers=headers)
# 模拟浏览器向服务器发送请求
resp = urllib.request.urlopen(request)
# 获取响应的内容
content = resp.read().decode("utf-8")
# 报错 :'ascii' codec can't encode characters in position 10-12: ordinal not in range(128) ASCII码不能解码中文
# print(content)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
2、get请求方式:urllib.parse.urlencode()
主要解决多个中文参数时候
# urlencode应用场景:多个参数的时候
# https://www.baidu.com/s?wd=周杰伦&sex=男
import urllib.parse
import urllib.request
# data = {
# 'wd':'周杰伦',
# 'sex':'男',
# 'locatin':'中国台湾省'
# }
# content = urllib.parse.urlencode(data)
# print(content)
# 获取https://www.baidu.com/s?wd=%E5%91%A8%E6%9D%B0%E4%BC%A6&sex=%E7%94%B7
base_url = "https://www.baidu.com/s?"
data = {
'wd': '周杰伦',
'sex': '男',
'locatin': '中国台湾省'
}
new_data = urllib.parse.urlencode(data)
base_url += new_data
print(base_url)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"
}
# 请求对象的定制
request = urllib.request.Request(url=base_url, headers=headers)
# 模拟浏览器向服务器发送请求
resp = urllib.request.urlopen(request)
content = resp.read().decode("utf-8")
print(content)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
6.Post请求方式
post请求的参数,必须要进行编码 编码之后必须调用encode方法 data = urllib.parse.urlencode(data).encode("utf-8") 参数是放在请求对象定制的方法中 request = urllib.request.Request(url=url,data=data,headers=headers)
- 1
- 2
- 3
import urllib.request
import urllib.parse
# (1) post请求
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.0.0 "
"Safari/537.36 "
}
data = {
'kw': 'spider'
}
# (2) post请求的参数,必须进行编码
data = urllib.parse.urlencode(data).encode("utf-8")
# (3) post的请求参数是不会拼接在url的后面,而是需要放在请求定制对象的参数中
request = urllib.request.Request(url=url,data=data,headers=headers)
# (4) 模拟浏览器向服务器发送请求
resp = urllib.request.urlopen(request)
# (5) 最后查询内容时解码
content = resp.read().decode("utf-8")
print(content)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
百度详细翻译
import urllib.request
import urllib.parse
url = "https://fanyi.baidu.com/v2transapi?from=en&to=zh" # 在network中的v2transapi?from=en&to=zh中
headers = {
'Accept': '*/*',
# 'Accept-Encoding': 'gzip, deflate, br', 这句话需要注释,接收的格式不是utf-8
'Accept-Language': 'zh-CN,zh;q=0.9',
'Acs-Token': '1657609209232_1657634073392_QzvIJLYMoJlfU9K6oVDIEFqoL28DWbm988ZKnjR3xk8/Sa3rfbEgNkdwkbNM+hDMZzMdrF6a5Vwq6oR8XYtzy0d5DASp2ylIydmE62BTPpaZI/R15QT4dmatC0qtrzBFaBMCPzNtKYJxKugFW+JQzSu1gJkM3jvFBfQasudzEqAta6zzAZjptPRIg1leKg/oWvn5soJ4Marpa4nkA7jdSCs9Z0CoUuMGKxxxX46k7oLg+2WKmaolL8kMNDrBnwuo32t3c8UVkzqV9WRoVwe8jYSmCt1ghiaDRUhmxrdyutg=',
'Connection': 'keep-alive',
'Content-Length': '136',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Cookie': 'BIDUPSID=D51BF5882EE7B65BD4075DB6F624444E; PSTM=1649342254; BAIDUID=D51BF5882EE7B65B161C80EE82019036:FG=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; REALTIME_TRANS_SWITCH=1; SOUND_PREFER_SWITCH=1; SOUND_SPD_SWITCH=1; H_WISE_SIDS=110085_127969_131862_176399_179349_180636_185636_189755_191527_194085_196426_196527_197096_197471_197711_199568_204919_207234_207540_208721_209568_210302_210321_210643_211312_211557_211732_211953_212296_212726_212739_212798_212870_212912_213039_213059_213094_213278_213359_213485_213508_214093_214655_214789_215070_215120_215126_215731_215833_215856_215957_216044_216252_216295_216353_216416_216449_216569_216595_216635_216646_216656_216840_216913_216927_216937_216942_217088_217320_217452_217516_217584; BDUSS=lBHbDZNNVpieGxifjhwemJzMGljVzcxVHV-aTZEcjJ-YXBiZ2F0SjNVak9nLTlpRVFBQUFBJCQAAAAAAAAAAAEAAABWgsFN0MSwtsrvueJpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM72x2LO9sdib; BDUSS_BFESS=lBHbDZNNVpieGxifjhwemJzMGljVzcxVHV-aTZEcjJ-YXBiZ2F0SjNVak9nLTlpRVFBQUFBJCQAAAAAAAAAAAEAAABWgsFN0MSwtsrvueJpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM72x2LO9sdib; BDRCVFR[brmhvwvKpQR]=mk3SLVN4HKm; delPer=0; PSINO=2; ZFY=ak38XErjDSK5YKTfi2mIe1QGJTriLqXfChfud3qtFDM:C; H_WISE_SIDS_BFESS=110085_127969_131862_176399_179349_180636_185636_189755_191527_194085_196426_196527_197096_197471_197711_199568_204919_207234_207540_208721_209568_210302_210321_210643_211312_211557_211732_211953_212296_212726_212739_212798_212870_212912_213039_213059_213094_213278_213359_213485_213508_214093_214655_214789_215070_215120_215126_215731_215833_215856_215957_216044_216252_216295_216353_216416_216449_216569_216595_216635_216646_216656_216840_216913_216927_216937_216942_217088_217320_217452_217516_217584; RT="z=1&dm=baidu.com&si=dh45lyulsgc&ss=l5gs5ber&sl=1&tt=nz&bcn=https%3A%2F%2Ffclog.baidu.com%2Flog%2Fweirwood%3Ftype%3Dperf&ld=1g2&ul=b8n&hd=b8s"; BAIDUID_BFESS=7E6E2DBCD1049094EF0AAC7C26407A69:FG=1; BDRCVFR[S4-dAuiWMmn]=FZ_Jfs2436CUAqWmykCULPYrWm1n1fz; BDRCVFR[dG2JNJb_ajR]=mk3SLVN4HKm; BDRCVFR[X_XKQks0S63]=mk3SLVN4HKm; BDRCVFR[Q5XHKaSBNfR]=mk3SLVN4HKm; BDRCVFR[tox4WRQ4-Km]=mk3SLVN4HKm; BDRCVFR[-pGxjrCMryR]=mk3SLVN4HKm; BA_HECTOR=002k848l0h21a10h0hag1caq1hcqpqm17; H_PS_PSSID=26350; BDORZ=FFFB88E999055A3F8A630C64834BD6D0; APPGUIDE_10_0_2=1; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1657633745; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1657634066; ab_sr=1.0.1_NWFlMWJhMzUzZjNjODgxZTZjZTUwOWYwNjNlNjE1MmRiZTg1MTcxNzNlYzMwZGJiYzNkZGFkMGI4MDY2NDNhMjNkYzY5NjVlYTI0N2ViNmVhMGYyZWMyOGY0ZjMyOGE2ZGMzZGE5MjE4OTMxYTFiZDczMTA2ZjFlNTdkZWRhMDVkNDcxMDM0YzVmZTlhNGIwYTY2ZjE3ZmUwOTQ3MGM3YTc3YTc5YzcxMjY4ODc4YzJhYzVhNGVmM2Y0MGQ1MWE5',
'Host': 'fanyi.baidu.com',
'Origin': 'https://fanyi.baidu.com',
'Referer': 'https://fanyi.baidu.com/',
'sec-ch-ua': '".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36',
'X-Requested-With': 'XMLHttpRequest',
}
data = {
"from": "en",
"to": "zh",
"query": "spider",
"transtype": "realtime",
"simple_means_flag": "3",
"sign": "63766.268839",
"token": "c343c5a7b4fb792c974092c83cecf80f",
"domain": "common"
}
# post请求的参数必须编码,还必须调用encode方法
data = urllib.parse.urlencode(data).encode("utf-8")
# 请求对象的定制
request = urllib.request.Request(url=url,data=data,headers=headers)
# 模拟浏览器向服务器发送请求
resp = urllib.request.urlopen(request)
content = resp.read().decode('utf-8')
# {"errno":997,"errmsg":"\u672a\u77e5\u9519\u8bef","query":"spider","from":"en","to":"zh","error":997}
print(content)
import json
obj = json.loads(content)
# {'errno': 997, 'errmsg': '未知错误', 'query': 'spider', 'from': 'en', 'to': 'zh', 'error': 997}
print(obj)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
7.Ajax的get请求
get请求豆瓣的第一页内容
# get请求
# 获取豆瓣电影第一页的数据,并且保存起来
import urllib.request
import urllib.parse
url = "https://movie.douban.com/j/chart/top_list?type=11&interval_id=100:90&action=&start=0&limit=20"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36"
}
# (1)请求对象的定制
request = urllib.request.Request(url=url, headers=headers)
# (2)获取响应数据
resp = urllib.request.urlopen(request)
content = resp.read().decode("utf-8")
print(content)
# (3)数据下载到本地
# open方法默认情况下使用的gbk的编码,如果我们要想保存汉字,那么需要在open方法中指定编码格式为utf-8
fp = open("demo/douban.json","w",encoding='utf-8')
fp.write(content)
fp.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
-
get请求豆瓣电影前十页
# limit代表一页20条 # https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action=&start=0&limit=20 # https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action=&start=20&limit=20 # https://movie.douban.com/j/chart/top_list?type=11&interval_id=100%3A90&action=&start=40&limit=20 # page 1 2 3 4 # start 0 20 40 60 # start = (page-1)*20 # 下载豆瓣电影前十页的数据 # (1) 请求对象的定制 # (2) 获取响应数据 # (3) 下载数据 import urllib.parse import urllib.request # 获取request def create_request(page): base_url = "https://movie.douban.com/j/chart/top_list?type=11&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/103.0.0.0 Safari/537.36" } data = urllib.parse.urlencode(data) new_url = base_url + data request = urllib.request.Request(url=new_url, headers=headers) return request # 获取内容 def get_content(request): resp = urllib.request.urlopen(request) content = resp.read().decode("utf-8") return content # 下载数据 def download_data(content,page): fp = open("demo/douban_"+str(page)+'.json', "w",encoding='utf-8') fp.write(content) fp.close() # 程序的入口 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) # 下载 download_data(content,page)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
8.Ajax的post请求
-
post请求肯德基温州门店信息
# 请求地址 第一页 # http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword # post请求 # cname: # pid: # keyword: 太原 # pageIndex: 1 # pageSize: 10 # 第二页 # http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword # post请求 # cname: # pid: # keyword: 太原 # pageIndex: 2 # pageSize: 10 import urllib.request import urllib.parse # 获取request def create_request(page): base_url = "http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword" headers = { "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/103.0.0.0 Safari/537.36 " } # 获取data数据 data = { "cname":"", "pid":"", "keyword": "太原", "pageIndex": page, "pageSize": 10 } # post请求参数,必须编码 data = urllib.parse.urlencode(data).encode("utf-8") # post的请求参数是不会拼接到url后面,需要放在请求定制对象的参数中 request = urllib.request.Request(url=base_url,data=data,headers=headers) return request def create_content(request): # 模拟浏览器向服务器发送请求 resp = urllib.request.urlopen(request) content = resp.read().decode("utf-8") return content def download_data(content, page): fp = open("demo/kfc/kfc_"+str(page)+".json","w",encoding="utf-8") fp.write(content) fp.close() 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 = create_content(request) # 封装数据到文件中 download_data(content, page)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
9.URLError\HTTPError
import urllib.request
import urllib.error
# 正确的url : "https://blog.csdn.net/sulixu/article/details/119818949"
url = "https://blog.csdn.net/sulixu/article/details/119818949"
# urllib.error.HTTPError: HTTP Error 404: Not Found
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 "
"Safari/537.36 "
}
try:
# 请求对象的定制
request = urllib.request.Request(url=url, headers=headers)
# 模拟浏览器向服务器发送请求
resp = urllib.request.urlopen(request)
# 获取页面内容
content = resp.read().decode("utf-8")
print(content)
except urllib.error.HTTPError:
print("系统正在升级.....")
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
10.微博的cookie登录
适用的场景:数据采集的时候,需要绕过登录,然后进入到某个页面
cookie是headers中的关键信息,如果有登录之后的cookie,那么我们可以携带着cookie进入到任何页面
# 适用的场景:数据采集的时候,需要绕过登录,然后进入到某个页面
# 个人信息页面是utf-8 但还是报错了编码错误,因为并没有进入到个人信息页面,而是跳转到了登录页面
import urllib.request
url = "https://weibo.cn/5873215474/profile"
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 "
"Safari/537.36 ",
"cookie": "_T_WM=8976340b3c92efa3a03b7fb4682e53d4; "
"SCF=AkwF768NP5yG7U7IM_1mAFgkAANBFgxO8xLzIe8aDTyPsRX0h0nT1lXgYkJh7-VsFN4BnJCBHNWpmoTL54XJ0gQ.; "
"SUB=_2A25Py-vdDeRhGeNG7FET8SvIzDiIHXVtN_WVrDV6PUJbktAKLXmikW1NSwrsX3IMnAf8hBG_QjQwt96xry03Xpu3; "
"SUBP"
"=0033WrSXqPxfM725Ws9jqgMF55529P9D9W592gFJm2N2necZ9sUyMAdh5NHD95Qf1hM0eo2fShMXWs4DqcjSxP9LMJUjdNUNUNUNTBtt; SSOLoginState=1657772941 "
}
# 请求对象的定制
request = urllib.request.Request(url=url,headers=headers)
# 模拟浏览器向服务器发送请求
resp = urllib.request.urlopen(request)
# 获取内容
content = resp.read().decode("UTF-8")
print(content)
# 将数据保存在本地
with open("demo/weibo.html",'w',encoding='UTF-8') as fp:
fp.write(content)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
11.Handler处理器
# 需求 使用handler来访问百度 获取网页源码
import urllib.request
url = "http://www.baidu.com"
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 '
'Safari/537.36',
}
request = urllib.request.Request(url=url, headers=headers)
# handler build_opener open
# (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)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
import urllib.request
url = "https://www.baidu.com/s?wd=ip"
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 '
'Safari/537.36',
}
# 请求对象的定制
request = urllib.request.Request(url=url,headers=headers)
# 模拟浏览器访问服务器
# resp = urllib.request.urlopen(request)
# handler build_opener open
proxies = {
'http':'202.55.5.209:8090'
}
handler = urllib.request.ProxyHandler(proxies=proxies)
opener = urllib.request.build_opener(handler)
resp = opener.open(request)
# 获取响应信息
content = resp.read().decode("utf-8")
# 保存
with open("demo/daili.html",'w',encoding="utf-8") as fp:
fp.write(content)
fp.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
12.代理池
import urllib.request
proxies_pool= [
{
'http':'202.55.5.209:8091111',
'http':'202.55.5.209:8092222'
}
]
import random
proxies = random.choice(proxies_pool)
print(proxies)
url = "https://www.baidu.com/s?wd=ip"
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 '
'Safari/537.36',
}
# 定制请求对象
request = urllib.request.Request(url=url,headers=headers)
# ProxyHandler build_opener open
handler = urllib.request.ProxyHandler(proxies=proxies)
opener = urllib.request.build_opener(handler)
resp = opener.open(request)
content = resp.read().decode("utf-8")
print(content)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
21.xpath
1.xpath基本使用
# xpath解析
# (1) 本地文件 etree.parse
# (2)服务器响应的数据 resp.read().decode("utf-8")**** 使用居多 etree.HTML()
- 1
- 2
- 3
-
安装lxml库
pip install lxml ‐i https://pypi.douban.com/simple # 如果没用就换以下 pip install lxml -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python
- 1
- 2
- 3
-
导入lxml.etree
from lxml import etree
- 1
-
etree.parse() 解析本地文件
html页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"/> <title>Title</title> </head> <body> <ul> <li id="l1" class="c1">武汉</li> <li id="l2">北京</li> <li id="c3">上海</li> <li id="c4">深圳</li> </ul> <ul> <li>辽宁</li> <li>山西</li> <li>重庆</li> </ul> </body> </html>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
# xpath解析本地文件 tree = etree.parse("040_解析_xpath的基本使用.html") # print(tree) # tree.xpath("xpath路径") # 查找ul下面的li # li_list = tree.xpath("//ul/li") # 查找所有有id属性的id # li_list = tree.xpath("//ul/li[@id]") # 查找id为l1的li标签 注意引号的问题 # li_list = tree.xpath("//ul/li[@id='l1']") # 查找到id为l1的li标签的class属性值 # li_list = tree.xpath("//ul/li[@id='l1']/@class") # ['c1'] # 查询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,'l')]/text()") # ['武汉', '北京'] # 查询id为l1和class为c1 # li_list = tree.xpath("//ul/li[@id='l1' and @class='c1']/text()") # ['武汉'] # 查询id为l1或id为l2 li_list = tree.xpath("//ul/li[@id='l1' or @id='l2' ]/text()") # ['武汉', '北京'] print(li_list) print(len(li_list))
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
-
etree.HTML() 服务器响应文件
在浏览器上打开xpath: ctrl+shift+x
获取百度中百度一下
html_tree = etree.HTML(response.read().decode('utf‐8') # (1) 获取网页的源码 # (2) 解析 解析服务器响应的文件 etree.HTML # (3) 打印 import urllib.request from lxml import etree 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.0.0 ' 'Safari/537.36', } # 请求对象的定制 request = urllib.request.Request(url=url,headers=headers) # 模拟浏览器访问服务器 resp = urllib.request.urlopen(request) # 获取网页源码 content = resp.read().decode("utf-8") # print(content) # 解析服务器响应的文件 xpath的返回值是一个列表类型的返回值 tree = etree.HTML(content) result = tree.xpath("//input[@id='su']/@value") print(result)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
2.抓取站长素材图片案例
# (1)请求对象的定制
# (2)获取网页源码
# (3)下载
# 需求:下载前十页的图片
# https://sc.chinaz.com/tupian/fengjingtupian.html 第一页地址
# https://sc.chinaz.com/tupian/fengjingtupian_2.html 第二页地址
import urllib.request
from lxml import etree
def create_request(page):
if (page == 1):
url = "https://sc.chinaz.com/tupian/fengjingtupian.html"
else:
url = "https://sc.chinaz.com/tupian/fengjingtupian_" + str(page + 1) + ".html"
headers = {
'Cookie': 'UM_distinctid=180329fba793b3-012dea3615a8f7-1734337f-1fa400-180329fba7ae91; '
'Hm_lvt_398913ed58c9e7dfe9695953fb7b6799=1657797106; '
'Hm_lpvt_398913ed58c9e7dfe9695953fb7b6799=1657797286',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/103.0.0.0 Safari/537.36',
}
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 download_photo(content):
# 下载图片
tree = etree.HTML(content)
name_list = tree.xpath("//div[@id = 'container']//a/img/@alt")
# 一般设计图片的网站都会进行懒加载
img_list = tree.xpath("//div[@id = 'container']//a/img/@src")
print(len(name_list),len(img_list))
# urllib.request.urlretrieve("图片地址","文件名字")
for i in range(len(name_list)):
name = name_list[i]
src = img_list[i]
url = 'https:'+ src
urllib.request.urlretrieve(url=url,filename='demo/zhanzhang/'+name+'.jpg')
if __name__ == '__main__':
start_page = int(input("请输入起始页码:"))
end_page = int(input("请输入结束页码:"))
for page in range(start_page, end_page + 1):
# (1)请求对象的定制
request = create_request(page)
# (2)获取网页源码
content = get_content(request)
# (3)下载源码
download_photo(content)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
22.JsonPath
pip安装
pip install jsonpath
- 1
jsonpath的使用
obj = json.load(open('json文件', 'r', encoding='utf‐8'))
ret = jsonpath.jsonpath(obj, 'jsonpath语法')
- 1
- 2
jsonpath与lxml语法对比
数据源
{ "store": {
"book": [
{ "category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{ "category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{ "category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{ "category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
根据json案例写出jsonpath解析json数据
import jsonpath
import json
obj = json.load(open("043_解析_jsonpath.json",'r',encoding="utf-8"))
# print(obj)
# 书店所有书的作者
author_list = jsonpath.jsonpath(obj,'$.store.book[*].author')
# print(author_list)
# 所有的作者
all_author = jsonpath.jsonpath(obj,'$..author')
# print(all_author)
# store下面所有的元素
a_list = jsonpath.jsonpath(obj,'$.store.*')
# print(a_list)
# store里面所有的price
p_list = jsonpath.jsonpath(obj,'$.store..price')
# print(p_list)
# 第三本书
three_b = jsonpath.jsonpath(obj,'$..book[2]')
# print(three_b)
# 最后一本书
last_b = jsonpath.jsonpath(obj,'$..book[(@.length-1)]')
# print(last_b)
# 前面两本书
one_two_book = jsonpath.jsonpath(obj,'$..book[0,1]')
# print(one_two_book)
# 条件过滤需要在()前面添加一个?
# 过滤出所有包含isbn的书
isbn_b = jsonpath.jsonpath(obj,'$..book[?(@.isbn)]')
# print(isbn_b)
# 过滤出价格低于10的书
low_10_b = jsonpath.jsonpath(obj,'$..book[?(@.price<10)]')
print(low_10_b)
# 所有元素
all = jsonpath.jsonpath(obj,'$..*')
print(all)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
jsonpath与lxml写法对比
jsonpath解析淘票票
import json
import urllib.request
import jsonpath
url = "https://dianying.taobao.com/cityAction.json?activityId&_ksTS=1657803673954_108&jsoncallback=jsonp109&action" \
"=cityAction&n_s=new&event_submit_doGetAllRegion=true "
headers = {
'accept': '*/*',
# 'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9',
'cookie': 't=d62feb12ede27bcd90fe3ffe94fcd7b6; cna=IpPWGiQbjAMCAbe/VXNAveQr; '
'cookie2=17a771d956232603066efff8888c59de; v=0; _tb_token_=e9be5b5e1b3be; xlly_s=1; '
'tfstk=cpJOBFx4f20GG155Ghhh3dwFrgJOaGgARl_0HKiY2MroUjyzEsX2ELHSTfsfzNnd.; '
'l=eBrLzoUILDxDBeT3BO5Bhurza779NQdb8rVzaNbMiInca6gPTUHnqNCHHI4J7dtjgt5AGeKPUcfRbdh2kzUg7FGjL77uKtyuJLpp-e1'
'..; isg=BICAe8v59pOlJIo0Dr70WK-GUQ5SCWTT7VDLXvoS7RtmdSGfox_JYEQLjd21Qxyr',
'referer': 'https://dianying.taobao.com/',
'sec-ch-ua': '".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'sec-fetch-dest': 'script',
'sec-fetch-mode': 'no-cors',
'sec-fetch-site': 'same-site',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36',
}
# 请求对象的定制
request = urllib.request.Request(url=url,headers=headers)
# 模拟浏览器向服务器发送请求
resp = urllib.request.urlopen(request)
content = resp.read().decode("utf-8")
# 字符串切割
content = content.split("(")[1].split(")")[0]
# print(content)
# with open("demo/taopiaopiao/tpp.json",'w',encoding='utf-8') as fp:
# fp.write(content)
fp = open("demo/taopiaopiao/tpp.json",'r',encoding='utf-8')
obj = json.load(fp)
print(obj)
region_name = jsonpath.jsonpath(obj,'$..regionName')
print(region_name)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
23.BeatifulSoup
1.基本简介
2.安装以及创建
3.节点定位
4.节点信息
本地数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>Title</title>
</head>
<body>
<div>
<ul>
<li id="l1">张三</li>
<li id="l2">李四</li>
<li>王五</li>
<a href="" class="a1">张三之家</a>
<span>哈哈哈哈</span>
</ul>
</div>
<a href="" title="a2">李四之家</a>
<div id="d1">
<span>哈哈哈哈</span>
</div>
<p id="p1" class="p1">呵呵呵</p>
</body>
</html>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
bs4的基本使用
from bs4 import BeautifulSoup
# 通过解析本地文件 来将bs4的基础语法进行解析
# 默认打开的文件的编码格式是gbk 所以在打开文件的时候需要指定编码
soup = BeautifulSoup(open('045_解析_bs4的基本使用.html',encoding='utf-8'),'lxml')
# 根据标签名查找节点
# print(soup.a) # 找到的是第一个符合条件的数据
# attrs获取标签的属性和属性值
# print(soup.a.attrs)
# bs4的一些函数
# (1) find 返回的是第一个符合条件的数据
# print(soup.find('a'))
# 找到title标签为a2的数据
# print(soup.find('a',title='a2'))
# 根据class的值找到标签对象,注意:class要加下划线
# print(soup.find('a',class_='a1'))
# (2) find_all 返回的是列表,并且返回了所有的a标签
# print(soup.find_all('a'))
# 找到所有a标签和span标签 如果要获取的是多个标签的数据,那么需要在find_all()的参数中添加的是列表的数据
# print(soup.find_all(['a','span']))
# limit是查询前几个的数据
# print(soup.find_all('li',limit=2))
# print(soup.find_all('li')[1:3])
# (3) select(推荐)
# select方法返回的是一个列表,并且会返回多个数据
# print(soup.select('a'))
# 可以通过.代表class,这种操作叫做类选择器
# print(soup.select('.a1')) # [<a class="a1" href="">张三之家</a>]
# id选择器
# print(soup.select(("#l1"))) # [<li id="l1">张三</li>]
# 属性选择器---通过属性来寻找对应标签
# 查找到li标签中有id的标签
# print(soup.select('li[id]')) # [<li id="l1">张三</li>, <li id="l2">李四</li>]
# 查找到li标签中id=l2的标签
# print(soup.select('li[id="l2"]')) # [<li id="l2">李四</li>]
# 层级选择器
# 后代选择器
# 找到div下面的li,空格代表后代
# print(soup.select('div li')) # [<li id="l1">张三</li>, <li id="l2">李四</li>, <li>王五</li>]
# 子代选择器
# 某标签的第一级子标签 注意:很多编程语言中,如果不加空格不会输出内容,在bs4中不会报错
# print(soup.select('div>ul>li')) # [<li id="l1">张三</li>, <li id="l2">李四</li>, <li>王五</li>]
# 找到a标签和li标签的所有对象(优点)
# print(soup.select('a,li')) # [<li id="l1">张三</li>, <li id="l2">李四</li>, <li>王五</li>, <a class="a1" href="">张三之家</a>, <a href="" title="a2">李四之家</a>]
# 节点信息
# 获取节点内容
# obj = soup.select('#d1')[0]
# 如果标签对象中,只有内容,那么string和get_text()都可以使用
# 如果标签对象中,除了内容还有标签,那么string就获取不到内容,而get_text()是可以获取数据
# 我们一般情况下,推荐使用get_text()
# print(obj.string)
# print(obj.get_text())
# 节点的属性
obj = soup.select('#p1')[0]
# name是标签的名字
# print(obj.name)
# 将属性值作为一个字典返回
# print(obj.attrs) # {'id': 'p1', 'class': ['p1']}
# 获取节点的属性
obj = soup.select('#p1')[0]
print(obj.attrs.get('class')) # ['p1']
print(obj.get('class')) # ['p1']
print(obj['class']) # ['p1']
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
bs4爬取星巴克数据
import urllib.request
from bs4 import BeautifulSoup
url = 'https://www.starbucks.com.cn/menu/'
resp = urllib.request.urlopen(url)
content = resp.read().decode("utf-8")
soup = BeautifulSoup(content,'lxml')
# //ul[@class='grid padded-3 product']//strong/text()
name_list = soup.select('ul[class="grid padded-3 product"] strong')
# print(name_list)
for name in name_list:
print(name.get_text())
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
24.Requests
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t0m1X1Vw-1658307246358)(D:\Desktop\CSDN博客\Python学习.assets\image-20220717110557728.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MndtXWN6-1658307246359)(D:\Desktop\CSDN博客\Python学习.assets\image-20220717110618063.png)]
1.一个方法以及六个属性
基本使用
import requests
url = 'http://www.baidu.com'
resp = requests.get(url=url)
# 一个类型,六个属性 <class 'requests.models.Response'>
# print(type(resp))
# 1.设置响应的编码格式
resp.encoding = 'utf-8'
# 2.以字符串形式返回了网页源码
# print(resp.text)
# 3.返回url地址
# print(resp.url)
# 4.返回二进制数据
# print(resp.content)
# 5.返回响应的状态码
# print(resp.status_code)
# 6.获取响应头
print(resp.headers)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
2.requests与urllib的区别
# urllib
# (1) 一个类型以及六个方法
# (2) get请求
# (3) post请求 百度翻译
# (4) ajax的get请求
# (5) ajax的post请求
# (6) cookie登录 微博
# (7) 代理 快代理
# requests
# (1) 一个类型以及六个属性
# (2) get请求
# (3) post请求
# (4) 代理
# (5) cookie 验证码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
3.get请求
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.0.0 "
"Safari/537.36 "
}
data = {
'wd':'北京'
}
# url 请求资源路径
# params 参数
# kwargs 字典
resp = requests.get(url=url,params=data,headers=headers)
content = resp.text
print(content)
# 总结:
# 参数使用params传递
# 参数无须urlencoding编码
# 不需要请求对象的定制
# 请求资源路径中的?可以加也可以不加
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
4.post请求
import json
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.0.0 "
"Safari/537.36 "
}
data = {
'kw': 'eye'
}
# url 请求地址
# data 请求参数
# kwargs 字典
resp = requests.post(url=url, data=data, headers=headers)
content = resp.text
# 转成json格式
obj = json.loads(content.encode('utf-8'))
print(obj)
# 总结
# (1) post请求 是不需要编解码
# (2) post请求的参数是data
# (3) 不需要请求对象的定制
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
5.cookie登录古诗文网
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nbvklSwY-1658307246360)(D:\Desktop\CSDN博客\Python学习.assets\image-20220717121244899.png)]
# 通过登录 然后进入到主页面
# 通过找登录接口我们发现,登录的时候需要的参数很多
# __VIEWSTATE: WQcK5cuI5TJ9JhnptzvgDT7zIWCLYU1DlLMsyTxFVGrXSoTAWWvYxcP1QP96hGeWPO/zIWvqJtAW6wk/Q4nQy9xjvWQZbMzhAsJhgpEJovkoPf4vzXgZSwoMXttI98whqL29O6+E6iocDXxBeF6loWoheEs=
# __VIEWSTATEGENERATOR: C93BE1AE
# from: http://so.gushiwen.cn/user/collect.aspx
# email: 18672599132
# pwd: wwwddddd
# code: wrvh
# denglu: 登录
# 观察到__VIEWSTATE __VIEWSTATEGENERATOR code是变量
# 难点 :(1)__VIEWSTATE __VIEWSTATEGENERATOR 一般情况看不到的数据 都是在页面的源码中
# 我们观察到的这两个数据在页面的源码中,所以我们需要获取页面的源码,然后进行解析就可以获取了
# (2) code验证码
import requests
from bs4 import BeautifulSoup
# 登录页面的url地址
url = 'https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx'
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 "
"Safari/537.36 "
}
# 获取页面源码
resp = requests.get(url=url,headers=headers)
content = resp.text
# print(content)
# 解析页面源码
soup = BeautifulSoup(content,'lxml')
# 获取__VIEWSTATE
viewstate = soup.select('#__VIEWSTATE')[0].attrs.get('value')
# 获取__VIEWSTATEGENERATOR
viewstateGenerator = soup.select('#__VIEWSTATEGENERATOR')[0].attrs.get('value')
# 获取验证码图片
code = soup.select('#imgCode')[0].attrs.get('src')
code_url = 'https://so.gushiwen.cn'+code
# 有坑 获取验证码后相当于向服务器请求一次了,后续登录时又请求了一次,两次验证码不一致
# import urllib.request
# urllib.request.urlretrieve(url=code_url,filename='code.jpg')
# requests中有一个方法 session(),通过session返回值就能使用请求变成一个对象
session = requests.session()
# 验证码的url的内容
resp_code = session.get(code_url)
# 注意此时要使用二进制数据,因为我们要使用的是图片的下载
content_code = resp_code.content
with open('code.jpg','wb') as fp:
fp.write(content_code)
fp.close()
# 获取验证码的图片后下载到本地,然后观察验证码,观察之后在控制台输入这个验证码,就可以把值给code的参数然后登录
code_name = input("请输入你的验证码:")
# 点击登录提交后的url
url_post = 'https://so.gushiwen.cn/user/login.aspx?from=http%3a%2f%2fso.gushiwen.cn%2fuser%2fcollect.aspx'
data_post = {
'__VIEWSTATE': viewstate,
'__VIEWSTATEGENERATOR': viewstateGenerator,
'from': 'http://so.gushiwen.cn/user/collect.aspx',
'email': '18672599132',
'pwd': 'dhn913219642',
'code': code_name,
'denglu': '登录',
}
# 不能使用requests.post 必须使用session!!!
resp_post = session.post(url=url_post,data=data_post,headers=headers)
content_post = resp_post.text
with open('demo/gushiwen/gushiwen.html','w',encoding='utf-8') as fp:
fp.write(content_post)
fp.close()
# 难点
# (1)隐藏域
# (2)验证码
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
6.超级鹰打码平台的使用
25.scrapy
scrapy是什么?
Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。
- 1
安装scrapy
pip install scrapy
- 1
1.基本使用
1.1创建scrapy项目
终端输入 scrapy startproject 项目名称
1.2项目组成
1.3创建爬虫文件
跳转到spiders文件夹
cd 目录名字/目录名字/spiders
- 1
创建爬虫文件.py
scrapy genspider 爬虫名字 网页的域名
# 比如
scrapy genspider baidu www.baidu.com
- 1
- 2
- 3
爬虫文件的基本组成
生成的爬虫文件
import scrapy
class BaiduSpider(scrapy.Spider):
# 爬虫名字,用于运行爬虫时使用的值
name = 'baidu'
# 允许访问的域名
allowed_domains = ['www.baidu.com']
# 起始的url地址,指的是第一次要访问的域名
# start_urls 是在allowed_domains的前面添加一个http:// 在allowed_domains的后面添加了一个斜线
# start_urls的值是根据allowed_domains的基础上修改出来的
start_urls = ['http://www.baidu.com/']
# 执行了start_urls之后执行的方法 方法中的response 就是返回的那个对象
# 相当于response = urllib.request.ulopen()
# 还相当于response = requests.get()
def parse(self, response):
print('hello scrapy')
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
运行爬虫代码
scrapy crawl 爬虫的名字
eg: scrapy crawl baidu
- 1
- 2
运行后有君子协议,修改君子协议
# 在settings.py中注释以下
# ROBOTSTXT_OBEY = True
- 1
- 2
1.4 爬取58同城数据
项目结构
scrapy项目的结构
项目名字
项目名字
spiders文件夹(存储的是爬虫文件)
init
自定义的爬虫文件
init
items 定义数据结构的地方,爬取的数据都包含哪些
middleware 中间件 代理
pipelines 管道 用来处理下载的数据
settings 配置文件 robots协议 ua定义等
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
response属性的方法
response.text 获取的是响应的字符串
response.body 获取的是二进制数据
response.xpath 可以直接是xpath方法来解析response中的内容
response.extract() 提取selector对象的data属性值
response.extract_first() 提取的是selector列表的第一个数据
- 1
- 2
- 3
- 4
- 5
代码
import scrapy
class TcSpider(scrapy.Spider):
name = 'tc'
allowed_domains = ['ty.58.com']
start_urls = ['http://ty.58.com/']
def parse(self, response):
print("=================")
# 返回的页面字符串
# content = response.text
# 返回的页面二进制数据
# content = response.body
# 可以直接使用xpath方法解析response中的内容
content = response.xpath("//ul[@class='icoNav']")
print(content)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
1.5 scrapy架构组成
1.6 scrapy工作原理
scrapy爬取汽车之家
import scrapy
class CarSpider(scrapy.Spider):
name = 'car'
allowed_domains = ['https://car.autohome.com.cn/price/brand-15.html']
# 注意如果你的请求是html结尾的,是不需要加/
start_urls = ['https://car.autohome.com.cn/price/brand-15.html']
def parse(self, response):
print("=============")
name_list = response.xpath("//div[@class='main-title']/a/text()")
price_list = response.xpath("//div[@class='main-lever-right']//span/span/text()")
for i in range(len(name_list)):
# <Selector xpath="//div[@class='main-title']/a/text()" data='宝马X3'> 遍历出来是selector形式 extract()可以提取出数据
print(name_list[i].extract(),price_list[i].extract())
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
1.7 scrapy shell
# 进入到scrapy shell的终端,直接在window的终端中输入scrapy shell 域名
# 如果想看到一些高亮或自动补全,那么可以安装ipython pip install ipython
# scrapy shell www.baidu.com
In [3]: response.url
Out[3]: 'http://www.baidu.com'
In [4]: response.status
Out[4]: 200
In [5]: response.xpath("//input[@id='su']/@value")
Out[5]: [<Selector xpath="//input[@id='su']/@value" data='百度一下'>]
In [6]: response.xpath("//input[@id='su']/@value").extract()
Out[6]: ['百度一下']
In [7]: response.xpath("//input[@id='su']/@value").extract_first()
Out[7]: '百度一下'
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
1.8.yield
简要理解:
yield就是 return 返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后(下一行)开始
案例1:当当网
(1)yield(2)管道封装(3)多条管道下载 (4)多页数据下载
实现代码
dangdang.py
import scrapy
from scrapy_dangdang_062.items import ScrapyDangdang062Item
class DangdangSpider(scrapy.Spider):
name = 'dangdang'
# 如果要多页下载的话,那么必须要调整的是allowed_domains的范围,一般情况下只写域名
allowed_domains = ['category.dangdang.com']
start_urls = ['http://category.dangdang.com/cp01.01.01.00.00.00.html']
base_url = 'http://category.dangdang.com/pg'
page = 1
def parse(self, response):
print("========")
# pipelines 下载数据
# items 定义数据结构
# src = response.xpath("//ul[@id='component_59']/li/a/img/@src")
# name = response.xpath("//ul[@id='component_59']/li/a/img/@alt")
# price = response.xpath("//ul[@id='component_59']/li//p[@class='price']/span[1]/text()")
# 所有的selector的对象都可以再次调用xpath方法
li_list = response.xpath("//ul[@id='component_59']/li")
for li in li_list:
# 图片懒加载,所以都是一样的,第一张图片和其他图片不一样,第一张图片得使用src
src = li.xpath("./a/img/@data-original").extract_first()
if src:
src = src
else:
src = li.xpath("./a/img/@src").extract_first()
name = li.xpath("./a/img/@alt").extract_first()
price = li.xpath(".//p[@class='price']/span[1]/text()").extract_first()
book = ScrapyDangdang062Item(src=src, name=name, price=price)
# print(src,name,price)
# 获取一个book就将book交给pipelines, yield相当于return book
# yield是迭代器,将封装的book交给pipelines
yield book
# 每一页的爬取的业务逻辑全都是一样的,所以我们只需要将执行的页的请求再次调用parse方法
# 第一页:http://category.dangdang.com/cp01.01.01.00.00.00.html
# 第二页:http://category.dangdang.com/pg2-cp01.01.01.00.00.00.html
# 第三页:http://category.dangdang.com/pg3-cp01.01.01.00.00.00.html
# 观察规律
if self.page<100:
self.page = self.page+1
url = self.base_url+str(self.page)+'-cp01.01.01.00.00.00.html'
# 怎么去调用parse对象
# scrapy.Request就是scrapy的get方法
# url就是请求地址
# callback就是你要执行的那个函数,注意不要加()
yield scrapy.Request(url=url,callback=self.parse)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
pipelines.py
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
# useful for handling different item types with a single interface
from itemadapter import ItemAdapter
# 如果想使用管道的话,那么就必须在settings中打开管道(打开注释)
# ITEM_PIPELINES = {
# 'scrapy_carhome_060.pipelines.ScrapyCarhome060Pipeline': 300,
# }
class ScrapyDangdang062Pipeline:
# 这样切片编程减少文件处理量,只用开始打开,后面关闭就可,中间切片写入数据
# 在爬虫文件开始前执行的方法
def open_spider(self,spider):
self.fp = open("book.json",'w',encoding='utf-8')
# item就是yield后面的book
def process_item(self, item, spider):
# 以下这种模式不推荐,因为每传递一个对象,那么就打开一个文件,对文件的操作过于频繁
# 下载数据
# (1) write方法必须要写一个字符串,而不能是其他的对象
# (2) w模式,会每一个对象都打开一次文件,覆盖之前的内容,a可以追加文本
# with open("book.json",'a',encoding='utf-8') as fp:
# fp.write(str(item))
# # fp.close()
self.fp.write(str(item))
return item
# 在爬虫文件开始后执行的方法
def close_spider(self,spider):
self.fp.close()
import urllib.request
# 多条管道开启
# (1)定义管道类
# (2)在settings中开启管道(新增一条)
# ITEM_PIPELINES = {
# 'scrapy_dangdang_062.pipelines.DangDangDownloadPipeline': 301
# }
class DangDangDownloadPipeline:
def process_item(self, item, spider):
url = 'http:'+item.get('src')
filename = './book/book'+item.get('name')+'.jpg'
urllib.request.urlretrieve(url=url,filename=filename)
return item
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
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 ScrapyDangdang062Item(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
# 通俗的说就是你要下载的数据都有什么
# 图片
src = scrapy.Field()
# 图书名
name = scrapy.Field()
# 价格
price = scrapy.Field()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
settings.py
ITEM_PIPELINES = {
'scrapy_dangdang_062.pipelines.ScrapyDangdang062Pipeline': 300,
'scrapy_dangdang_062.pipelines.DangDangDownloadPipeline': 301
}
- 1
- 2
- 3
- 4
案例2:电影天堂
mv.py
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
# useful for handling different item types with a single interface
import urllib.request
from itemadapter import ItemAdapter
class ScrapyMovie063Pipeline:
def open_spider(self,spider):
self.fp = open('movie.json','w',encoding='utf-8')
def process_item(self, item, spider):
self.fp.write(str(item))
# 下载图片
url = item.get('src')
filename = './movies/'+str(item.get('name'))+'.jpg'
urllib.request.urlretrieve(url=url,filename=filename)
return item
def close_spider(self, spider):
self.fp.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
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 ScrapyMovie063Item(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
name = scrapy.Field()
src = scrapy.Field()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
pipelines.py
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
# useful for handling different item types with a single interface
import urllib.request
from itemadapter import ItemAdapter
class ScrapyMovie063Pipeline:
def open_spider(self,spider):
self.fp = open('movie.json','w',encoding='utf-8')
def process_item(self, item, spider):
self.fp.write(str(item))
# 下载图片
url = item.get('src')
filename = './movies/'+str(item.get('name'))+'.jpg'
urllib.request.urlretrieve(url=url,filename=filename)
return item
def close_spider(self, spider):
self.fp.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
1.9 CrawlSpider
链接提取器,继承自scrapy.Spider
- 独门秘笈
CrawlSpider可以定义规则,再解析html内容的时候,可以根据链接规则提取出指定的链接,然后再向这些链接发送请求
所以,如果有需要跟进链接的需求,意思就是爬取了网页之后,需要提取链接再次爬取,使用CrawlSpider是非常合适的 - 提取链接
模拟使用
- 提取连接
from scrapy.linkextractors import LinkExtractor
# 提取符合正则的链接
link = LinkExtractor(allow = r'/book/1188_\d+\.html')
link.extract_links(response)
# 提取符合xpath规则的链接
- 1
- 2
- 3
- 4
- 5
- 6
- 7
注意事项
【注1】callback只能写函数名字符串,不需要写圈函数带上(), callback=‘parse_item’
【注2】在基本的spider中,如果重新发送请求,那里的callback写的是callback=self.parse_item
【注‐‐稍后看】follow=true 是否跟进 就是按照提取连接规则进行提取
运行原理
crawlSpider案例
需求:读书网数据入库
创建项目
scrapy startproject scrapy_readbook_064
- 1
创建爬虫类
scrapy genspider -t crawl read https://www.dushu.com/book/1090.html
- 1
实现代码
read.py
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from scrapy_readbook_064.items import ScrapyReadbook064Item
class ReadSpider(CrawlSpider):
name = 'read'
allowed_domains = ['www.dushu.com']
start_urls = ['https://www.dushu.com/book/1188.html']
rules = (
# \是转义符,\d是数字占位符
Rule(LinkExtractor(allow=r'/book/1188_\d+\.html'),
callback='parse_item',
follow=False),
)
def parse_item(self, response):
item = {}
print("================")
img_list = response.xpath("//div[@class='bookslist']//img")
for img in img_list:
name = img.xpath("./@alt").extract_first()
src = img.xpath('./@data-original').extract_first()
book = ScrapyReadbook064Item(name=name,src=src)
yield book
return item
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
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 ScrapyReadbook064Item(scrapy.Item):
# define the fields for your item here like:
name = scrapy.Field()
src = scrapy.Field()
pass
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
pipelines.py
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
# useful for handling different item types with a single interface
from itemadapter import ItemAdapter
class ScrapyReadbook064Pipeline:
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()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
代码实现
read.py
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from scrapy_readbook_064.items import ScrapyReadbook064Item
class ReadSpider(CrawlSpider):
name = 'read'
allowed_domains = ['www.dushu.com']
# 第一页与其他页不一样,所以需要_1
start_urls = ['https://www.dushu.com/book/1188_1.html']
rules = (
# \是转义符,\d是数字占位符
Rule(LinkExtractor(allow=r'/book/1188_\d+\.html'),
callback='parse_item',
# follow=True是否跟进,就三种提取连接规则进行提取
follow=True),
)
def parse_item(self, response):
item = {}
print("================")
img_list = response.xpath("//div[@class='bookslist']//img")
for img in img_list:
name = img.xpath("./@alt").extract_first()
src = img.xpath('./@data-original').extract_first()
book = ScrapyReadbook064Item(name=name,src=src)
yield book
return item
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
settings.py
DB_HOST = 'localhost'
# 端口号是一个整数
DB_PORT = 3306
DB_USER = 'root'
DB_PASSWORD = '123456'
DB_NAME = 'spider01'
# utf-8的杠不允许写
DB_CHARSET = 'utf8'
ITEM_PIPELINES = {
'scrapy_readbook_064.pipelines.ScrapyReadbook064Pipeline': 300,
"scrapy_readbook_064.pipelines.MysqlPipeline" : 301
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
pipelines.py
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
# useful for handling different item types with a single interface
from itemadapter import ItemAdapter
class ScrapyReadbook064Pipeline:
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()
# 加载settings文件
from scrapy.utils.project import get_project_settings
# 导入pymysql
import pymysql
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_PASSWORD']
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,
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['src'])
# 执行sql语句
self.cursor.execute(sql)
self.conn.commit()
return item
def close_spider(self,spider):
self.cursor.close()
self.conn.close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
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 ScrapyReadbook064Item(scrapy.Item):
# define the fields for your item here like:
name = scrapy.Field()
src = scrapy.Field()
pass
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
1.10 日志信息以及日志级别
# 指定日志级别
LOG_LEVEL = 'WARNING'
# 会给出日志文件
LOG_FILE = 'logdemo.log'
- 1
- 2
- 3
- 4