2022年 11月 9日

Python基础学习–基于尚硅谷python教学视频

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文件

img

文件的读写

# 写数据
# 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库的使用

img

基本使用

# 使用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处理器

img

# 需求 使用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

img

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.基本简介

img

2.安装以及创建

在这里插入图片描述

3.节点定位

img

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