资料 |
---|
视频:尚硅谷Python爬虫教程小白零基础速通(含python基础+爬虫案例) |
视频笔记:笔记.exe |
视频代码:代码.exe |
视频资源:资源.exe |
一 Python 基础
1.Python 环境的安装
2.pip 的使用
- pip
- 安装
- 配置
- 使用 pip 管理 Python 包
- 修改 pip 下载源
3.运行 Python 程序
4.Python
-
变量以及数据类型
-
函数 说明 int(x) 将 x 转换为一个整数 float(x) 将 x 转换为一个浮点数 str(x) 将对象 x 转换为字符串 bool(x) 将对象 x 转换成为布尔值 - 转换成为整数
print(int("123")) # 123 将字符串转换成为整数 print(int(123.78)) # 123 将浮点数转换成为整数 print(int(True)) # 1 布尔值True转换成为整数是 1 print(int(False)) # 0 布尔值False转换成为整数是 0 # 以下两种情况将会转换失败 ''' 123.456 和 12ab 字符串,都包含非法字符,不能被转换成为整数,会报错 print(int("123.456")) print(int("12ab")) '''
- 转换成为浮点数
f1 = float("12.34") print(f1) # 12.34 print(type(f1)) # float 将字符串的 "12.34" 转换成为浮点数 12.34 f2 = float(23) print(f2) # 23.0 print(type(f2)) # float 将整数转换成为了浮点数
- 转换成为字符串
str1 = str(45) str2 = str(34.56) str3 = str(True) print(type(str1),type(str2),type(str3))
- 转换成为布尔值
''' 除了以下的将强转为 False ,其他的都将会转为 True ''' print(bool('')) print(bool("")) print(bool(0)) print(bool({})) print(bool([])) print(bool(()))
- 转换成为整数
-
-
运算符 描述 实例 + 加 两个对象相加 a + b 输出结果 30 – 减 得到负数或是一个数减去另一个数 a – b 输出结果 -10 * 乘 两个数相乘或是返回一个被重复若干次的字符串 a * b 输出结果 200 / 除 b / a 输出结果 2 // 取整数 返回商的整数部分 9//2 输出结果 4 , 9.0//2.0 输出结果 4.0 % 取余 返回除法的余数 b % a 输出结果 0 ** 指数 a**b 为10的20次方 () 小括号 提高运算优先级,比如: (1+2) * 3 注意:混合运算时,优先级顺序为: ** 高于 * / % // 高于 + – ,为了避免歧义,建议使用 () 来处理运算符优先级。 并且,不同类型的数字在进行混合运算时,整数将会转换成浮点数进行运算
- 如果是两个字符串做加法运算,会直接把这两个字符串拼接成一个字符串
str1 ='hello' str2 = 'world' print(str1+str2) # 'helloworld'
- 如果是数字和字符串做加法运算,会直接报错
str1 = 'hello' a = 2 print(str1+a) ''' Traceback (most recent call last): File "D:我的下载2 代码和电路有关的pythonpyCharmcode1.HelloWordcomxcHelloWord.py", line 3, in <module> print(str1+a) ~~~~^~ TypeError: can only concatenate str (not "int") to str '''
- 如果是数字和字符串做乘法运算,会将这个字符串重复多次
str1 = 'hello' print(str1*10) # hellohellohellohellohellohellohellohellohellohello
- 如果是两个字符串做加法运算,会直接把这两个字符串拼接成一个字符串
-
赋值运算符
运算符 描述 实例 = 赋值运算符 把 = 号右边的结果 赋给 左边的变量,如 num = 1 + 2 * 3,结果num的值为7 # 单个变量赋值 num = 10 print(num) # 10 # 同时为多个变量赋值(使用等号连接) a = b = 4 print(a) # 4 print(b) #4 # 多个变量赋值(使用逗号分隔) num1, f1, str1 = 100, 3.14, "hello" print(num1) # 100 print(f1) # 3.14 print(str1) # hello
-
复合赋值运算符
运算符 描述 实例 += 加法赋值运算符 c += a 等效于 c = c + a -= 减法赋值运算符 c -= a 等效于 c = c – a *= 乘法赋值运算符 c *= a 等效于 c = c * a /= 除法赋值运算符 c /= a 等效于 c = c / a //= 取整除赋值运算符 c //= a 等效于 c = c // a %= 取模赋值运算符 c %= a 等效于 c = c % a **= 幂赋值运算符 c **= a 等效于 c = c ** a # 示例:*=,运算时,符号右侧的表达式先计算出结果,再与左边变量的值运算 a=100 a *= 1+2 print(a) # 300
-
运算符 描述 实例 == 等于:比较对象是否相等 (a==b) 返回 False != 不等于:比较两个对象是否不相等 (a!=b) 返回 True > 大于:返回x是否大于y (a>b) 返回 False >= 大于等于:返回x是否大于等于y (a>=b) 返回 False < 小于:返回x是否小于y。所有比较运算符返回1表示真,返回0表示假。这分别与特殊的变量True和False等价 (a<b) 返回 True <= 小于等于:返回x是否小于等于y (a<=b) 返回 True -
逻辑运算符
运算符 逻辑表达式 描述 实例 and x and y 只要有一个运算数是 False,结果就是 False ;只有所有的运算数都为 True 时结果才是 True ,做取值运算时,取第一个为 False 的值,如果所有的值都为 True ,取最后一个值 True and True and False–>结果为 False ;True and True and True–>结果为 True or x or y 只要有一个运算数是 True ,结果就是 True ;只有所有的运算数都为 False 时,结果才是 False ,做取值运算时,取第一个为 True 的值,如果所有的值都为 False ,取最后一个值 False or False or True–>结果为 True ;False or False or False–>结果为 False not not x 布尔”非” – 如果 x 为 True,返回 False 。如果 x 为 False,它返回 True not True –> False
-
-
- 字符串高级
函数 说明 len len函数可以获取字符串的长度 find 查找指定内容在字符串中是否存在,如果存在就返回该内容在字符串中第一次出现的开始位置索引值,如果不存在,则返回-1 startswith/endswith 判断字符串是不是以谁谁谁开头/结尾 count 返回 str在start和end之间 在 mystr里面出现的次数 replace 替换字符串中指定的内容,如果指定次数count,则替换不会超过count次 split 通过参数的内容切割字符串 upper/lower 将字符串中的大小写互换 strip 去空格 join 字符串拼接 - 列表高级
添加元素- append 会把新元素添加到列表末尾
A = ['xiaoWang','xiaoZhang','xiaoHua'] # A=['xiaoWang', 'xiaoZhang', 'xiaoHua'] print("A=%s" % A) temp = '添加的元素' A.append(temp) # A=['xiaoWang', 'xiaoZhang', 'xiaoHua', '添加的元素'] print("A=%s" % A)
- insert(index, object) 在指定位置 index 前插入元素 object
strs = ['a','b','m','s'] strs.insert(3,'h') print(strs) # ['a', 'b', 'm', 'h', 's']
- 通过 extend 可以将另一个列表中的元素逐一添加到列表中
a = ['a','b','c'] b = ['d','e','f'] a.extend(b) print(a) # ['a', 'b', 'c', 'd', 'e', 'f'] 将 b 添加到 a 里 print(b) # ['d','e','f'] b的内容不变
删除元素
- del:根据下标进行删除
movieName = ['加勒比海盗','骇客帝国','第一滴血','指环王','霍比特人','速度与激情'] # movieName=['加勒比海盗', '骇客帝国', '第一滴血', '指环王', '霍比特人', '速度与激情'] print('movieName=%s' % movieName) del movieName[2] # movieName=['加勒比海盗', '骇客帝国', '指环王', '霍比特人', '速度与激情'] print('movieName=%s' % movieName)
- pop:删除最后一个元素
movieName = ['加勒比海盗','骇客帝国','第一滴血','指环王','霍比特人','速度与激情'] # movieName=['加勒比海盗', '骇客帝国', '第一滴血', '指环王', '霍比特人', '速度与激情'] print('movieName=%s' % movieName) movieName.pop() # movieName=['加勒比海盗', '骇客帝国', '第一滴血', '指环王', '霍比特人'] print('movieName=%s' % movieName)
- remove:根据元素的值进行删除
movieName = ['加勒比海盗','骇客帝国','第一滴血','指环王','霍比特人','速度与激情'] # movieName=['加勒比海盗', '骇客帝国', '第一滴血', '指环王', '霍比特人', '速度与激情'] print('movieName=%s' % movieName) movieName.remove('指环王') # movieName=['加勒比海盗', '骇客帝国', '第一滴血', '霍比特人', '速度与激情'] print('movieName=%s' % movieName)
修改元素
- append 会把新元素添加到列表末尾
- 元组高级
Python 的元组与列表类似,不同之处在于元组的元素不能修改。元组使用小括号,列表使用方括号- 访问元组
tuple=('hello',12,30) print(tuple[0]) # hello
- 修改元组
tuple=('hello',12,30) tuple[0]='world' ''' Traceback (most recent call last): File "D:我的下载2 代码和电路有关的pythonpyCharmcode1.HelloWordcomxcHelloWord.py", line 2, in <module> tuple[0]='world' ~~~~~^^^ TypeError: 'tuple' object does not support item assignment '''
- python中不允许修改元组的数据,包括不能删除其中的元素
- 定义只有一个元素的元组,需要在唯一的元素后写一个逗号
- 访问元组
- 切片
- 切片是指对操作的对象截取其中一部分的操作。字符串、列表、元组都支持切片操作
- 切片的语法:[起始:结束:步长],也可以简化使用 [起始:结束]
- 注意:选取的区间从”起始”位开始,到”结束“位的前一位结束(不包含结束位本身),步长表示选取间隔
# 索引是通过下标取某一个元素 # 切片是通过下标去某一段元素 s = 'Hello World!' print(s) print(s[4]) # o 字符串里的第4个元素 print(s[3:7]) # lo W 包含下标 3,不含下标 7 print(s[1:]) # ello World! 从下标为1开始,取出 后面所有的元素(没有结束位) print(s[:4]) # Hell 从起始位置开始,取到 下标为4的前一个元素(不包括结束位本身) print(s[1:5:2]) # el 从下标为1开始,取到下标为5的前一个元素,步长为2(不包括结束位本身)
- 字典高级
查看元素- 除了使用 key 查找数据,还可以使用 get 来获取数据
info = {'name':'班长','age':18} print(info['age']) # 获取年龄 18 # print(info['sex']) # 获取不存在的key,会发生异常 print(info.get('sex')) # 获取不存在的key,获取到空的内容,不会出现异常,None print(info.get('sex', '男')) # 获取不存在的key, 可以提供一个默认值,返回 男
修改元素
- 字典的每个元素中的数据是可以修改的,只要通过 key 找到,即可修改
info = {'name':'班长', 'id':100} print('修改之前的字典为 %s:' % info) info['id'] = 200 # 为已存在的键赋值就是修改 print('修改之后的字典为 %s:' % info) # 修改之后的字典为 {'name': '班长', 'id': 200}:
添加元素
- 如果在使用 变量名[‘键’] = 数据 时,这个“键”在字典中,不存在,那么就会新增这个元素
info = {'name':'班长'} print('添加之前的字典为:%s' % info) info['id'] = 100 # 为不存在的键赋值就是添加元素 print('添加之后的字典为:%s' % info) # 添加之后的字典为:{'name': '班长', 'id': 100}
删除元素
- del 删除指定的元素
info = {'name':'班长', 'id':100} print('删除前,%s' % info) del info['name'] # del 可以通过键删除字典里的指定元素 print('删除后,%s' % info) # 删除后,{'id': 100}
- del 删除整个字典
info = {'name':'monitor', 'id':100} print('删除前,%s'%info) del info # del 也可以直接删除变量 # 这句打印直接报错 print('删除后,%s'%info)
- clear 清空整个字典
info = {'name':'monitor', 'id':100} print('清空前,%s'%info) info.clear() print('清空后,%s'%info) # 清空后,{}
字典的遍历
- 遍历字典的 key(键)
dict={'name':'Mike','age':18} for key in dict.keys(): print(key)
- 遍历字典的 value(值)
dict={'name':'Mike','age':18} for key in dict.values(): print(key)
- 遍历字典的项(元素)
dict={'name':'Mike','age':18} for item in dict.items(): print(item)
- 遍历字典的 key-value(键值对)
dict={'name':'Mike','age':18} for key,value in dict.items(): print(key,value)
- 除了使用 key 查找数据,还可以使用 get 来获取数据
- 字符串高级
-
函数
-
-
- 在python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件
- open(文件路径,访问模式)
f = open('test.txt', 'w')
- 绝对路径:指的是绝对位置,完整地描述了目标的所在地,所有目录层级关系是一目了然的
- 相对路径:是从当前文件所在的文件夹开始的路径
- 访问模式
访问模式 说明 r 以只读方式打开文件。文件的指针将会放在文件的开头。如果文件不存在,则报错。这是默认模式 w 打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件 a 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入 r+ 打开一个文件用于读写。文件指针将会放在文件的开头 w+ 打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件 a+ 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写 rb 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头 wb 以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件 ab 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入 rb+ 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头 wb+ 以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件 ab+ 以二进制格式打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写
关闭文件
# 新建一个文件,文件名为:test.txt f = open('test.txt', 'w') # 关闭这个文件 f.close()
-
- 如果文件不存在,那么创建;如果存在那么就先清空,然后写入数据
f = open('test.txt', 'w') f.write('hello world, i am here!n' * 5) f.close()
读数据(read)
- 如果文件不存在,那么创建;如果存在那么就先清空,然后写入数据
-
- 通过文件操作,我们可以将字符串写入到一个本地文件。但是,如果是一个对象(例如列表、字典、元组等),就无法直接写入到一个文件里,需要对这个对象进行序列化,然后才能写入到文件里
- 设计一套协议,按照某种规则,把内存中的数据转换为字节序列,保存到文件,这就是序列化,反之,从文件的字节序列恢复到内存中,就是反序列化
- JSON 模块
- JSON提供了 dump 和 dumps 方法,将一个对象进行序列化
- dumps 方法的作用是把对象转换成为字符串,它本身不具备将数据写入到文件的功能
import json file = open('names.txt', 'w') names = ['zhangsan', 'lisi', 'wangwu', 'jerry', 'henry', 'merry', 'chris'] # file.write(names) 出错,不能直接将列表写入到文件里 # 可以调用 json的dumps方法,传入一个对象参数 result = json.dumps(names) # dumps 方法得到的结果是一个字符串 print(type(result)) # <class 'str'> # 可以将字符串写入到文件里 file.write(result) file.close()
- dump 方法可以在将对象转换成为字符串的同时,指定一个文件对象,把转换后的字符串写入到这个文件里
import json file = open('names.txt', 'w') names = ['zhangsan', 'lisi', 'wangwu', 'jerry', 'henry', 'merry', 'chris'] # dump方法可以接收一个文件参数,在将对象转换成为字符串的同时写入到文件里 json.dump(names, file) file.close()
- 使用 JSON 实现反序列化
- 使用 loads 和 load 方法,可以将一个 JSON 字符串反序列化成为一个 Python 对象
- loads 方法需要一个字符串参数,用来将一个字符串加载成为 Python 对象
import json # 调用 loads 方法,传入一个字符串,可以将这个字符串加载成为 Python 对象 result = json.loads('["zhangsan", "lisi", "wangwu", "jerry", "henry", "merry", "chris"]') print(type(result)) # <class 'list'>
- load 方法可以传入一个文件对象,用来将一个文件对象里的数据加载成为 Python 对象
import json # 以可读方式打开一个文件 file = open('names.txt', 'r') # 调用 load 方法,将文件里的内容加载成为一个 Python 对象 result = json.load(file) print(result) file.close()
-
-
程序在运行过程中,由于我们的编码不规范,或者其他原因一些客观原因, 导致我们的程序无法继续运行,此时,程序就会出现异常。 如果我们不对异常进行处理,程序可能会由于异常直接中断掉。 为了保证程序的健壮性,我们在程序设计里提出了异常处理这个概念
二 Urllib
1.Urllib 介绍
-
爬虫的用途
-
通用爬虫: 实例 百度、360、google、sougou 等搜索引擎‐‐‐伯乐在线 功能 访问网页‐>抓取数据‐>数据存储‐>数据处理‐>提供检索服务 robots协议 一个约定俗成的协议,添加 robots.txt 文件,来说明本网站哪些内容不可以被抓取,起不到限制作用 自己写的爬虫无需遵守 网站排名(SEO) 1. 根据 pagerank 算法值进行排名(参考个网站流量、点击率等指标) 2. 百度竞价排名 缺点 1. 抓取的数据大多是无用的 2.不能根据用户的需求来精准获取数据 聚焦爬虫: 功能 根据需求,实现爬虫程序,抓取需要的数据 设计思路 1.确定要爬取的 url 如何获取 Url 2.模拟浏览器通过 http 协议访问 url ,获取服务器返回的 html 代码 如何访问 3.解析 html 字符串(根据一定规则提取需要的数据) 如何解析
-
反爬手段
2.Urllib 库使用以及请求对象的定制
-
Urllib 库使用
urllib.request.urlopen() 模拟浏览器向服务器发送请求 response 服务器返回的数据 response的数据类型是 HttpResponse 字节‐‐>字符串 解码 decode 字符串‐‐>字节 编码 encode read() 字节形式读取二进制 扩展:rede(5) 返回前几个字节 readline() 读取一行 readlines() 一行一行读取 直至结束 getcode() 获取状态码 geturl() 获取 url getheaders() 获取 headers urllib.request.urlretrieve() 请求网页 请求图片 请求视频
3.编解码
- 介绍:由于计算机是美国人发明的,因此,最早只有 127 个字符被编码到计算机里,也就是大小写英文字母、数字和一些符号,这个编码表被称为ASCII编码,比如大写字母A的编码是 65,小写字母z的编码是 122。但是要处理中文显然一个字节是不够的,至少需要两个字节,而且还不能和 ASCII 编码冲突,所以,中国制定了 GB2312 编码,用来把中文编进去。你可以想得到的是,全世界有上百种语言,日本把日文编到 Shift_JIS 里,韩国把韩文编到 Euc‐kr 里,各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。因此,Unicode 应运而生。Unicode 把所有语言都统一到一套编码里,这样就不会再有乱码问题了。Unicode 标准也在不断发展,但最常用的是用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要 4 个字节)。现代操作系统和大多数编程语言都直接支持 Unicode
- get 请求方式:urllib.parse.quote()
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, likeGecko) Chrome/74.0.3729.169 Safari/537.36' } url = url + urllib.parse.quote('小野') request = urllib.request.Request(url=url,headers=headers) response = urllib.request.urlopen(request) content=response.read().decode('utf‐8') print(content)
- get 请求方式:urllib.parse.urlencode()
import urllib.request import urllib.parse url = 'http://www.baidu.com/s?' data = { 'name':'小刚', 'sex':'男', } data = urllib.parse.urlencode(data) url = url + data print(url) headers = { 'User‐Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, likeGecko) Chrome/74.0.3729.169 Safari/537.36' } request = urllib.request.Request(url=url,headers=headers) response = urllib.request.urlopen(request) content=response.read().decode('utf‐8') print(content)
- post 请求方式
import urllib.request import urllib.parse url = 'https://fanyi.baidu.com/sug' headers = { 'user‐agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, likeGecko) Chrome/74.0.3729.169 Safari/537.36' } keyword = input('请输入您要查询的单词') data = { 'kw':keyword } data = urllib.parse.urlencode(data).encode('utf‐8') request = urllib.request.Request(url=url,headers=headers,data=data) response = urllib.request.urlopen(request) content=response.read().decode('utf‐8') print(content)
- post 和 get 区别
- 案例1:百度详细翻译
import urllib.request import urllib.parse url = 'https://fanyi.baidu.com/v2transapi' headers = { # ':authority': 'fanyi.baidu.com', # ':method': 'POST', # ':path': '/v2transapi', # ':scheme': 'https', # 'accept': '*/*', # 'accept‐encoding': 'gzip, deflate, br', # 'accept‐language': 'zh‐CN,zh;q=0.9', # 'content‐length': '119', # 'content‐type': 'application/x‐www‐form‐urlencoded; charset=UTF‐8', 'cookie':'REALTIME_TRANS_SWITCH=1;FANYI_WORD_SWITCH=1;HISTORY_SWITCH=1;SOUND_SPD_SWITCH=1;SOUND_PREFER_SWITCH=1;PSTM=1537097513;BIDUPSID=D96F9A49A8630C54630DD60CE082A55C;BAIDUID=0814C35D13AE23F5EAFA8E0B24D9B436:FG=1;to_lang_often=%5B%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%2C%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%5D;from_lang_often=%5B%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%2C%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%5D;BDORZ=B490B5EBF6F3CD402E515D22BCDA1598;delPer=0;H_PS_PSSID=1424_21115_29522_29519_29099_29568_28835_29220_26350;PSINO=2;locale=zh;Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1563000604,1563334706,1565592510;Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1565592510;yjs_js_security_passport=2379b52646498f3b5d216e6b21c6f1c7bf00f062_1565592544_js', # 'origin': 'https://fanyi.baidu.com', # 'referer': 'https://fanyi.baidu.com/translate?aldtype=16047&query=&keyfrom=baidu&smartresult=dict&lang=auto2zh', # 'sec‐fetch‐mode': 'cors', # 'sec‐fetch‐site': 'same‐origin', # 'user‐agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, likeGecko) Chrome/76.0.3809.100 Safari/537.36', # 'x‐requested‐with': 'XMLHttpRequest', } data = { 'from': 'en', 'to': 'zh', 'query': 'you', 'transtype': 'realtime', 'simple_means_flag': '3', 'sign': '269482.65435', 'token': '2e0f1cb44414248f3a2b49fbad28bbd5', } #参数的编码 data = urllib.parse.urlencode(data).encode('utf‐8') # 请求对象的定制 request = urllib.request.Request(url=url,headers=headers,data=data) response = urllib.request.urlopen(request) # 请求之后返回的所有的数据 content = response.read().decode('utf‐8') import json # loads将字符串转换为python对象 obj = json.loads(content) # python对象转换为json字符串 ensure_ascii=False 忽略字符集编码 s = json.dumps(obj,ensure_ascii=False) print(s)
- 案例2:豆瓣电影(ajax 的 get 请求)
# 爬取豆瓣电影前10页数据 # https://movie.douban.com/j/chart/top_list?type=20&interval_id=100%3A90&action=&start=0&limit=20 # https://movie.douban.com/j/chart/top_list?type=20&interval_id=100%3A90&action=&start=20&limit=20 # https://movie.douban.com/j/chart/top_list?type=20&interval_id=100%3A90&action=&start=40&limit=20 import urllib.request import urllib.parse # 下载前10页数据 # 下载的步骤:1.请求对象的定制 2.获取响应的数据 3.下载 # 每执行一次返回一个request对象 def create_request(page): base_url = 'https://movie.douban.com/j/chart/top_list?type=20&interval_id=100%3A90&action=&' headers = { 'User‐Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/76.0.3809.100 Safari/537.36' } data={ # 1 2 3 4 # 0 20 40 60 'start':(page‐1)*20, 'limit':20 } # data编码 data = urllib.parse.urlencode(data) url = base_url + data request = urllib.request.Request(url=url,headers=headers) return request # 获取网页源码 def get_content(request): response = urllib.request.urlopen(request) content = response.read().decode('utf‐8') return content def down_load(page,content): # with open(文件的名字,模式,编码)as fp: # fp.write(内容) with open('douban_'+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)
4.URLError HTTPError
- 简介
- 示例
import urllib.request import urllib.error url = 'https://blog.csdn.net/ityard/article/details/102646738' # url = 'http://www.goudan11111.com' headers = { #'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed‐exchange;v=b3', # 'Accept‐Encoding': 'gzip, deflate, br', # 'Accept‐Language': 'zh‐CN,zh;q=0.9', # 'Cache‐Control': 'max‐age=0', # 'Connection': 'keep‐alive', 'Cookie': 'uuid_tt_dd=10_19284691370‐1530006813444‐566189;smidV2=2018091619443662be2b30145de89bbb07f3f93a3167b80002b53e7acc61420;_ga=GA1.2.1823123463.1543288103;dc_session_id=10_1550457613466.265727;acw_tc=2760821d15710446036596250e10a1a7c89c3593e79928b22b3e3e2bc98b89;Hm_lvt_e5ef47b9f471504959267fd614d579cd=1571329184;Hm_ct_e5ef47b9f471504959267fd614d579cd=6525*1*10_19284691370‐1530006813444‐566189;__yadk_uid=r0LSXrcNYgymXooFiLaCGt1ahSCSxMCb;Hm_lvt_6bcd52f51e9b3dce32bec4a3997715ac=1571329199,1571329223,1571713144,1571799968;acw_sc__v2=5dafc3b3bc5fad549cbdea513e330fbbbee00e25; firstDie=1; SESSION=396bc85c‐556b‐42bd‐890c‐c20adaaa1e47;UserName=weixin_42565646;UserInfo=d34ab5352bfa4f21b1eb68cdacd74768;UserToken=d34ab5352bfa4f21b1eb68cdacd74768; UserNick=weixin_42565646; AU=7A5;UN=weixin_42565646; BT=1571800370777; p_uid=U000000; dc_tos=pzt4xf;Hm_lpvt_6bcd52f51e9b3dce32bec4a3997715ac=1571800372;Hm_ct_6bcd52f51e9b3dce32bec4a3997715ac=1788*1*PC_VC!6525*1*10_19284691370‐1530006813444‐566189!5744*1*weixin_42565646;announcement=%257B%2522isLogin%2522%253Atrue%252C%2522announcementUrl%2522%253A%2522https%253A%252F%252Fblogdev.blog.csdn.net%252Farticle%252Fdetails%252F102605809%2522%252C%2522announcementCount%2522%253A0%252C%2522announcementExpire%2522%253A3600000%257D', # 'Host': 'blog.csdn.net', # 'Referer': 'https://passport.csdn.net/login?code=public', # 'Sec‐Fetch‐Mode': 'navigate', # 'Sec‐Fetch‐Site': 'same‐site', # 'Sec‐Fetch‐User': '?1', # 'Upgrade‐Insecure‐Requests': '1', 'User‐Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, likeGecko) Chrome/77.0.3865.120 Safari/537.36', } try: request = urllib.request.Request(url=url,headers=headers) response = urllib.request.urlopen(request) content = response.read().decode('utf‐8') print(content) except urllib.error.HTTPError: print(1111) except urllib.error.URLError: print(2222)
- .cookie 登录
5.Handler 处理器与代理服务器
- 为什么要学习 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,likeGecko) Chrome / 74.0.3729.169Safari / 537.36' } request = urllib.request.Request(url=url,headers=headers) handler = urllib.request.HTTPHandler() opener = urllib.request.build_opener(handler) response = opener.open(request) content=response.read().decode('utf‐8') print(content)
- 代理的常用功能
- 代码配置代理
- 代理示例
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,likeGecko) Chrome / 74.0.3729.169Safari / 537.36' } request = urllib.request.Request(url=url,headers=headers) proxies = {'http':'117.141.155.244:53281'} handler = urllib.request.ProxyHandler(proxies=proxies) opener = urllib.request.build_opener(handler) response = opener.open(request) content = response.read().decode('utf‐8') with open('daili.html','w',encoding='utf‐8')as fp: fp.write(content)
- 扩展
- 代理池
- 快代理
三 解析
1.XPath
- xpath 使用
- xpath 基本语法
2.JsonPath
资料 |
---|
简单入门 |
-
pip 安装
pip install jsonpath
-
jsonpath 的使用
obj = json.load(open('json文件', 'r', encoding='utf‐8')) ret = jsonpath.jsonpath(obj, 'jsonpath语法')
3.BeautifulSoup
-
基本简介
-
安装以及创建
-
1.根据标签名查找节点 soup.a 【注】只能找到第一个a soup.a.name soup.a.attrs 2.函数 (1).find(返回一个对象) find('a'):只找到第一个a标签 find('a', title='名字') find('a', class_='名字') (2).find_all(返回一个列表) find_all('a') 查找到所有的a find_all(['a', 'span']) 返回所有的a和span find_all('a', limit=2) 只找前两个a (3).select(根据选择器得到节点对象)【推荐】 1.element eg:p 2..class eg:.firstname 3.#id eg:#firstname 4.属性选择器 [attribute] eg:li = soup.select('li[class]') [attribute=value] eg:li = soup.select('li[class="hengheng1"]') 5.层级选择器 element element div p element>element div>p element,element div,p eg:soup = soup.select('a,span')
-
节点信息
四 真实浏览器交互
1.Selenium
-
什么是 Selenium
-
为什么使用 Selenium
-
如何安装 Selenium
-
Selenium 的使用步骤
-
Selenium 的元素定位
元素定位:自动化要做的就是模拟鼠标和键盘来操作来操作这些元素,点击、输入等等。操作这些元素前首先要找到它们,WebDriver 提供很多定位元素的方法,最新方法方法(以下方法都被弃用) 示例 find_element_by_id button = browser.find_element_by_id(‘su’) find_elements_by_name name = browser.find_element_by_name(‘wd’) find_elements_by_xpath xpath1 = browser.find_elements_by_xpath(‘//input[@id=“su”]’) find_elements_by_tag_name names = browser.find_elements_by_tag_name(‘input’) find_elements_by_css_selector my_input = browser.find_elements_by_css_selector(‘#kw’)[0] find_elements_by_link_text browser.find_element_by_link_text(“新闻”) -
访问元素信息
方法 作用 .get_attribute(‘class’) 获取元素属性 .text 获取元素文本 .tag_name 获取标签名 -
方法 作用 click() 点击 send_keys() 输入 browser.back() 后退操作 browser.forword() 前进操作 js=‘document.documentElement.scrollTop=100000’(此方法无效) 模拟JS滚动 browser.execute_script(js代码) 执行js代码 page_source 获取网页代码 browser.quit() 退出
2.Phantomjs
- 什么是 Phantomjs
- 如何使用 Phantomjs
3.Chrome handless
- Chrome-headless 模式, Google 针对 Chrome 浏览器 59版 新增加的一种模式,可以让你不打开 UI 界面的情况下使用 Chrome 浏览器,所以运行效果与 Chrome 保持完美一致
- 系统要求
- 配置
from selenium import webdriver from selenium.webdriver.chrome.options import Options chrome_options = Options() chrome_options.add_argument('--headless') chrome_options.add_argument('--disable‐gpu') path = r'C:Program Files (x86)GoogleChromeApplicationchrome.exe' chrome_options.binary_location = path browser = webdriver.Chrome(options=chrome_options) browser.get('http://www.baidu.com/')
- 配置封装
from selenium import webdriver #这个是浏览器自带的 不需要我们再做额外的操作 from selenium.webdriver.chrome.options import Options def share_browser(): #初始化 chrome_options = Options() chrome_options.add_argument('‐‐headless') chrome_options.add_argument('‐‐disable‐gpu') #浏览器的安装路径 打开文件位置 #这个路径是你谷歌浏览器的路径 path = r'C:Program Files (x86)GoogleChromeApplicationchrome.exe' chrome_options.binary_location = path browser = webdriver.Chrome(chrome_options=chrome_options) return browser # 封装调用 from handless import share_browser browser = share_browser() browser.get('http://www.baidu.com/') browser.save_screenshot('handless1.png')
五 requests
1.基本使用
2.get 请求
- requests.get()
import requests url = 'http://www.baidu.com/s?' headers = { 'User‐Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/65.0.3325.181 Safari/537.36' } data = { 'wd':'北京' } response = requests.get(url,params=data,headers=headers)
- 定制参数
3.post请求
- requests.post()
# 百度翻译 import requests post_url = 'http://fanyi.baidu.com/sug' headers={ 'User‐Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36(KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36' } data = { 'kw': 'eye' } r = requests.post(url = post_url,headers=headers,data=data)
- get 和 post 区别
4.代理
- proxy 定制
在请求中设置 proxies 参数
参数类型是一个字典类型import requests url = 'http://www.baidu.com/s?' headers = { 'user‐agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/65.0.3325.181 Safari/537.36' } data = { 'wd':'ip' } proxy = { 'http':'219.149.59.250:9797' } r = requests.get(url=url,params=data,headers=headers,proxies=proxy) with open('proxy.html','w',encoding='utf‐8') as fp: fp.write(r.text)
5.cookie 定制
六 scrapy
1.scrapy
①scrapy 介绍
-
scrapy 是什么
-
安装
安装 scrapy: pip install scrapy 安装过程中出错: 如果安装有错误!!!! pip install Scrapy building 'twisted.test.raiser' extension error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools": http://landinghub.visualstudio.com/visual‐cpp‐build‐tools 解决方案: http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted 下载twisted对应版本的 whl 文件(如我的 Twisted‐17.5.0‐cp36‐cp36m‐win_amd64.whl),cp 后面是 python 版本,amd64 代表 64 位,运行命令: pip install C:Users...Twisted‐17.5.0‐cp36‐cp36m‐win_amd64.whl pip install Scrapy 如果再报错 python ‐m pip install ‐‐upgrade pip 如果再报错 win32 解决方法: pip install pypiwin32 再报错:使用 anaconda 使用步骤: 打开 anaconda 点击 environments 点击 not installed 输入 scrapy apply 在 pycharm 中选择 anaconda 的环境
②scrapy 项目的创建以及运行
- 创建 scrapy 项目
- 项目组成
- 创建爬虫文件
- 爬虫文件的基本组成
继承 scrapy.Spider 类 - 运行爬虫文件
③scrapy 架构组成
④scrapy 工作原理
2.scrapy shell
- 什么是 scrapy shell
- 安装 ipython
- 应用
- 语法
- response 对象
- response 的解析
- selector对象 –> 通过 xpath 方法调用返回的是 seletor 列表
3.yield
- 带有 yield 的函数不再是一个普通函数,而是一个生成器 generator ,可用于迭代
- yield 是一个类似 return 的关键字,迭代一次遇到 yield 时就返回 yield 后面(右边)的值。重点是:下一次迭代时,从上一次迭代遇到的 yield 后面的代码(下一行)开始执行
- 简要理解:yield 就是 return 返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后(下一行)开始
- 案例
4.pymysql 与 CrawlSpider
-
Mysql
-
pymysql 的使用步骤
pip install pymysql pymysql.connect(host,port,user,password,db,charset) conn.cursor() cursor.execute()
-
CrawlSpider
1.继承自 scrapy.Spider 2.独门秘笈 CrawlSpider 可以定义规则,再解析 html 内容的时候,可以根据链接规则提取出指定的链接,然后再向这些链接发送请求 所以,如果有需要跟进链接的需求,意思就是爬取了网页之后,需要提取链接再次爬取,使用 CrawlSpider 是非常合适的 3.提取链接 链接提取器,在这里就可以写规则提取指定链接 scrapy.linkextractors.LinkExtractor( allow = (), # 正则表达式 提取符合正则的链接 deny = (), # (不用)正则表达式 不提取符合正则的链接 allow_domains = (), # (不用)允许的域名 deny_domains = (), # (不用)不允许的域名 restrict_xpaths = (), # xpath,提取符合 xpath 规则的链接 restrict_css = () # 提取符合选择器规则的链接 ) 4.模拟使用 正则用法:links1 = LinkExtractor(allow=r'list_23_d+.html') xpath用法:links2 = LinkExtractor(restrict_xpaths=r'//div[@class="x"]') css用法:links3 = LinkExtractor(restrict_css='.x') 5.提取连接 link.extract_links(response) 6.注意事项 【注1】callback只能写函数名字符串, callback='parse_item' 【注2】在基本的spider中,如果重新发送请求,那里的callback写的是 callback=self.parse_item 【注‐ ‐稍后看】follow=true 是否跟进 就是按照提取连接规则进行提取
-
CrawlSpider 运行原理
-
CrawlSpider 案例
-
数据入库
# settings 配置参数 DB_HOST = '192.168.231.128' DB_PORT = 3306 DB_USER = 'root' DB_PASSWORD = '1234' DB_NAME = 'test' DB_CHARSET = 'utf8' # 管道配置 from scrapy.utils.project import get_project_settings import pymysql class MysqlPipeline(object): #__init__方法和open_spider的作用是一样的 #init是获取settings中的连接参数 def __init__(self): settings = get_project_settings() self.host = settings['DB_HOST'] self.port = settings['DB_PORT'] self.user = settings['DB_USER'] self.pwd = settings['DB_PWD'] self.name = settings['DB_NAME'] self.charset = settings['DB_CHARSET'] self.connect() # 连接数据库并且获取cursor对象 def connect(self): self.conn = pymysql.connect(host=self.host, port=self.port, user=self.user, password=self.pwd, db=self.name, charset=self.charset) self.cursor = self.conn.cursor() def process_item(self, item, spider): sql = 'insert into book(image_url, book_name, author, info) values("%s","%s", "%s", "%s")' % (item['image_url'], item['book_name'], item['author'], item['info']) sql = 'insert into book(image_url,book_name,author,info) values("{}","{}","{}","{}")'.format(item['image_url'], item['book_name'], item['author'],item['info']) # 执行sql语句 self.cursor.execute(sql) self.conn.commit() return item def close_spider(self, spider): self.conn.close() self.cursor.close()
5.日志信息和日志等级
6.scrapy 的 post 请求与代理
-
scrapy 的 post 请求
(1)重写start_requests方法: def start_requests(self) (2)start_requests的返回值: scrapy.FormRequest(url=url, headers=headers, callback=self.parse_item, formdata=data) url: 要发送的post地址 headers:可以定制头信息 callback: 回调函数 formdata: post所携带的数据,这是一个字典
-
代理
(1)到settings.py中,打开一个选项 DOWNLOADER_MIDDLEWARES = { 'postproject.middlewares.Proxy': 543, } (2)到middlewares.py中写代码 def process_request(self, request, spider): request.meta['proxy'] = 'https://113.68.202.10:9999' return None
原文地址:https://blog.csdn.net/weixin_48636891/article/details/128238198
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_26248.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。