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

Python学习

1.pycharm一些常用设置

设置通用代码模板

2.注释

单行注释:#

多行注释: ‘’’ ‘’‘’

3.变量类型

Number(数字) : int(有符号整形)、long(长整型,也可以代表八进制和十六进制)、float(浮点型)、complex(复数)
布尔类型:True、Flase
String(字符串)
List(列表)
Tuple(元祖)
Dictionary(字典)

使用

# 变量类型的基本使用
#  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"])

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))

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)))

6.赋值运算符

d,e,f = 1,2,3
print(d)

7.逻辑运算符

# 逻辑运算符 and:与 or:或 not:非
# and:都成立为True
# or:一个成立为True,两个都不成立为False
# not:逻辑非,成立的为False,不成立的True

8.输入输出

输出

# 普通输出
print("1111")

# 格式化输出
# scrapy框架的时候 excel文件 mysql redis
age = 22
name = '张三'
print("我的年龄是:"+str(age))
# %s 代表着字符串   %d 代表着数值
print("我的名字是:%s,我的年龄是:%d" % (name,age))

输入

# 输入
code = input('请输入验证码:')
print("我的验证码是:%s" %code)

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("不及格")

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))

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'))

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)

2.修改

# 修改
city_list = ['北京','武汉','重庆']
print(city_list)
# 将列表中的元素的值修改
city_list[2] = '大连'
print(city_list)

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('在')

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)

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))

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

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

修改

person2 = {'name':'李四','age':'23'}

# 修改之前的字典
print(person2.get('name'))

# 修改name的值为法外狂徒
person['name'] = '法外狂徒'
print(person['name'])

添加

person3 = {"name":'老大'}
# 如果使用变量名字['键'] = 数据时,这个键如果在字典中不存在 那么就会变成新增元素
person3['age'] = '18'
print(person3['age'])

删除

# 删除
# del
# (1)删除字典中指定的某一个元素
person4 = {'name':"老马",'age':18}
# 删除前
print(person4)
del person4['age']
# 删除后
print(person4)
# (2)删除整个字典
# del person4
# print(person4)
# clear
# (3) 清空字典 但是保留字典对象
person4.clear()
print(person4) # {} 删除整个字典但是不删除结构

遍历

# 遍历
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)

16.函数

函数的定义与调用

# 定义函数
def f():
    print("欢迎")

# 调用函数
f()

函数参数的使用

# 使用函数计算1和2的和
def add(a,b):
    print(a+b)

# 位置参数
add(3,4)
# 关键字传参
add(b = 100,a = 200) 

函数返回值

def add(a,b):
    return a+b

c = add(3,4)
print(c)

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()

文件路径

绝对路径:绝对位置,完整地描述了目标的所在地,所有目录层级关系是一目了然的。

  • 例如:E:\python,从电脑的盘符开始,表示的就是一个绝对路径。

相对路径:是从当前文件所在的文件夹开始的路径。

  • test.txt,是在当前文件查找 test.txt文件
  • ./test.txt,也是当前文件夹中查找 test.txt文件,./表示的是当前文件夹
  • ../test.txt,从当前文件夹的上一级文件夹里查找 test.txt文件。../表示的是上一级文件夹
  • demo/test.txt,在当前文件夹里查找 demo这个文件夹,并在这个文件夹里查找 test.txt文件

Python基础学习--基于尚硅谷python教学视频_第1张图片

文件的读写

# 写数据
# 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)

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)
# 
print(type(content))
# loads 加载字符串
# 反序列化json对象为python对象
result = json.loads(content)
# 转换之后
print(result)
# 
print(type(result))
fp.close()


# load 加载文件
fp = open("demo/test.txt",'r')
content = json.load(fp)
print(content)
print(type(content))

19.异常

try:
可能出现异常的代码
except 异常的类型
友好的提示

try:
    fp=open("demo/s.txt",'r')
    fp.read()
except FileNotFoundError:
    print('系统正在升级,请稍后')

20.Urllib

一、反爬手段
User‐Agent:
User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。
代理IP
西次代理
快代理
什么是高匿名、匿名和透明代理?它们有什么区别?
1.使用透明代理,对方服务器可以知道你使用了代理,并且也知道你的真实IP。
2.使用匿名代理,对方服务器可以知道你使用了代理,但不知道你的真实IP。
3.使用高匿名代理,对方服务器不知道你使用了代理,更不知道你的真实IP。
验证码访问

- 打码平台
- 云打码平台
- 超级
  动态加载网页 网站返回的是js数据 并不是网页的真实数据
  selenium驱动真实的浏览器发送请求
  数据加密
  分析js代码

1.Urllib库的使用

Python基础学习--基于尚硅谷python教学视频_第2张图片

基本使用

# 使用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)

2.一个类型和六个方法

# 一个类型 HTTPResponse
# 六个方法 read()、readline()、readlines()、getcode()、geturl()、getheaders()

import urllib.request

url = "http://www.baidu.com"

# 模拟浏览器向服务器发送请求
resp = urllib.request.urlopen(url)

# 一个类型和六个方法 
# print(type(resp))

# 按照一个字节一个字节读取
# content = resp.read()
# print(content)
# resp.read(数字) 代表返回多少个字节 b'
# 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())

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')

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)

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)

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)

6.Post请求方式

post请求的参数,必须要进行编码
编码之后必须调用encode方法 data = urllib.parse.urlencode(data).encode("utf-8")
参数是放在请求对象定制的方法中 request = urllib.request.Request(url=url,data=data,headers=headers)
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)

百度详细翻译

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)

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()
  • 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)
    

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)
    

9.URLError\HTTPError

Python基础学习--基于尚硅谷python教学视频_第3张图片

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("系统正在升级.....")

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)

11.Handler处理器

Python基础学习--基于尚硅谷python教学视频_第4张图片

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

Python基础学习--基于尚硅谷python教学视频_第5张图片

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()

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)

21.xpath

1.xpath基本使用

Python基础学习--基于尚硅谷python教学视频_第6张图片

# xpath解析
# (1) 本地文件                                                           etree.parse
# (2)服务器响应的数据 resp.read().decode("utf-8")****   使用居多            etree.HTML()
  • 安装lxml库

    pip install lxml ‐i https://pypi.douban.com/simple 
    # 如果没用就换以下
    pip install lxml -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python
    
  • 导入lxml.etree

    from lxml import etree 
    

    Python基础学习--基于尚硅谷python教学视频_第7张图片

  • etree.parse() 解析本地文件

    html页面

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8"/>
        <title>Titletitle>
    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>
    
    # 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))
    
  • 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)           
    

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)

22.JsonPath

pip安装

pip install jsonpath 

jsonpath的使用

obj = json.load(open('json文件', 'r', encoding='utf‐8'))
ret = jsonpath.jsonpath(obj, 'jsonpath语法')

jsonpath与lxml语法对比

Python基础学习--基于尚硅谷python教学视频_第8张图片

数据源

{ "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
    }
  }
}

根据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)

jsonpath与lxml写法对比

Python基础学习--基于尚硅谷python教学视频_第9张图片

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)

23.BeatifulSoup

1.基本简介

Python基础学习--基于尚硅谷python教学视频_第10张图片

2.安装以及创建

Python基础学习--基于尚硅谷python教学视频_第11张图片

3.节点定位

Python基础学习--基于尚硅谷python教学视频_第12张图片

Python基础学习--基于尚硅谷python教学视频_第13张图片

4.节点信息

Python基础学习--基于尚硅谷python教学视频_第14张图片

本地数据

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>Titletitle>
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>

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')) # [张三之家]

# id选择器
# print(soup.select(("#l1"))) # [
  • 张三
  • ]
    # 属性选择器---通过属性来寻找对应标签 # 查找到li标签中有id的标签 # print(soup.select('li[id]')) # [
  • 张三
  • ,
  • 李四
  • ]
    # 查找到li标签中id=l2的标签 # print(soup.select('li[id="l2"]')) # [
  • 李四
  • ]
    # 层级选择器 # 后代选择器 # 找到div下面的li,空格代表后代 # print(soup.select('div li')) # [
  • 张三
  • ,
  • 李四
  • ,
  • 王五
  • ]
    # 子代选择器 # 某标签的第一级子标签 注意:很多编程语言中,如果不加空格不会输出内容,在bs4中不会报错 # print(soup.select('div>ul>li')) # [
  • 张三
  • ,
  • 李四
  • ,
  • 王五
  • ]
    # 找到a标签和li标签的所有对象(优点) # print(soup.select('a,li')) # [
  • 张三
  • ,
  • 李四
  • ,
  • 王五
  • , 张三之家, 李四之家]
    # 节点信息 # 获取节点内容 # 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']

    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())
    

    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)
    
    # 一个类型,六个属性 
    # 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)
    

    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 验证码
    

    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编码
    # 不需要请求对象的定制
    # 请求资源路径中的?可以加也可以不加
    

    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) 不需要请求对象的定制
    

    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)验证码
    

    6.超级鹰打码平台的使用

    25.scrapy

    scrapy是什么

    Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。
    

    安装scrapy

    pip install scrapy
    

    Python基础学习--基于尚硅谷python教学视频_第15张图片

    1.基本使用

    1.1创建scrapy项目

    终端输入 scrapy startproject 项目名称

    1.2项目组成

    Python基础学习--基于尚硅谷python教学视频_第16张图片

    Python基础学习--基于尚硅谷python教学视频_第17张图片

    1.3创建爬虫文件

    跳转到spiders文件夹

    cd 目录名字/目录名字/spiders 
    

    创建爬虫文件.py

    scrapy genspider 爬虫名字 网页的域名
    # 比如
    scrapy genspider baidu www.baidu.com
    

    爬虫文件的基本组成

    Python基础学习--基于尚硅谷python教学视频_第18张图片

    生成的爬虫文件

    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')
    

    运行爬虫代码

    scrapy crawl 爬虫的名字
    eg: scrapy crawl baidu
    

    运行后有君子协议,修改君子协议

    # 在settings.py中注释以下
    # ROBOTSTXT_OBEY = True
    

    1.4 爬取58同城数据

    项目结构

    scrapy项目的结构
    	项目名字
    		项目名字
    			spiders文件夹(存储的是爬虫文件)
    				init
    				自定义的爬虫文件
    			init
    			items 定义数据结构的地方,爬取的数据都包含哪些
    			middleware 中间件 代理
    			pipelines  管道  用来处理下载的数据
    			settings  配置文件  robots协议 ua定义等
    

    response属性的方法

    response.text  获取的是响应的字符串
    response.body  获取的是二进制数据
    response.xpath 可以直接是xpath方法来解析response中的内容
    response.extract()  提取selector对象的data属性值
    response.extract_first() 提取的是selector列表的第一个数据
    

    代码

    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.5 scrapy架构组成

    Python基础学习--基于尚硅谷python教学视频_第19张图片

    1.6 scrapy工作原理

    Python基础学习--基于尚硅谷python教学视频_第20张图片

    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形式 extract()可以提取出数据
                print(name_list[i].extract(),price_list[i].extract())
    

    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.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)
    

    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
    

    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()
    

    settings.py

    ITEM_PIPELINES = {
       'scrapy_dangdang_062.pipelines.ScrapyDangdang062Pipeline': 300,
       'scrapy_dangdang_062.pipelines.DangDangDownloadPipeline': 301
    }
    
    案例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()
    

    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()
    

    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.9 CrawlSpider

    链接提取器,继承自scrapy.Spider

    • 独门秘笈
      CrawlSpider可以定义规则,再解析html内容的时候,可以根据链接规则提取出指定的链接,然后再向这些链接发送请求
      所以,如果有需要跟进链接的需求,意思就是爬取了网页之后,需要提取链接再次爬取,使用CrawlSpider是非常合适的
    • 提取链接

    Python基础学习--基于尚硅谷python教学视频_第21张图片

    模拟使用

    在这里插入图片描述

    • 提取连接
    from scrapy.linkextractors import LinkExtractor
    # 提取符合正则的链接
    link = LinkExtractor(allow = r'/book/1188_\d+\.html')
    link.extract_links(response) 
    
    # 提取符合xpath规则的链接
    
    

    注意事项

    【注1】callback只能写函数名字符串,不需要写圈函数带上(), callback=‘parse_item’
    【注2】在基本的spider中,如果重新发送请求,那里的callback写的是callback=self.parse_item
    【注‐‐稍后看】follow=true 是否跟进 就是按照提取连接规则进行提取
    运行原理

    Python基础学习--基于尚硅谷python教学视频_第22张图片

    crawlSpider案例

    需求读书网数据入库

    创建项目

    scrapy startproject scrapy_readbook_064
    

    创建爬虫类

    scrapy genspider -t crawl read https://www.dushu.com/book/1090.html
    

    实现代码

    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
    

    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
    

    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()
    

    代码实现

    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
    

    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
    }
    

    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()
    

    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.10 日志信息以及日志级别

    Python基础学习--基于尚硅谷python教学视频_第23张图片

    # 指定日志级别
    LOG_LEVEL = 'WARNING'
    # 会给出日志文件
    LOG_FILE = 'logdemo.log'
    

    你可能感兴趣的:(python,学习,开发语言)