爬虫学习笔记-python基础+urllib

一、Python基础知识回顾

1、pip下载源

pip install python包默认是从 https://files.pythonhosted.org/ 网站(国外网站)上下载,故速度偏慢。
pip install python包 -i 国内源地址中国科技大学:https://pypi.mirrors.ustc.edu.cn/simple/
阿里云: http://mirrors.aliyun.com/pypi/simple/
豆瓣:http://pypi.douban.com/simple/
清华:https://pypi.tuna.tsinghua.edu.cn/simple/

2、pycharm设置作者信息

在这里插入图片描述
在这里插入图片描述

3、python注释

# 单行

'''
多行
'''

4、变量

  • 变量即是可以变化的量,可以随时进行修改。
  • 程序就是用来处理数据的,而变量就是用来存储数据的
    在这里插入图片描述

4.1 类型转换

函数说明
int(x)转换为整数
float(x)转换为浮点数
str(x)转换为字符串
bool(x)转换为布尔值
  • 转换为整数
print(int('123'))   # 123  字符串转换为整数
print(int(123.78))   # 123  浮点型转换为整数,没有四舍五入,只取整数部分
print(int(True))   # 1  布尔型转换为整数,True为1,False为0

# 以下两种转换失败的情况
print(int('123.78'))   # 浮点型字符串不能转为整数
print(int('12ab'))   # 含非法字符转换失败
  • 转换为浮点数
f1 = float('12.34')
print(f1)  # 12.34
print(type(f1))  # <class 'float'> 将浮点型字符串转换成浮点型

f2 = float(12)
print(f2)  # 12.0
print(type(f2))  # <class 'float'> 将整数转换成浮点型
  • 转换为字符串
print(str(45))  # 45 将整数转换为字符串
print(str(34.56))  # 34.56 将浮点型转换为字符串
print(str(True))  # True 将布尔型转换为字符串
  • 转换为布尔型
# 1、整数转布尔值,非0的为True,0为False
print(bool(-1))  # True
print(bool(1))  # True
print(bool(0))  # False

# 2、浮点型转布尔值,和整数一样
print(bool(-1.0))  # True
print(bool(1.0))  # True
print(bool(0.0))  # False

# 3、字符串(列表、元祖、字典)转布尔值,只要有内容就是True
print(bool('  '))  # True
print(bool('xx'))  # True
print(bool(''))  # False

# 4、总结为False的情况
print(bool(0))
print(bool(0.0))
print(bool(''))
print(bool(""))
print(bool([]))
print(bool(()))
print(bool({}))

4.2 字符串函数

find函数

find查找指定内容在字符串中是否存在,如果存在就返回该内容在字符串中第一次出现的开始位置索引值,如果不存在,则返回-1.

s1 = 'china'
print(s1.find('a'))  # 4
startswith和endswith函数

判断字符串是不是以谁谁谁开头/结尾。

s1 = 'china'
print(s1.startswith('a'))  # False
print(s1.endswith('a'))  # True
replace函数

替换字符串中指定的内容,如果指定次数count,则替换不会超过count次。

s1 = 'cccdd'
print(s1.replace('c','d'))  # ddddd
print(s1.replace('c','d',2))  # ddcdd
split函数

通过参数的内容切割字符串,且输出列表的形式。

s1 = '1#2#3#4#'
print(s1.split('#'))  # ['1', '2', '3', '4', '']
print(s1.split('2'))  # ['1#', '#3#4#']
print(s1.split('1'))  # ['', '#2#3#4#']
strip函数:去空格
s1 = '   a    '
print(len(s1))  # 8
print(s1.strip())  # a
print(len(s1.strip()))  # 1
join函数

. join():将序列(也就是字符串、元组、列表、字典)中的元素以指定的字符连接生成一个新的字符串

# 字符串
b='i love china !'
print(' '.join(b))  # i   l o v e   c h i n a   !
print('-'.join(b)) # i- -l-o-v-e- -c-h-i-n-a- -!
print('*'.join(b))  # i* *l*o*v*e* *c*h*i*n*a* *!

# 列表
a=['i','love','china','!']
print(' '.join(a))  # i love china !
print('-'.join(a)) # i-love-china-!
print('*'.join(a))  # i*love*china*!

# 元组
a=('i','love','china','!')
print(' '.join(a))  # i love china !
print('-'.join(a)) # i-love-china-!
print('*'.join(a))  # i*love*china*!

# 字典
d={"i":11,"love":54,"china!":25}
print(' '.join(d))  # i love china!
print('-'.join(d)) # i-love-china!

os.path.join():将多个路径进行拼接。或者称之为合并目录。

import os
filedir = os.path.join('/home/ubuntu/a/','b/c/','d')
print(filedir)  # /home/ubuntu/a/b/c/d

4.3 列表的增删改查

4.3.1 添加元素
append函数

末尾直接添加,不用重新赋值之类的

q=['xm','xh','xh']
temp=input('请输入新的学生姓名:')  # xz
print(q)   # ['xm', 'xh', 'xh']
q.append(temp)
print(q)  # ['xm', 'xh', 'xh', 'xz']
insert函数

在指定位置插入元素

q=['xm','xh','xl']
q.insert(2,'xz')
print(q)  # ['xm', 'xh', 'xz', 'xl']
extend函数

合并两个列表,通过extend可以将另一个列表中的元素逐一添加到列表中

q=['xm','xh','xl']
b=['a','b','c']
q.extend(b)
print(q)  # ['xm', 'xh', 'xl', 'a', 'b', 'c']
print(b)  # ['a','b','c']
4.3.2 修改元素

通过下标赋值替换原来的元素为新的元素

q=['xm','xh','xl']
q[2]='xz'
print(q)  # ['xm', 'xh', 'xz']
4.3.3 查找元素

所谓的查找,就是看看指定的元素是否存在,主要是in 和 not in。

  • in(存在),如果存在那么结果为true,否则为false
  • not in(不存在),如果不存在那么结果为true,否则false
list=['锅巴肉','大乱炖','红烧鱼']
food = input('请输入你想吃的食物:')  # 糖醋里脊
if food in list:
    print("有")
else:
    print("没有")

if food not in list:
    print("没有")
else:
    print("有")
4.3.4 删除元素

列表元素的常用删除方法有:

  • del:根据下标进行删除
  • pop:删除最后一个元素
  • remove:根据元素的值进行删除
# del
a=[1,2,3,4]
del a[2]
print(a)  # [1, 2, 4]
# pop
a=[1,2,3,4]
a.pop()
print(a)  # [1, 2, 3]
# remove
a=[1,2,3,4]
a.remove(2)
print(a)   # [1, 3, 4]

4.4 元组无法修改

定义只有一个元素的元组,需要在唯一的元素后写一个逗号

a=(11)
print(a,type(a))  # 11 <class 'int'>
b=(11,)
print(b,type(b))  # (11,) <class 'tuple'>

4.5 切片(适用于字符串、列表和元组)

  • 索引是通过下标取某一个元素
  • 切片是通过下标取某一段元素
s = 'hello world!'
print(s[4])  # o
print(s[3:7])  # lo w  左包右不包
print(s[1:])  # ello world!
print(s[:4])  # hell
print(s[1:8:2])  # el o

s= ['1','2','3','4']
print(s[1])  # 2
print(s[1:])  # ['2', '3', '4']
print(s[1:3]) # ['2', '3']

4.6 字典

4.6.1 获取value的方法
# 通过key获取value的方法:
# 使用[]的方法当字典中不存在key的时候,会发生异常
person = {'name':'张三','age':28}
print(person['name'])  # 张三
print(person['age'])   # 28
print(person['sex'])   # KeyError: 'sex'

# 不能使用.字典的方式来访问value
print(person.name)  # AttributeError: 'dict' object has no attribute 'name'

# 使用.get的方式时,如果key不存在返回none
print(person.get('name'))  # 张三
print(person.get('age'))   # 28
print(person.get('sex'))   # none
4.6.2 修改和增加字典
# 修改
person = {'name':'张三','age':28}
person['name'] = '李四'
print(person)  # {'name': '李四', 'age': 28}

# 添加
# 上面的方法如果key存在就是修改,不存在就是增加
person = {'name':'张三','age':28}
person['sex'] = '男'
print(person)  # {'name': '张三', 'age': 28, 'sex': '男'}
4.6.3 删除
  • del:删除字典中指定的某一个元素;或删除整个字典
  • clear:清空字典 但是保留字典对象
# del
# 删除指定元素
person = {'name':'张三','age':28}
del person['age']
print(person)  # {'name': '张三'}
# 删除整个字典
person = {'name':'张三','age':28}
del person
# print(person)   NameError: name 'person' is not defined


# clear
# 清空字典,但是保留字典对象
person = {'name':'张三','age':28}
person.clear()
print(person)   # {}
4.6.4 遍历字典的key和Value
person = {'name':'张三','age':28}

for key in person.keys():
    print(key)
# name
# age

for value in person.values():
    print(value)
# 张三
# 28

for key,value in person.items():
    print(key,value)
# name 张三
# age 28

for item in person.items():
    print(item)
    print(type(item))
'''
('name', '张三')
<class 'tuple'>
('age', 28)
<class 'tuple'>
'''

5、运算符

5.1 算术运算符

在这里插入图片描述
算术运算符在字符串中的应用:

# 如果是两个字符串做加法运算,会直接把这两个字符串拼接成一个字符串。(数字+字符串会报错)
str1 = 'hello'
str2 = 'world'
print(str1+str2)  # helloworld

# 如果是数字和字符串做乘法运算,会将这个字符串重复多次。
str1 = 'hello'
print(str1*10)  # hellohellohellohellohellohellohellohellohellohello

5.2 比较运算符

在这里插入图片描述

5.3 逻辑运算符

  • and:只要有一个运算数是False,结果就是False;只有所有的运算数都为True时,结果才是True。
  • or:只要有一个运算数是True,结果就是True;只有所有的运算数都为False时,结果才是False。
  • not:布尔"非" - 如果 x 为 True,返回 False 。如果 x 为False,它返回 True。

6、输入与输出

# 输出
# 普通输出
print('故事里的小黄花,从出生那年就飘着')
# 格式化输出
# scrapy框架的时候
age = 18
name = '红浪漫晶哥'
# %s 代表的是字符串    %d 代表的是数值
print('我的名字是%s,我的年龄是%d' % (name,age))

# 输入
'''
 - input()的小括号中放入的是提示信息,用来在获取数据之前给用户的一个简单提示
 - input()在从键盘获取了数据以后,会存放到等号左边的变量中 
 - input()会把用户输入的任何值都作为字符串来对待
'''
name = input('请输入您的名字')
print('我的名字是:%s' % name)

7、 流程控制语句

if判断语句

当满足一定条件时才会执行代码块语句,否则就不执行代码块语句。

在这里插入图片描述

if-else判断语句

在这里插入图片描述

if-elif判断语句

  • 当xxx1满足时,执行事情1,然后整个if结束
  • 当xxx1不满足时,那么判断xxx2,如果xxx2满足,则执行事情2,然后整个if结束
  • 当xxx1不满足时,xxx2也不满足,如果xxx3满足,则执行事情3,然后整个if结束
    在这里插入图片描述
score = int(input('请输入您的成绩'))

if score >= 90:
    print('优秀')
elif score >= 80:
    print('良好')
elif score >= 70:
    print('中等')
elif score >= 60:
    print('及格')
else:
    print('不及格')

for循环

在这里插入图片描述

8、函数

8.1 定义和调用函数

# 定义函数
def f1():
    print('xxxx1')
    print('xxxx2')

# 调用函数
f1()   # xxxx1  xxxx2

8.2 形参和实参

  • 定义函数的时候 sum(a,b) 我们称a 和 b 为形式参数 简称形参
  • 调用函数的时候 sum(1,2) 我们称1 和 2 为实际参数 简称实参
# 定义函数
def sum(a,b):
    c=a+b
    print(c)

# 按照位置一一对应关系来传递参数
sum(100,200)  # 300
# 关键字传参
sum(b = 200,a = 100)  # 300

8.3 局部变量和全局变量

局部变量:就是在函数内部定义的变量,其作用范围是这个函数内部,即只能在这个函数中使用,在函数的外部是不能使用的。
在这里插入图片描述
全局变量:如果一个变量,既能在一个函数中使用,也能在其他的函数中使用,这样的变量就是全局变量。在函数外边定义的变量叫做全局变量,全局变量能够在所有的函数中进行访问。
在这里插入图片描述

9、文件的读写

参数说明
r只读,文件不存在,报错。
w只用于写入,文件存在,清空后重新写入,不存在,创建后写入。
a追加,存在就在原本基础上向后追加写入,不存在,创建后写入。
r+读写,存在就在前面进行改写,写入几个就覆盖之前的结果,不存在报错。
W+读写,文件存在,清空后重新写入,不存在,创建后写入,比w多了读的功能。
a+读写,存在就在原本基础上向后追加写入,不存在,创建后写入。多了读。
rb
wb
ab
rb+
Wb+
ab+
和上面一样,就是加了二进制的打开方式。

运行:

f = open('test.txt','w')
f.write('hello world,i am here\n'*5)
f.close()

生成test.txt
在这里插入图片描述
使用read(num)可以从文件中读取数据,num表示要从文件中读取的数据的长度(单位是字节),如果没有传入 num,那么就表示读取文件中所有的数据。

f = open('test.txt','r')
content = f.read(5)  # 最多读5个数据
print(content)

print('-'*30)

content = f.read()  # 从上次读取的位置继续读完剩下的
print(content)

f.close()

在这里插入图片描述
readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行为列表的一个元素。

f = open('test.txt','r')
content = f.readlines()
print(content)
print(type(content))

for temp in content:
    print(temp)

f.close()

在这里插入图片描述

10、序列化和反序列化

文件的写入默认只能是字符串,但是如果是一个对象(例如列表、字典、元组等),就无法直接写入到一个文件里,需要对这个对象进行序列化,反之,从文件的字节序列恢复到内存中,就是反序列化。Python中提供了JSON模块用来实现数据的序列化和反序列化。

10.1 序列化:dump函数

dump方法将对象转换为字符串的同时,指定一个文件对象,把转换后的字符串写入到这个文件里。

import json
f = open('a.txt','w')
names = ['z3','l4','w5','z6']
json.dump(names,f)
f.close()

在这里插入图片描述

10.2 反序列化:load函数

load方法可以将一个JSON字符串反序列化成为一个Python对象。

import json
f = open('a.txt','r')
result = json.load(f)
print(result)  # ['z3', 'l4', 'w5', 'z6']
print(type(result))  # <class 'list'>
f.close()


f = open('a.txt','r')
result = f.read()
print(result)  # ['z3', 'l4', 'w5', 'z6']
print(type(result))  # <class 'str'>
f.close()

二、Urllib使用(python自带)

2.1 使用urllib来获取百度首页的源码

在这里插入图片描述

# 使用urllib来获取百度首页的源码
import urllib.request

# (1)定义一个url  就是你要访问的地址
url = 'http://www.baidu.com'

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

# (3)获取响应中的页面的源码  content 内容的意思
# read方法  返回的是字节形式的二进制数据
# 我们要将二进制的数据转换为字符串
# 二进制--》字符串  解码  decode('编码的格式')
content = response.read().decode('utf-8')

# (4)打印数据
print(content)

在这里插入图片描述在这里插入图片描述

2.2 一个类型和六个方法

  • 一个类型 HTTPResponse
  • 六个方法 read readline readlines getcode geturl getheaders
import urllib.request

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

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

# 一个类型和六个方法
# response是HTTPResponse的类型
print(type(response))   # <class 'http.client.HTTPResponse'>

# read:按照一个字节一个字节的去读
content = response.read()
print(content)

# 指定返回多少个字节
content = response.read(5)
print(content)

# readline:读取一行
content = response.readline()
print(content)
# 按行读完
content1 = response.readlines()
print(content)

# 返回状态码  如果是200了 那么就证明我们的逻辑没有错
print(response.getcode())

# 返回的是url地址
print(response.geturl())

# 获取是一个状态信息
print(response.getheaders())

2.3 urlretrieve下载网页/图片/视频

import urllib.request

# 下载网页
url_page = 'http://www.baidu.com'
# url代表的是下载的路径  filename文件的名字
urllib.request.urlretrieve(url_page,'baidu.html')

# 下载图片
url_img = 'https://img1.baidu.com/it/u=3004965690,4089234593&fm=26&fmt=auto&gp=0.jpg'
urllib.request.urlretrieve(url= url_img,filename='lisa.jpg')

# 下载视频
url_video = 'https://vd3.bdstatic.com/mda-'
urllib.request.urlretrieve(url_video,'syz.mp4')

在这里插入图片描述

2.4 请求对象的定制

UA介绍:User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本。浏览器内核、浏览器渲染引擎、浏览器语言、浏览器插件等
语法:request = urllib.request.Request()
在这里插入图片描述

import urllib.request
url = 'https://www.baidu.com'
headers = {
    'User-Agent': ' Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Mobile Safari/537.36'
}

# 因为urlopen方法中不能存储字典 所以headers不能传递进去
# 因此,先用request请求对象的定制,然后再urlopen请求
request = urllib.request.Request(url=url,headers=headers)
response = urllib.request.urlopen(request)
content = response.read().decode('utf8')
print(content)

2.5 编解码

Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。

  • get请求方式的参数必须编码,参数是拼接到url后面,编码之后不需要调用encode方法
  • post请求方式的参数必须编码,参数是放在请求对象定制的方法中,编码之后需要调用encode方法

2.5.1 get请求方式:urllib.parse.quote()

在这里插入图片描述
将百度搜索的“周杰伦”网址粘贴到pycharm会自动解码成 https://www.baidu.com/s?wd=%E5%91%A8%E6%9D%B0%E4%BC%A6,原理就是urllib.parse.quote方法将中文解码成对应的unicode编码。

# 百度搜索获取周杰伦的网页信息
import urllib.request
import urllib.parse

url = 'https://www.baidu.com/s?wd='

# 请求对象的定制为了解决反爬的第一种手段
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}

# 将周杰伦三个字变成unicode编码的格式
# 我们需要依赖于urllib.parse
name = urllib.parse.quote('周杰伦')
print(name)  # %E5%91%A8%E6%9D%B0%E4%BC%A6
url = url + name  # 解码后完整的地址
print(url)  # https://www.baidu.com/s?wd=%E5%91%A8%E6%9D%B0%E4%BC%A6

# 请求对象的定制
request = urllib.request.Request(url=url,headers=headers)
# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)
# 获取响应的内容
content = response.read().decode('utf-8')
# 打印数据
print(content)

2.5.2 get请求方式:urllib.parse.urlencode()

现实浏览器输入周杰伦,其实后面还有好多编码参数,因此还要将更多的筛选条件变成unicode字符。因此使用urllib.parse.urlencode()解决多参数的问题。
在这里插入图片描述

2.5.3 post请求实现百度翻译功能

图1 寻找url
图2 寻找翻译功能
import urllib.request
import urllib.parse

# 耐心寻找符合条件的网址
url = 'https://fanyi.baidu.com/sug'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}

data = {
    'kw':'spider'
}

# post请求的参数 必须要进行编码,编码后还需调用encode
data = urllib.parse.urlencode(data).encode('utf-8')

# post的请求的参数 是不会拼接在url的后面的  而是需要放在请求对象定制的参数中
request = urllib.request.Request(url=url,data=data,headers=headers)

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

# 获取响应的数据
content = response.read().decode('utf-8')
print(content)  # 输出字符串的编码:{"errno":0,"data":[{"k":"spider","v":"n. \u8718\u86db; \u661f\u5f6
# 字符串--》json对象
import json
obj = json.loads(content)
print(obj)  
# {'errno': 0, 'data': [{'k': 'spider', 'v': 'n. 蜘蛛; 星形轮,十字叉; 带柄三脚平底锅; 三脚架'},

2.5.4 post请求实现百度详细翻译功能

找到:v2transapi?from
在这里插入图片描述
head需要全部导出且注释掉编码,其中cookie有决定作用:

import urllib.request
import urllib.parse

url = 'https://fanyi.baidu.com/v2transapi?from=en&to=zh'

# 对应网页上的内容,需要将Accept-Encodin注释掉,因为我们用的是utf-8
headers = {
    'Accept': '*/*',
    # 'Accept-Encoding': 'gzip, deflate, br',
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'Connection': 'keep-alive',
    'Content-Length': '135',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'Cookie': 'BIDUPSID=DAA8F9F0BD801A2929D96D69CF7EBF50; PSTM=1597202227; BAIDUID=DAA8F9F0BD801A29B2813502000BF8E9:SL=0:NR=10:FG=1; __yjs_duid=1_c19765bd685fa6fa12c2853fc392f8db1618999058029; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; BDUSS=R2bEZvTjFCNHQxdUV-cTZ-MzZrSGxhbUYwSkRkUWk2SkxxS3E2M2lqaFRLUlJoRVFBQUFBJCQAAAAAAAAAAAEAAAA3e~BTveK-9sHLZGF5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFOc7GBTnOxgaW; BDUSS_BFESS=R2bEZvTjFCNHQxdUV-cTZ-MzZrSGxhbUYwSkRkUWk2SkxxS3E2M2lqaFRLUlJoRVFBQUFBJCQAAAAAAAAAAAEAAAA3e~BTveK-9sHLZGF5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFOc7GBTnOxgaW; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BAIDUID_BFESS=DAA8F9F0BD801A29B2813502000BF8E9:SL=0:NR=10:FG=1; BDRCVFR[feWj1Vr5u3D]=I67x6TjHwwYf0; PSINO=2; H_PS_PSSID=34435_31660_34405_34004_34073_34092_26350_34426_34323_22158_34390; delPer=1; BA_HECTOR=8185a12020018421b61gi6ka20q; BCLID=10943521300863382545; BDSFRCVID=boDOJexroG0YyvRHKn7hh7zlD_weG7bTDYLEOwXPsp3LGJLVJeC6EG0Pts1-dEu-EHtdogKK0mOTHv8F_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF=tR3aQ5rtKRTffjrnhPF3-44vXP6-hnjy3bRkX4Q4Wpv_Mnndjn6SQh4Wbttf5q3RymJ42-39LPO2hpRjyxv4y4Ldj4oxJpOJ-bCL0p5aHl51fbbvbURvD-ug3-7qqU5dtjTO2bc_5KnlfMQ_bf--QfbQ0hOhqP-jBRIE3-oJqC8hMIt43f; BCLID_BFESS=10943521300863382545; BDSFRCVID_BFESS=boDOJexroG0YyvRHKn7hh7zlD_weG7bTDYLEOwXPsp3LGJLVJeC6EG0Pts1-dEu-EHtdogKK0mOTHv8F_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF_BFESS=tR3aQ5rtKRTffjrnhPF3-44vXP6-hnjy3bRkX4Q4Wpv_Mnndjn6SQh4Wbttf5q3RymJ42-39LPO2hpRjyxv4y4Ldj4oxJpOJ-bCL0p5aHl51fbbvbURvD-ug3-7qqU5dtjTO2bc_5KnlfMQ_bf--QfbQ0hOhqP-jBRIE3-oJqC8hMIt43f; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1629701482,1629702031,1629702343,1629704515; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1629704515; __yjs_st=2_MDBkZDdkNzg4YzYyZGU2NTM5NzBjZmQ0OTZiMWRmZGUxM2QwYzkwZTc2NTZmMmIxNDJkYzk4NzU1ZDUzN2U3Yjc4ZTJmYjE1YTUzMTljYWFkMWUwYmVmZGEzNmZjN2FlY2M3NDAzOThhZTY5NzI0MjVkMmQ0NWU3MWE1YTJmNGE5NDBhYjVlOWY3MTFiMWNjYTVhYWI0YThlMDVjODBkNWU2NjMwMzY2MjFhZDNkMzVhNGMzMGZkMWY2NjU5YzkxMDk3NTEzODJiZWUyMjEyYTk5YzY4ODUyYzNjZTJjMGM5MzhhMWE5YjU3NTM3NWZiOWQxNmU3MDVkODExYzFjN183XzliY2RhYjgz; ab_sr=1.0.1_ZTc2ZDFkMTU5ZTM0ZTM4MWVlNDU2MGEzYTM4MzZiY2I2MDIxNzY1Nzc1OWZjZGNiZWRhYjU5ZjYwZmNjMTE2ZjIzNmQxMTdiMzIzYTgzZjVjMTY0ZjM1YjMwZTdjMjhiNDRmN2QzMjMwNWRhZmUxYTJjZjZhNTViMGM2ODFlYjE5YTlmMWRjZDAwZGFmMDY4ZTFlNGJiZjU5YzE1MGIxN2FiYTU3NDgzZmI4MDdhMDM5NTQ0MjQxNDBiNzdhMDdl',
    'Host': 'fanyi.baidu.com',
    'Origin': 'https://fanyi.baidu.com',
    'Referer': 'https://fanyi.baidu.com/?aldtype=16047',
    'sec-ch-ua': '"Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"',
    'sec-ch-ua-mobile': '?0',
    '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/92.0.4515.159 Safari/537.36',
    'X-Requested-With': 'XMLHttpRequest',
}

# 对应网页上的内容
data = {
    'from': 'en',
    'to': 'zh',
    'query': 'love',
    'transtype': 'realtime',
    'simple_means_flag': '3',
    'sign': '198772.518981',
    'tk': '5483bfa652979b41f9c90d91f3de875d',
    'domain': 'common',
}
# post请求的参数  必须进行编码 并且要调用encode方法
data = urllib.parse.urlencode(data).encode('utf-8')
# 请求对象的定制
request = urllib.request.Request(url = url,data = data,headers = headers)
# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)
# 获取响应的数据
content = response.read().decode('utf-8')

import json
obj = json.loads(content)
print(obj)

2.6 ajax的get请求

alt+ctrl+l :自动分行
案例:爬取豆瓣电影动作类排行榜第一页
在这里插入图片描述
检查-找到top_list?type=5&interv

图1 寻找包含页面信息的链接
图2 获取URL,利用GET请求
import urllib.request

url = 'https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&start=0&limit=20'

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36'
}

# (1) 请求对象的定制
request = urllib.request.Request(url=url,headers=headers)

# (2)获取响应的数据
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')
# print(content)

# (3) 数据下载到本地,生成douban1.json文件
# open方法默认情况下使用的是gbk的编码  如果我们要想保存汉字 那么需要在open方法中指定编码格式为utf-8
# encoding = 'utf-8'
# fp = open('douban.json','w',encoding='utf-8')
# fp.write(content)

with open('douban1.json','w',encoding='utf-8') as fp:
    fp.write(content)

案例:爬取豆瓣电影动作类排行榜前10页–利用ajax

'''
观察总结规律:

第一页:https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&start=0&limit=20
第二页:https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&start=20&limit=20
第三页:https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&start=40&limit=20

page    1  2   3   4
start   0  20  40  60
limit  20  20  20  20

start =(page - 1)*20
'''

# 下载豆瓣电影1-10页的数据

import urllib.request
import urllib.parse

# (1) 请求对象的定制:request
def creat_request(page):
    base_url = 'https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&'
    # get请求参数方式,后面不需要加encode
    data = {
        'start': (page - 1) * 20,
        'limit': 20
    }
    data = urllib.parse.urlencode(data)  # start=0&limit=20
    url = base_url + data
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
    }
    request = urllib.request.Request(url=url,headers=headers)
    return request

# (2) 获取响应的数据 content
def get_content(request):
    response = urllib.request.urlopen(request)
    content =  response.read().decode('utf-8')
    return content

# (3)下载
def down_load(page,content):
    with open('douban'+ str(page) +'.json', 'w', encoding='utf-8') as fp:
        fp.write(content)

# 1、程序入口
if __name__ == '__main__':
    start_page = int(input('起始页码:'))  # 1
    end_page = int(input('结束页码:'))   # 10

    for page in range(start_page,end_page+1):
        # 1.1 请求对象的定制(每一页) request
        request = creat_request(page)

        # 1.2 获取响应的数据 content
        content = get_content(request)

        # 1.3 下载
        down_load(page,content)

2.7 ajax的post请求

案例:KFC官网北京地区前10页餐厅地址

图1 寻找包含页面信息的接口
图2 获取URL,利用post请求
图3 获取post的相关data参数
'''
规律:
第1页:
http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname
cname: 北京
pid:
pageIndex: 1
pageSize: 10

第2页:
http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname
cname: 北京
pid:
pageIndex: 2
pageSize: 10
'''

import urllib.request
import urllib.parse

def create_request(page):
    base_url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname'
    data = {
        'cname': '北京',
        'pid':'',
        'pageIndex': page,
        'pageSize': '10'
    }
    data = urllib.parse.urlencode(data).encode('utf-8')
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
    }
    request = urllib.request.Request(url=base_url, headers=headers, data=data)
    return request

def get_content(request):
    response = urllib.request.urlopen(request)
    content = response.read().decode('utf-8')
    return content

def down_load(page,content):
    with open('kfc_' + str(page) + '.json','w',encoding='utf-8') as fp:
        fp.write(content)

if __name__ == '__main__':
    start_page = int(input('开始页码:'))
    end_page = int(input('结束页码:'))

    for page in range(start_page,end_page+1):
        # 请求对象定制
        request = create_request(page)
        # 响应
        content = get_content(request)
        # 下载
        down_load(page,content)

2.8 cookie登录

在这里插入图片描述

'''
适用的场景:数据采集的时候 需要绕过登陆 然后进入到某个页面

思路:请求头信息补充,将header中的信息都放进去,其中cookie起决定性因素,还有referer不同网站也会定期验证
'''


import urllib.request

url = 'https://weibo.cn/6451491586/info'

headers = {
    # ':authority': 'weibo.cn',
    # ':method': 'GET',
    # ':path': '/6451491586/info',
    # ':scheme': 'https',
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
    # 'accept-encoding': 'gzip, deflate, br',
    'accept-language': 'zh-CN,zh;q=0.9',
    'cache-control': 'max-age=0',
    # cookie中携带着你的登陆信息   如果有登陆之后的cookie  那么我们就可以携带着cookie进入到任何页面
    'cookie': '_T_WM=24c44910ba98d188fced94ba0da5960e; SUBP=0033WrSXqPxfM725Ws9jqgMF55529P9D9WFxxfgNNUmXi4YiaYZKr_J_5NHD95QcSh-pSh.pSKncWs4DqcjiqgSXIgvVPcpD; SUB=_2A25MKKG_DeRhGeBK7lMV-S_JwzqIHXVv0s_3rDV6PUJbktCOLXL2kW1NR6e0UHkCGcyvxTYyKB2OV9aloJJ7mUNz; SSOLoginState=1630327279',
    # referer  判断当前路径是不是由上一个路径进来的    一般情况下 是做图片防盗链
    'referer': 'https://weibo.cn/',
    'sec-ch-ua': '"Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"',
    'sec-ch-ua-mobile': '?0',
    'sec-fetch-dest': 'document',
    'sec-fetch-mode': 'navigate',
    'sec-fetch-site': 'same-origin',
    'sec-fetch-user': '?1',
    'upgrade-insecure-requests': '1',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36',
}
# 请求对象的定制
request = urllib.request.Request(url=url,headers=headers)
# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)
# 获取响应的数据
content = response.read().decode('utf-8')

# 将数据保存到本地
with open('weibo.html','w',encoding='utf-8')as fp:
    fp.write(content)

2.9 handler处理器

虽然用urllib.request.Request(url,headers,data)解决了urllib.request.urlopen(url)不能定制请求头的问题,但是随着业务逻辑的复杂,如每次登陆cookie动态变化和代理动态变化的情况,利用Handler定制更高级的请求头,就不用每次单独定制了。

基本应用:

# 需求 使用handler来访问百度  获取网页源码

import urllib.request

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

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}

request = urllib.request.Request(url = url,headers = headers)

# handler   build_opener  open

# (1)获取hanlder对象
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)

3.0 代理服务器-利用handler

import urllib.request

url = 'http://www.baidu.com/s?wd=ip'

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}

# 1、原始方法
# 请求对象的定制
request = urllib.request.Request(url = url,headers= headers)

# 模拟浏览器访问服务器
response = urllib.request.urlopen(request)

# 获取响应的信息
content = response.read().decode('utf-8')

# 保存
with open('daili1.html','w',encoding='utf-8')as fp:
    fp.write(content)

# 2、Handler方法利用代理ip
# 请求对象的定制
request = urllib.request.Request(url = url,headers= headers)

# 代理ip
proxies = {
    'http':'20.74.169.104:8118'
}
# handler  build_opener  open
handler = urllib.request.ProxyHandler(proxies = proxies)

opener = urllib.request.build_opener(handler)

response = opener.open(request)

# 获取响应的信息
content = response.read().decode('utf-8')

# 保存
with open('daili2.html','w',encoding='utf-8')as fp:
    fp.write(content)

代理池:

# 创建代理池
proxies_pool = [
    {'http':'118.24.219.151:16817'},
    {'http':'118.24.219.151:16817'},
]

import random

proxies = random.choice(proxies_pool)
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Python爬虫教程urllib主要是介绍了Python爬虫技术中的urllib库的基础用法。该教程详细讲解了urllib库的各种功能和方法,包括发送请求、处理响应、设置请求头、处理异常等。这个教程对于想要学习和使用Python进行网络爬虫的人来说具有很大的参考价值。 同时,该教程也提到了一些常见的问题和解决方法,例如模拟超时的处理方法。在网络爬虫中,有时候我们长时间无法访问一个页面,可能是因为网速有限或者被发现我们是一个爬虫。针对这种情况,可以使用timeout参数来设置超时时间,如果超过了设定的时间仍无法获取响应,则会抛出URLError异常,我们可以在异常处理中对超时进行相应的处理。 总的来说,Python爬虫教程urllib是一个很好的学习资源,适合想要入门或深入学习Python爬虫技术的人使用。它提供了详细的教程和实例,可以让你快速上手和掌握使用urllib库进行网络爬虫的基本知识和技巧。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Python爬虫urllib基础用法教程](https://download.csdn.net/download/weixin_38656741/12858843)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Python爬虫 —— urllib库的使用(get/post请求+模拟超时/浏览器)](https://blog.csdn.net/qq_50587771/article/details/123840479)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [python爬虫urllib3的使用示例](https://download.csdn.net/download/weixin_38681147/12867742)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值