python之爬虫二


10正则表达式

正则表达式(regular expression)是一种字符串匹配模式或者规则,它可以用来检索、替换那些符合特定规则的文本。正则表达式几乎适用于所有编程语言,无论是前端语言 JavaScript,还是诸如许多后端语言,比如 Python、Java、C# 等,这些语言都提供了相应的函数、模块来支持正则表达式,比如 Python 的 re 模块就提供了正则表达式的常用方法。

在使用 Python 编写爬虫的过程中,re 模块通常做为一种解析方法来使用。通过审查网页元素来获取网页的大体结构,然后使用解析模块来提取你想要的网页信息,最终实现数据的抓取。本节对正则表达式基本语法做简单讲解。

注意:学习本节知识之前,您应该已经掌握了正则表达式的使用方法。

正则表达式元字符

下表列出了常用的正则表达式元字符:

1) 元字符

正则表表达式元字符

元字符

匹配内容

匹配除换行符以外的任意字符

\w

匹配所有普通字符(数字、字母或下划线)

\s

匹配任意的空白符

\d

匹配数字

\n

匹配一个换行符

\t

匹配一个制表符

\b

匹配一个单词的结尾

匹配字符串的开始位置

匹配字符串的结尾位置

\W

匹配非字母或数字或下划线

\D

匹配非数字

\S

匹配非空白符

a|b

匹配字符 a 或字符 b

()

正则表达式分组所用符号,匹配括号内的表达式,表示一个组。

[...]

匹配字符组中的字符

[^...]

匹配除了字符组中字符的所有字符

2) 量词

正则表达式量词

量词

用法说明

重复零次或者更多次

重复一次或者更多次

重复0次或者一次

{n}

重复n次

{n,}

重复n次或者更多次

{n,m}

重复n到m次

3) 字符组

有时也会出现各种字符组成的字符组,这在正则表达式中使用[]表示,如下所示:

正则表达式字符组

正则

待匹配字符

匹配结果

说明

[0123456789]

True

在一个字符组里枚举所有字符,字符组里的任意一个字符
"待匹配字符"相同都视为可以匹配。

[0123456789]

False

由于字符组中没有 "a" 字符,所以不能匹配。

[0-9]

True

也可以用-表示范围,[0-9] 就和 [0123456789] 是一个意思。

[a-z]

True

同样的如果要匹配所有的小写字母,直接用 [a-z] 就可以表示。

[A-Z]

True

[A-Z] 就表示所有的大写字母。

[0-9a-fA-F]

True

可以匹配数字,大小写形式的 a~f,用来验证十六进制字符。

贪婪模式非贪婪模式

正则表达式默认为贪婪匹配,也就是尽可能多的向后匹配字符,比如 {n,m} 表示匹配前面的内容出现 n 到 m 次(n 小于 m),在贪婪模式下,首先以匹配 m 次为目标,而在非贪婪模式是尽可能少的向后匹配内容,也就是说匹配 n 次即可。

贪婪模式转换为非贪婪模式的方法很简单,在元字符后添加“?”即可实现,如下所示:

 

非贪婪模式

元字符(贪婪模式)

非贪婪模式

*?

+?

??

{n,m}

{n,m}?

正则表达式转义

如果使用正则表达式匹配特殊字符时,则需要在字符前加\表示转意。常见的特殊字符如下:

* + ? ^ $ [] () {} | \

11re模块使用

Python 爬虫过程中,实现网页元素解析的方法有很多,正则解析只是其中之一,常见的还有 BeautifulSoup 和 lxml,它们都支持网页 HTML 元素的解析操作。本节重点讲解如何使用 re 正则解析模块实现网页信息的提取。

注意:在学习本节知识之前,您应该基本掌握了 Python re 模块的常用方法。

re模块常用方法

1) re.compile()

该方法用来生成正则表达式对象,其语法格式如下:

regex=re.compile(pattern,flags=0)

参数说明:

  • pattern:正则表达式对象。
  • flags:代表功能标志位,扩展正则表达式的匹配。

2) re.findall()

根据正则表达式匹配目标字符串内容。

re.findall(pattern,string,flags=0)

该函数的返回值是匹配到的内容列表,如果正则表达式有子组,则只能获取到子组对应的内容。参数说明如下:

  • pattern:正则表达式对象。
  • string:目标字符串
  • flags:代表功能标志位,扩展正则表达式的匹配。

3) regex.findall()

该函数根据正则表达式对象匹配目标字符串内容。其语法格式如下:

regex.findall(string,pos,endpos)

参数说明:

  • string 目标字符串。
  • pos 截取目标字符串的开始匹配位置。
  • endpos 截取目标字符串的结束匹配位置。

4) re.split()

该函数使用正则表达式匹配内容,切割目标字符串。返回值是切割后的内容列表。参数说明:

re.split(pattern,string,flags = 0)

参数说明:

  • pattern:正则表达式。
  • string:目标字符串。
  • flags:功能标志位,扩展正则表达式的匹配。

5) re.sub
该函数使用一个字符串替换正则表达式匹配到的内容。返回值是替换后的字符串。其语法格式如下:

re.sub(pattern,replace,string,max,flags = 0)

其参数说明:

  • pattern:正则表达式。
  • replace:替换的字符串。
  • string:目标字符串。
  • max:最多替换几处,默认替换全部,
  • flags:功能标志位,扩展正则表达式的匹配。

5) re.search()

匹配目标字符串第一个符合的内容,返回值为匹配的对象。语法格式如下:

re.search(pattern,string,flags=0)

参数说明:

  • pattern:正则表达式
  • string:目标字符串

flags功能标志位

功能标志位的作用是扩展正则表达的匹配功能。常用的 flag 如下所示:

flag功能标志位

缩写元字符

说明

元字符只能匹配 ASCII码。

匹配忽略字母大小写。

使得.元字符可以匹配换行符。

使 ^ $ 可以匹配每一行的开头和结尾位置。


注意:可以同时使用福多个功能标志位,比如 flags=re.I|re.S。

下面使用贪婪和非贪婪两种模式来匹配 HTML 元素,分别,如下所示:

  1. import re
  2. html="""
  3. www.biancheng.net

  4. 编程帮

  5. """
  6. #贪婪匹配,re.S可以匹配换行符
  7. #创建正则表达式对象
  8. pattern=re.compile('

    .*

    ',re.S)
  9. #匹配HTMLX元素,提取信息
  10. re_list=pattern.findall(html)
  11. print(re_list)
  12. #非贪婪模式匹配,re.S可以匹配换行符
  13. pattern=re.compile('

    .*?

    ',re.S)
  14. re_list=pattern.findall(html)
  15. print(re_list)

输出结果:

['

www.biancheng.net

\n

编程帮

']

['

www.biancheng.net

', '

编程帮

']

从上述输出结果可以得出非贪婪模式比适合提取 HTML 信息。

正则表达式分组

通过正则表达式分组可以从匹配的信息中提取出想要的信息。示例演示:

  1. #正则表达式分组
  2. website="编程帮 www.biancheng.net"
  3. #提取所有信息
  4. #注意此时正则表达式的 "." 需要转义因此使用 \.
  5. pattern_1=re.compile('\w+\s+\w+\.\w+\.\w+')
  6. print(pattern_1.findall(website))
  7. #提取匹配信息的第一项
  8. pattern_2=re.compile('(\w+)\s+\w+\.\w+\.\w+')
  9. print(pattern_2.findall(website))
  10. #有两个及以上的()则以元组形式显示
  11. pattern_3=re.compile('(\w+)\s+(\w+\.\w+\.\w+)')
  12. print(pattern_3.findall(website))

输出结果:

['编程帮 www.biancheng.net']

['编程帮']

[('编程帮', 'www.biancheng.net')]

正则表达式分组是提取信息的常用方式。当需要哪个特定信息的时候,就可以通过分组(也就是加括号)的方式获得。

网页信息提取

实战演练:从下面的 HTML 代码中使用 re 模块提取出两部影片的名称和主演信息。

  • 刺杀,小说家">刺杀,小说家
  • 主演:雷佳音,杨幂,董子健,于和伟
  •     
  •  
  • """
  • # 寻找HTML规律,书写正则表达式,使用正则表达式分组提取信息
  • pattern=re.compile(r'(.*?)',re.S)
  • r_list=pattern.findall(html)
  • print(r_list)
  • # 整理数据格式并输出
  • if  r_list:
  • for r_info in  r_list:
  • print("影片名称:",r_info[0])
  • print("影片主演:",r_info[1].strip())
  • print(20*"*")
  • 输出结果如下:

    [('你好,李焕英', '\n主演:贾玲,张小斐,沈腾\n'), ('刺杀,小说家', '\n主演:雷佳音,杨幂,董子健,于和伟\n')]

     

    影片名称: 你好,李焕英

    影片主演: 主演:贾玲,张小斐,沈腾

    ********************

    影片名称: 刺杀,小说家

    影片主演: 主演:雷佳音,杨幂,董子健,于和伟

    ********************

    12csv模块

    CSV 文件又称为逗号分隔值文件,是一种通用的、相对简单的文件格式,用以存储表格数据,包括数字或者字符。CSV 是电子表格和数据库中最常见的输入、输出文件格式,可参考《CSV介绍》。

    通过爬虫将数据抓取的下来,然后把数据保存在文件,或者数据库中,这个过程称为数据的持久化存储。本节介绍 Python 内置模块 CSV 的读写操作。

    CSV文件写入

    1) csv.writer()

    csv 模块中的 writer 类可用于读写序列化的数据,其语法格式如下:

    writer(csvfile, dialect='excel', **fmtparams)

    参数说明:

    • csvfile:必须是支持迭代(Iterator)的对象,可以是文件(file)对象或者列表(list)对象。
    • dialect:编码风格,默认为 excel 的风格,也就是使用逗号,分隔。
    • fmtparam:格式化参数,用来覆盖之前 dialect 对象指定的编码风格。


    示例如下:

    1. import csv
    2. # 操作文件对象时,需要添加newline参数逐行写入,否则会出现空行现象
    3. with open('eggs.csv', 'w', newline='') as csvfile:
    4. # delimiter 指定分隔符,默认为逗号,这里指定为空格
    5. # quotechar 表示引用符
    6. # writerow 单行写入,列表格式传入数据
    7. spamwriter = csv.writer(csvfile, delimiter=' ',quotechar='|')
    8. spamwriter.writerow(['www.biancheng.net'] * 5 + ['how are you'])
    9. spamwriter.writerow(['hello world', 'web site', 'www.biancheng.net'])

    eggs.csv 文件内容如下:

    www.biancheng.net www.biancheng.net www.biancheng.net www.biancheng.net www.biancheng.net |how are you|

    |hello world| |web site| www.biancheng.net

    其中,quotechar 是引用符,当一段话中出现分隔符的时候,用引用符将这句话括起来,以能排除歧义。

    如果想同时写入多行数据,需要使用 writerrows() 方法,代码如下所示:

    1. import csv
    2. with open('aggs.csv', 'w', newline='') as f:
    3. writer = csv.writer(f)
    4. # 注意传入数据的格式为列表元组格式
    5. writer.writerows([('hello','world'), ('I','love','you')])

    aggs.csv文件内容:

    hello,world

    I,love,you

    2) csv.DictWriter()

    当然也可使用 DictWriter 类以字典的形式读写数据,使用示例如下:

    1. import csv
    2. with open('names.csv', 'w', newline='') as csvfile:
    3. #构建字段名称,也就是key
    4. fieldnames = ['first_name', 'last_name']
    5. writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
    6. # 写入字段名,当做表头
    7. writer.writeheader()
    8. # 多行写入
    9. writer.writerows([{'first_name': 'Baked', 'last_name': 'Beans'},{'first_name': 'Lovely', 'last_name': 'Spam'}])
    10. # 单行写入
    11. writer.writerow({'first_name': 'Wonderful', 'last_name': 'Spam'})

    name.csv 文件内容,如下所示:

    first_name,last_name

    Baked,Beans

    Lovely,Spam

    Wonderful,Spam

    CSV文件读取

    1) csv,reader()

    csv 模块中的 reader 类和  DictReader 类用于读取文件中的数据,其中 reader() 语法格式如下:

    csv.reader(csvfile, dialect='excel', **fmtparams)

    应用示例如下:

    1. import csv
    2. with open('eggs.csv', 'r', newline='') as csvfile:
    3. spamreader = csv.reader(csvfile, delimiter=' ', quotechar='|')
    4. for row in spamreader:
    5. print(', '.join(row))

    输出结果:

    www.biancheng.net, www.biancheng.net, www.biancheng.net, www.biancheng.net, www.biancheng.net, how are you

    hello world, web site, www.biancheng.net

    2) csv.DictReader()

    应用示例如下:

    1. import csv
    2. with open('names.csv', newline='') as csvfile:
    3. reader = csv.DictReader(csvfile)
    4. for row in reader:
    5. print(row['first_name'], row['last_name'])

    输出结果:

    Baked Beans

    Lovely Spam

    Wonderful Spam

    13实战

    本节使用 Python 爬虫抓取猫眼电影网 TOP100 排行榜(https://maoyan.com/board/4)影片信息,包括电影名称、上映时间、主演信息。

    在开始编写程序之前,首先要确定页面类型(静态页面或动态页面),其次找出页面的 url 规律,最后通过分析网页元素结构来确定正则表达式,从而提取网页信息。

    确定页面类型

    点击右键查看页面源码,确定要抓取的数据是否存在于页面内。通过浏览得知要抓取的信息全部存在于源码内,因此该页面输属于静态页面。如下所示:

    1.  class="movie-item-info">
    2.  class="name"> href="/films/1200486" title="我不是药神" data-act="boarditem-click" data-val="{movieId:1200486}">我不是药神

    3.  class="star">
    4. 主演:徐峥,周一围,王传君
    5.  class="releasetime">上映时间:2018-07-05

          

    确定url规律

    想要确定 url 规律,需要您多浏览几个页面,然后才可以总结出 url 规律,如下所示:

    第一页:https://maoyan.com/board/4?offset=0

    第二页:https://maoyan.com/board/4?offset=10

    第三页:https://maoyan.com/board/4?offset=20

    ...

    n页:https://maoyan.com/board/4?offset=(n-1)*10

    确定正则表达式

    通过分析网页元素结构来确定正则表达式,如下所示:

    1.  class="movie-item-info">
    2.  class="name"> href="/films/1200486" title="我不是药神" data-act="boarditem-click" data-val="{movieId:1200486}">我不是药神

    3.  class="star">
    4. 主演:徐峥,周一围,王传君
    5.  class="releasetime">上映时间:2018-07-05

    使用 Chrome 开发者调试工具来精准定位要抓取信息的元素结构。之所以这样做,是因为这能避免正则表达式的冗余,提高编写正则表达式的速度。正则表达式如下所示:

    .*?title="(.*?)".*?class="star">(.*?)

    .*?releasetime">(.*?)

    编写正则表达式时将需要提取的信息使用(.*?)代替,而不需要的内容(包括元素标签)使用.*?代替。

    编写爬虫程序

    下面使用面向对象的方法编写爬虫程序,主要编写四个函数,分别是请求函数、解析函数、保存数据函数、主函数。

    1. from urllib import request
    2. import re
    3. import time
    4. import random
    5. import csv
    6. from ua_info import ua_list
    7. # 定义一个爬虫类
    8. class MaoyanSpider(object): 
    9. # 初始化
    10. # 定义初始页面url
    11. def __init__(self):
    12. self.url = 'https://maoyan.com/board/4?offset={}'
    13. # 请求函数
    14. def get_html(self,url):
    15. headers = {'User-Agent':random.choice(ua_list)}
    16. req = request.Request(url=url,headers=headers)
    17. res = request.urlopen(req)
    18. html = res.read().decode()
    19. # 直接调用解析函数
    20. self.parse_html(html)
    21. # 解析函数
    22. def parse_html(self,html):
    23. # 正则表达式
    24. re_bds = '
      .*?title="(.*?)".*?

      (.*?)

      .*?class="releasetime">(.*?)

      '
    25. # 生成正则表达式对象
    26. pattern = re.compile(re_bds,re.S)
    27. # r_list: [('我不是药神','徐峥,周一围,王传君','2018-07-05'),...] 列表元组
    28. r_list = pattern.findall(html)
    29. self.save_html(r_list)
    30. # 保存数据函数,使用python内置csv模块
    31. def save_html(self,r_list):
    32. #生成文件对象  
    33. with open('maoyan.csv','a',newline='',encoding="utf-8") as f:
    34. #生成csv操作对象
    35. writer = csv.writer(f)
    36. #整理数据
    37. for r in r_list:
    38. name = r[0].strip()
    39. star = r[1].strip()[3:]
    40. # 上映时间:2018-07-05
    41. # 切片截取时间
    42. time = r[2].strip()[5:15]
    43. L = [name,star,time]
    44. # 写入csv文件
    45. writer.writerow(L)
    46. print(name,time,star)
    47. # 主函数
    48. def run(self):
    49. #抓取第一页数据
    50. for offset in range(0,11,10):
    51. url = self.url.format(offset)
    52. self.get_html(url)
    53. #生成1-2之间的浮点数
    54. time.sleep(random.uniform(1,2))
    55. # 以脚本方式启动
    56. if __name__ == '__main__':
    57. #捕捉异常错误
    58. try:
    59. spider = MaoyanSpider()
    60. spider.run()
    61. except Exception as e:
    62. print("错误:",e)

    输出结果:

    我不是药神 2018-07-05 徐峥,周一围,王传君
    肖申克的救赎 1994-09-10 蒂姆·罗宾斯,摩根·弗里曼,鲍勃·冈顿
    绿皮书 2019-03-01 维果·莫腾森,马赫沙拉·阿里,琳达·卡德里尼
    海上钢琴师 2019-11-15 蒂姆·罗斯,比尔·努恩,克兰伦斯·威廉姆斯三世
    小偷家族 2018-08-03 中川雅也,安藤樱,松冈茉优
    霸王别姬 1993-07-26 张国荣,张丰毅,巩俐
    哪吒之魔童降世 2019-07-26 吕艳婷,囧森瑟夫,瀚墨
    美丽人生 2020-01-03 罗伯托·贝尼尼,朱斯蒂诺·杜拉诺,赛尔乔·比尼·布斯特里克
    这个杀手不太冷 1994-09-14 让·雷诺,加里·奥德曼,娜塔莉·波特曼
    盗梦空间 2010-09-01 莱昂纳多·迪卡普里奥,渡边谦,约瑟夫·高登-莱维特

    14pymasql应用

    Python 连接并操作 MySQL 数据库,主要通过 Pymysql 模块实现。本节讲解如何将抓取的数据存储至 MySQL 数据库。

    提示:在学习本节知识之前,您已经掌握了 SQL 语言的基本语法。可参考《MySQL教程

    创建存储数据表

    首先您应该确定您的计算机上已经安装了 MySQL 数据库,然后再进行如下操作:

    # 1. 连接到mysql数据库

    mysql -h127.0.0.1 -uroot -p123456

    # 2. 建库

    create database maoyandb charset utf8;

    # 3. 切换数据库

    use maoyandb;

    # 4. 创建数据表

    create table filmtab(

    name varchar(100),

    star varchar(400),

    time varchar(30)

    );

    Pymysql基本使用

    1) 连接数据库

    1. db = pymysql.connect('localhost','root','123456','maoyandb')

    参数说明:

    • localhost:本地 MySQL 服务端地址,也可以是远程数据库的 IP 地址。
    • root:连接数据所使用的用户名。
    • password:连接数据库使用的密码,本机 MySQL 服务端密码“123456”。
    • db:连接的数据库名称。

    2) 创建cursor对象

    cursor = db.cursor()

    3) 执行sql命令

    execute() 方法用来执行 SQL 语句。如下所示:

    1. #第一种方法:编写sql语句,使用占位符传入相应数据
    2. sql = "insert into filmtab values('%s','%s','%s')" % ('刺杀,小说家','雷佳音','2021')
    3. cursor.excute(sql)
    4. 第二种方法:编写sql语句,使用列表传参方式
    5. sql = 'insert into filmtab values(%s,%s,%s)'
    6. cursor.execute(sql,['刺杀,小说家','雷佳音','2021'])

    4) 提交数据

    db.commit()

    5) 关闭数据库

    cursor.close()

    db.close()

    完整的代码如下所示:

    1. # -*-coding:utf-8-*-
    2. import pymysql
    3. #创建对象
    4. db = pymysql.connect('localhost','root','123456','maoyandb')
    5. cursor = db.cursor()
    6. # sql语句执性,单行插入
    7. info_list = ['刺杀,小说家','雷佳音,杨幂','2021-2-12']
    8. sql = 'insert into movieinfo values(%s,%s,%s)'
    9. #列表传参
    10. cursor.execute(sql,info_list)
    11. db.commit()
    12. # 关闭
    13. cursor.close()
    14. db.close()

    查询数据结果,如下所示:

    mysql> select * from movieinfo;

    +-------------+-------------------+-----------+

    | name        | star              | time      |

    +-------------+-------------------+-----------+

    | 刺杀,小说家   | 雷佳音,杨幂         | 2021-2-12 |

    +-------------+-------------------+-----------+

    1 rows in set (0.01 sec)

    还有一种效率较高的方法,使用 executemany() 可以同时插入多条数据。示例如下:

    1. db = pymysql.connect('localhost','root','123456','maoyandb',charset='utf8')
    2. cursor = db.cursor()
    3. # sql语句执性,列表元组
    4. info_list = [('我不是药神','徐峥','2018-07-05'),('你好,李焕英','贾玲','2021-02-12')]
    5. sql = 'insert into movieinfo values(%s,%s,%s)'
    6. cursor.executemany(sql,info_list)
    7. db.commit()
    8. # 关闭
    9. cursor.close()
    10. db.close()

    查询插入结果,如下所示:

    mysql> select * from movieinfo;

    +-------------+-------------------+------------+

    | name        | star              | time       |

    +-------------+-------------------+------------+

    | 我不是药神  | 徐峥              | 2018-07-05 |

    | 你好,李焕英 | 贾玲              | 2021-02-12 |

    +-------------+-------------------+------------+

    2 rows in set (0.01 sec)

    修改爬虫程序

    下面修改上一节《Python爬虫抓取猫眼电影排行榜》中的爬虫程序,将抓取下来的数据存储到 MySQL 数据库。如下所示:

    1. # coding=gbk
    2. from urllib import request
    3. import re
    4. import time
    5. import random
    6. from ua_info import ua_list
    7. import pymysql
    8. class MaoyanSpider(object):
    9. def __init__(self):
    10. #初始化属性对象
    11. self.url = 'https://maoyan.com/board/4?offset={}'
    12. #数据库连接对象
    13. self.db = pymysql.connect(
    14. 'localhost','root','123456','maoyandb',charset='utf8')
    15. #创建游标对象
    16. self.cursor = self.db.cursor()
    17. def get_html(self,url):
    18. headers = {'User-Agent':random.choice(ua_list)}
    19. req = request.Request(url=url,headers=headers)
    20. res = request.urlopen(req)
    21. html = res.read().decode()
    22. # 直接解析
    23. self.parse_html(html)
    24. def parse_html(self,html):
    25. re_bds = '
      .*?title="(.*?)".*?

      (.*?)

      .*?class="releasetime">(.*?)

      '
    26. pattern = re.compile(re_bds,re.S)
    27. r_list = pattern.findall(html)
    28. self.save_html(r_list)
    29. def save_html(self, r_list):
    30. L = []
    31. sql = 'insert into movieinfo values(%s,%s,%s)'
    32. # 整理数据
    33. for r in r_list:
    34. t = (
    35. r[0].strip(),
    36. r[1].strip()[3:],
    37. r[2].strip()[5:15]
    38. )
    39. L.append(t)
    40. print(L)
    41. # 一次性插入多条数据 L:[(),(),()]
    42. try:
    43. self.cursor.executemany(sql,L)
    44. # 将数据提交数据库
    45. self.db.commit()
    46. except:
    47. # 发生错误则回滚
    48. self.db.rollback()
    49. def run(self):
    50. for offset in range(0,11,10):
    51. url = self.url.format(offset)
    52. self.get_html(url)
    53. time.sleep(random.uniform(1,3))
    54. # 断开游标与数据库连接
    55. self.cursor.close()
    56. self.db.close()
    57. if __name__ == '__main__':
    58. start=time.time()
    59. spider = MaoyanSpider()
    60. spider.run()
    61. end=time.time()
    62. print("执行时间:%.2f" % (end-start))

    数据库查询存储结果,如下所示:

    mysql> select * from movieinfo;

    +----------------+----------------------------------------------------------+------------+

    | name           | star                                                     | time       |

    +----------------+----------------------------------------------------------+------------+

    | 我不是药神     | 徐峥,周一围,王传君                                               | 2018-07-05 |

    | 肖申克的救赎   | 蒂姆·罗宾斯,摩根·弗里曼,鲍勃·冈顿                                  | 1994-09-10 |

    | 绿皮书         | 维果·莫腾森,马赫沙拉·阿里,琳达·卡德里尼                            | 2019-03-01 |

    | 海上钢琴师     | 蒂姆·罗斯,比尔·努恩,克兰伦斯·威廉姆斯三世                           | 2019-11-15 |

    | 小偷家族       | 中川雅也,安藤樱,松冈茉优                                          | 2018-08-03 |

    | 霸王别姬       | 张国荣,张丰毅,巩俐                                               | 1993-07-26 |

    | 哪吒之魔童降世 | 吕艳婷,囧森瑟夫,瀚墨                                              | 2019-07-26 |

    | 美丽人生       | 罗伯托·贝尼尼,朱斯蒂诺·杜拉诺,赛尔乔·比尼·布斯特里克                  | 2020-01-03 |

    | 这个杀手不太冷 | 让·雷诺,加里·奥德曼,娜塔莉·波特曼                                   | 1994-09-14 |

    | 盗梦空间       | 莱昂纳多·迪卡普里奥,渡边谦,约瑟夫·高登-莱维特                        | 2010-09-01 |

    +----------------+----------------------------------------------------------+------------+

    10 rows in set (0.01 sec)

    16抓多级页面

    前面讲解的爬虫案例都是单级页面数据抓取,但有些时候,只抓取一个单级页面是无法完成数据提取的。本节讲解如何使用爬虫抓取多级页面的数据。

    在爬虫的过程中,多级页面抓取是经常遇见的。下面以抓取二级页面为例,对每级页面的作用进行说明:

    • 一级页面提供了获取二级页面的访问链接。
    • 二级页面作为详情页用来提取所需数据。


    一级页面以标签的形式链接到二级页面,只有在二级页面才可以提取到所需数据。

    多级页面分析

    下面以电影天堂(点击访问 2020 新片精品为案例进行讲解,将每部影片的名称,以及下载链接抓取下来。首先点击“更多”进入一级页面,如下图所示:


    1:Python爬虫多级页面抓取

    1) 寻找url规律

    通过简单分析可以得知一级与二级页面均为静态页面,接下来分析 url 规律,通过点击第 1 页,第 2 页 ...,其规律如下:

    1页 :https://www.dytt8.net/html/gndy/dyzz/list_23_1.html

    2页 :https://www.dytt8.net/html/gndy/dyzz/list_23_2.html

    n页 :https://www.dytt8.net/html/gndy/dyzz/list_23_n.html

    2) 确定正则表达式

    通过元素审查可知一级页面的元素结构如下:


    2:页面元素分析

    其正则表达式如下:

     

    .*?


    点击二级页面进入详情页,通过开发者工具分析想要数据的网页元素,即电影名称,和下载链接,其正则表达式如下:

    (.*?)

    .*?
    .*?

    爬虫增量抓取

    爬虫是一种效率很低的程序,非常消耗计算机资源。对于聚焦爬虫程序而言,需要每天对特定的网站进行数据抓取,如果每次都去抓取之前已经抓取过的数据,就会白白消耗了时间和资源。而增量爬虫是指通过监测网站更新的情况,只抓取最新数据的一种方式,这样就大大降低了资源的消耗。

    对于本节案例来说,电影天堂网站每天都会更新内容,因此编写一个增量抓取的爬虫程序是非常合适的。

    那么要如何判断爬虫程序是否已抓取过二级页面的 url 呢?其实,当您第一次运行爬虫程序时,爬虫会将所有的 url 抓取下来,然后将这些 url 放入数据库中。为了提高数据库的查询效率,您可以为每一个 url 生成专属的“指纹”。当网站更新后,第二次运行爬虫程序时,程序只会对数据库中不存在的指纹进行抓取。

    程序代码实现

    1) 建库建表

    将抓取的数据的存放至 MySQL 数据库,需要先进行建库建表操作。注意,这里需要将 url 指纹单独存放在一张表中,如下所示:

    1. create database movieskydb charset utf8;
    2. use movieskydb;
    3. create table request_finger(
    4. finger char(60)
    5. )charset=utf8;
    6. create table movieinfo(
    7. moviename varchar(300),
    8. downloadaddr varchar(600)
    9. )charset=utf8;

    2) url指纹生成

    您可以使用 Python 内置模块 md5 来生成加密“指纹”,如下所示。 

    1. #导入模块
    2. from hashlib import md5
    3. #待加密的url
    4. url="https://www.dytt8.net/html/gndy/dyzz/20210226/61131.html"
    5. # 生成MD5对象
    6. secret = md5()
    7. # 加密url
    8. secret.update(url.encode())
    9. # 提取十六进制的加密串
    10. finger = secret.hexdigest()
    11. print(finger)

    输出结果:

    2d5e46ee52756e8ae59c9ba42230b883

    3) 程序完整代码

    1. # -*- coding: utf-8 -*-
    2. from urllib import request
    3. import re
    4. import time
    5. import random
    6. import pymysql
    7. from hashlib import md5
    8. from ua_info import ua_list
    9. import sys
    10. class MovieSkySpider(object):
    11. def __init__(self):
    12. self.url = 'https://www.dytt8.net/html/gndy/dyzz/list_23_{}.html'
    13. self.db = pymysql.connect(
    14. 'localhost','root','123456','movieskydb',
    15. charset='utf8'
    16. )
    17. self.cursor = self.db.cursor()
    18. # 1.请求函数
    19. def get_html(self, url):
    20. headers = {'User-Agent': random.choice(ua_list)}
    21. req = request.Request(url=url, headers=headers)
    22. res = request.urlopen(req)
    23. # 本网站使用gb2312的编码格式
    24. html = res.read().decode('gb2312', 'ignore')
    25. return html
    26. # 2.正则解析函数
    27. def re_func(self,re_bds,html):
    28. pattern = re.compile(re_bds,re.S)
    29. r_list = pattern.findall(html)
    30. return r_list
    31. # 3.提取数据函数
    32. def parse_html(self,one_url):
    33. # 调用请求函数,获取一级页面
    34. one_html = self.get_html(one_url)
    35. re_bds = '.*?
      '
    36. # 获取二级页面链接
    37. # link_list: ['/html//html/gndy/dyzz/20210226/61131.html','/html/xxx','','']
    38. link_list = self.re_func(re_bds,one_html)
    39. for link in link_list:
    40. # 判断是否需要爬取此链接
    41. # 1.获取指纹
    42. # 拼接二级页面url
    43. two_url = 'https://www.dytt8.net' + link
    44. s = md5()
    45. #加密url,需要是字节串
    46. s.update(two_url.encode())
    47. # 生成指纹,获取十六进制加密字符串,
    48. finger = s.hexdigest()
    49. # 2.通过函数判断指纹在数据库中是否存在
    50. if self.is_hold_on(finger):
    51. # 抓取二级页面数据
    52. self.save_html(two_url)
    53. time.sleep(random.randint(1,2))
    54. # 抓取后,把想用的url专属指纹存入数据库
    55. ins = 'insert into request_finger values (%s)'
    56. self.cursor.execute(ins,[finger])
    57. self.db.commit()
    58. else:
    59. sys.exit('更新完成')
    60. # 4.判断链接是否已经抓取过
    61. def is_hold_on(self,finger):
    62. # 查询数据库
    63. sql='select finger from request_finger where finger=%s'
    64. # execute()函数返回值为受影响的行数(即0或者非0
    65. r = self.cursor.execute(sql,[finger])
    66. # 如果为0表示没有抓取过
    67. if not r:
    68. return True
    69. # 5.解析二级页面,获取数据(名称与下载链接)
    70. def save_html(self,two_url):
    71. two_html = self.get_html(two_url)
    72. re_bds = '

      (.*?)

      \
    .*?.*?style="/a>'
  • # film_list: [('name','downloadlink'),(),(),()]
  • film_list = self.re_func(re_bds,two_html)
  • print(film_list)
  • # 插入数据库
  • sql = 'insert into movieinfo values(%s,%s)'
  • #L = list(film_list[0])
  • self.cursor.executemany(sql,film_list)
  • self.db.commit()
  • #主函数
  • def run(self):
  • # 二级页面后四页的正则表达式略有不同,需要重新分析
  • for i in range(1,4):
  • url = self.url.format(i)
  • self.parse_html(url)
  • if __name__ == '__main__':
  • spider = MovieSkySpider()
  • spider.run()
  • 若要查询数据库存储数据,执行以下命令即可:

    1. mysql> select * from movieinfo\G

    输出如下,如下图所示:


    3:MySQL数据库存储数据
     

    在二级页面提取数据时要注意该页面的类型。该网站在二级页面使用了两种类型的网页结构,另外一种页面结构的正则表达式如下所示:

    (.*?)

    .*?若要抓取此类页面的数据,需要更换二级页面正则表达式

    17requests第三库使用

    Python 提供了多个用来编写爬虫程序的库,除了前面已经介绍的 urllib 库之外,还有一个很重的 Requests 库,这个库的宗旨是“让 HTTP 服务于人类”。


     

    Requests 是 Python 的第三方库,它的安装非常简便,如下所示:

    python -m pip install requests

    Requests 库是在 urllib 的基础上开发而来,它使用 Python 语言编写,并且采用了 Apache2 Licensed(一种开源协议)的 HTTP 库。与 urllib 相比,Requests 更加方便、快捷,因此在编写爬虫程序时 Requests 库使用较多。

    常用请求方法

    1) requests.get()

    该方法用于 GET 请求,表示向网站发起请求,获取页面响应对象。语法如下:

    res = requests.get(url,headers=headers,params,timeout)

    参数说明如下:

    • url:要抓取的 url 地址。
    • headers:用于包装请求头信息。
    • params:请求时携带的查询字符串参数。
    • timeout:超时时间,超过时间会抛出异常。


    具体使用示例如下:

    1. import requests
    2. url = 'http://baidu.com'
    3. response = requests.get(url)
    4. print(response)

    输出结果:

    获取带查询字符串参数的响应对象,如下所示:

    1. import requests
    2. data = {
    3. 'name': '编程帮',
    4. 'url': "www.biancheng.net"
    5. }
    6. response = requests.get('http://httpbin.org/get', params=data)
    7. #直接拼接参数也可以
    8. #response = requests.get(http://httpbin.org/get?name=gemey&age=22)
    9. #调用响应对象text属性,获取文本信息
    10. print(response.text)

    输出结果:

    {

      "args": {

        "name": "\u7f16\u7a0b\u5e2e",

        "url": "www.biancheng.net"

      },

      "headers": {

        "Accept": "*/*",

        "Accept-Encoding": "gzip, deflate",

        "Host": "httpbin.org",

        "User-Agent": "python-requests/2.23.0",

        "X-Amzn-Trace-Id": "Root=1-60420026-236f9205646b68706d0fafa7"

      },

      "origin": "121.17.25.194",

      "url": "http://httpbin.org/get?name=\u7f16\u7a0b\u5e2e&url=www.biancheng.net"

    }

    2) requests.post()

    该方法用于 POST 请求,先由用户向目标 url 提交数据,然后服务器返回一个 HttpResponse 响应对象,语法如下:

    response=requests.post(url,data={请求体的字典})

    示例如下所示:

    1. import requests
    2. #百度翻译
    3. url = 'https://fanyi.baidu.com'
    4. #post请求体携带的参数,可通过开发者调试工具查看
    5. #查看步骤:NetWork选项->Headers选项->Form Data
    6. data = {'from': 'zh',
    7. 'to': 'en',
    8. 'query': '编程帮www.biancheng.net你好'
    9. }
    10. response = requests.post(url, data=data)
    11. print(response)

    输出结果:

    查看 Form Data 的步骤,如下图所示:

    1:Chrome开发者调试工具(点击看高清图

    对象属性

    当我们使用 Requests 模块向一个 URL 发起请求后会返回一个 HttpResponse 响应对象,该对象具有以下常用属性:

    HttpResponse响应对象属性

    常用属性

    说明

    encoding

    查看或者指定响应字符编码

    status_code

    返回HTTP响应码

    url

    查看请求的 url 地址

    headers

    查看请求头信息

    cookies

    查看cookies 信息

    text

    以字符串形式输出

    content

    以字节流形式输出,若要保存下载图片需使用该属性。


    使用示例如下所示:

    1. import requests
    2. response = requests.get('http://www.baidu.com')
    3. print(response.encoding)
    4. response.encoding="utf-8"    #更改为utf-8编码
    5. print(response.status_code)  # 打印状态码
    6. print(response.url)          # 打印请求url
    7. print(response.headers)      # 打印头信息
    8. print(response.cookies)      # 打印cookie信息
    9. print(response.text)  #以字符串形式打印网页源码
    10. print(response.content) #以字节流形式打印

    输出结果:

    #编码格式

    ISO-8859-1

    #响应码

    200

    #url地址

    http://www.baidu.com/

    #请求头信息

    {'Cache-Control': 'private, no-cache, no-store, proxy-revalidate, no-transform', 'Connection': 'keep-alive', 'Content-Encoding': 'gzip', 'Content-Type': 'text/html', 'Date': 'Mon, 08 Mar 2021 05:19:33 GMT', 'Last-Modified': 'Mon, 23 Jan 2017 13:27:29 GMT', 'Pragma': 'no-cache', 'Server': 'bfe/1.0.8.18', 'Set-Cookie': 'BDORZ=27315; max-age=86400; domain=.baidu.com; path=/', 'Transfer-Encoding': 'chunked'}

    #查看cookies信息

    ]>

    ...内容过长,此处省略后两项输出

    Requests库应用

    示例应用:使用 Requsets 库下载百度图片。

    首先打开百度图片(https://image.baidu.com/),并在输入框搜索 “python logo”,然后使用 Chrome 开发者工具查看第一张图片的源地址,即 data-imgurl 所对应的 url 地址,如下所示:

    data-imgurl="https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=38785274,1357847304&fm=26&gp=0.jpg"

    可以将上述 url 粘贴至浏览器地址栏进行验证。当我们确定图片地址后,就可以使用 requests 库进行编码了:

    1. import requests
    2. url = 'https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=38785274,1357847304&fm=26&gp=0.jpg'
    3. #简单定义浏览器ua信息
    4. headers = {'User-Agent':'Mozilla/4.0'}
    5. ?#读取图片需要使用content属性
    6. html = requests.get(url=url,headers=headers).content
    7. #以二进制的方式下载图片
    8. with open('C:/Users/Administrator/Desktop/image/python_logo.jpg','wb') as f:
    9. f.write(html)

    最后,您会在桌面文件夹中找到已经下载好的图片,如下所示:


    2:Requests库简单应用

    17爬取网络图片

    本节编写一个快速下载照片的程序,通过百度图片下载您想要的前 60 张图片,并将其保存至相应的目录。本节实战案例是上一节《Python Request库安装和使用》图片下载案例的延伸。

    分析url规律

    打开百度图片翻页版(点击访问),该翻页版网址要妥善保留。其 url 规律如下:

    第一页:https://image.baidu.com/search/flip?tn=baiduimage&word=python&pn=0

    第二页:https://image.baidu.com/search/flip?tn=baiduimage&word=python&pn=20

    第三页:https://image.baidu.com/search/flip?tn=baiduimage&word=python&pn=40

    n页:https://image.baidu.com/search/flip?tn=baiduimage&word=python&pn=20*(n-1)

    百度为了限制爬虫,将原来的翻页版变为了“瀑布流”浏览形式,也就是通过滚动滑轮自动加载图片,此种方式在一定程度上限制了爬虫程序。

    写正则表达式

    通过上一节可以得知每一张图片有一个源地址如下所示:

    data-imgurl="图片源地址"

    复制图片源地址,并检查网页源代码,使用 Ctrl+F 搜索该地址,如下图所示:

    1:检查网页结构(点击看高清图


    使用上述方式依次检查几张图片,您会发现每张图片源地址,有如下三种匹配结果:

    "thumbURL":"https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=38785274,1357847304&fm=26&gp=0.jpg"

    "middleURL":"https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=38785274,1357847304&fm=26&gp=0.jpg"

    "hoverURL":"https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=38785274,1357847304&fm=26&gp=0.jpg"

    任选其一,写出图片源地址正则表达式,如下所示:

    re_bds='"hoverURL":"(.*?)"'

    编写程序代码

    下面使用 Requests 库的相应方法和属性编写程序代码,最终实现一个快速下载照片的小程序。

    1. # -*- coding:utf8 -*-
    2. import requests
    3. import re
    4. from urllib import parse
    5. import os
    6. class BaiduImageSpider(object):
    7. def __init__(self):
    8. self.url = 'https://image.baidu.com/search/flip?tn=baiduimage&word={}'
    9. self.headers = {'User-Agent':'Mozilla/4.0'}
    10. # 获取图片
    11. def get_image(self,url,word):
    12. #使用 requests模块得到响应对象
    13. res= requests.get(url,headers=self.headers)
    14. # 更改编码格式
    15. res.encoding="utf-8"
    16. # 得到html网页
    17. html=res.text
    18. print(html)
    19. #正则解析
    20. pattern = re.compile('"hoverURL":"(.*?)"',re.S)
    21. img_link_list = pattern.findall(html)
    22. #存储图片的url链接
    23. print(img_link_list)
    24. # 创建目录,用于保存图片
    25. directory = 'C:/Users/Administrator/Desktop/image/{}/'.format(word)
    26. # 如果目录不存在则创建,此方法常用
    27. if not os.path.exists(directory):
    28. os.makedirs(directory)
    29. #添加计数
    30. i = 1
    31. for img_link in img_link_list:
    32. filename = '{}{}_{}.jpg'.format(directory, word, i)
    33. self.save_image(img_link,filename)
    34. i += 1
    35. #下载图片
    36. def save_image(self,img_link,filename):
    37. html = requests.get(url=img_link,headers=self.headers).content
    38. with open(filename,'wb') as f:
    39. f.write(html)
    40. print(filename,'下载成功')
    41. # 入口函数
    42. def run(self):
    43. word = input("您想要谁的照片?")
    44. word_parse = parse.quote(word)
    45. url = self.url.format(word_parse)
    46. self.get_image(url,word)
    47. if __name__ == '__main__':
    48. spider = BaiduImageSpider()
    49. spider.run()

    程序执行结果如下图:


    2:程序执行图


    目录文件下载图如下所示:


    3:程序执行结果

    18requests库常用操作

    Requests 库中定义了七个常用的请求方法,这些方法各自有着不同的作用,在这些请求方法中 requests.get() 与 requests.post() 方法最为常用。请求方法如下所示:

    常用请求方法

    方法

    说明

    requests.request()

    构造一个请求对象,该方法是实现以下各个方法的基础。

    requests.get()

    获取HTML网页的主要方法,对应于 HTTP 的 GET 方法。

    requests.head()

    获取HTML网页头信息的方法,对应于 HTTP 的 HEAD 方法。

    requests.post()

    获取 HTML 网页提交 POST请求方法,对应于 HTTP 的 POST。

    requests.put()

    获取HTML网页提交PUT请求方法,对应于 HTTP 的 PUT。

    requests.patch()

    获取HTML网页提交局部修改请求,对应于 HTTP 的 PATCH。

    requests.delete()

    获取HTML页面提交删除请求,对应于 HTTP 的 DELETE。


    上述方法都提供了相同的参数,其中某些参数已经使用过,比如headersparams,前者用来构造请求头,后者用来构建查询字符串。这些参数对于编写爬虫程序有着至关重要的作用。本节对其他常用参数做重点介绍。

    SSL认证-verify参数

    SSL 证书是数字证书的一种,类似于驾驶证、护照和营业执照。因为配置在服务器上,也称为 SSL 服务器证书。SSL 证书遵守 SSL 协议,由受信任的数字证书颁发机构 CA(电子认证服务)颁发。 SSL 具有服务器身份验证和数据传输加密功能。

    verify参数的作用是检查 SSL 证书认证,参数的默认值为 True,如果设置为 False 则表示不检查 SSL证书,此参数适用于没有经过 CA 机构认证的 HTTPS 类型的网站。其使用格式如下:

    1. response = requests.get(
    2. url=url,
    3. params=params,
    4. headers=headers,
    5. verify=False
    6. )

    代理IP-proxies参数

    一些网站为了限制爬虫从而设置了很多反爬策略,其中一项就是针对 IP 地址设置的。比如,访问网站超过规定次数导致流量异常,或者某个时间段内频繁地更换浏览器访问,存在上述行为的 IP 极有可能被网站封杀掉。

    代理 IP 就是解决上述问题的,它突破了 IP 地址的访问限制,隐藏了本地网络的真实 IP,而使用第三方 IP 代替自己去访问网站。

    1) 代理IP池

    通过构建代理 IP 池可以让你编写的爬虫程序更加稳定,从 IP 池中随机选择一个 IP 去访问网站,而不使用固定的真实 IP。总之将爬虫程序伪装的越像人,它就越不容易被网站封杀。当然代理 IP 也不是完全不能被察觉,通过端口探测技等术识仍然可以辨别。其实爬虫与反爬虫永远相互斗争的,就看谁的技术更加厉害。

    2) proxies参数

    Requests 提供了一个代理 IP 参数proxies,该参数的语法结构如下:

    proxies = {

          '协议类型(http/https)':'协议类型://IP地址:端口号'

        }

    下面构建了两个协议版本的代理 IP,示例如下:

    proxies = {

       'http':'http://IP:端口号',

       'https':'https://IP:端口号'

    }

    3) 代理IP使用

    下面通过简单演示如何使用proxies参数,示例如下:

    1. import requests
    2. ?
    3. url = 'http://httpbin.org/get'
    4. headers = {
    5. 'User-Agent':'Mozilla/5.0'
    6. }
    7. # 网上找的免费代理ip
    8. proxies = {
    9. 'http':'http://191.231.62.142:8000',
    10. 'https':'https://191.231.62.142:8000'
    11. }
    12. html = requests.get(url,proxies=proxies,headers=headers,timeout=5).text
    13. print(html)

    输出结果:

    {

      "args": {},

      "headers": {

        "Accept": "*/*",

        "Accept-Encoding": "gzip, deflate",

        "Cache-Control": "max-age=259200",

        "Host": "httpbin.org",

        "User-Agent": "Mozilla/5.0",

        "X-Amzn-Trace-Id": "Root=1-605073b0-4f54db1b2d2cfc0c074a1193"

      },

     

      # 注意此处显示两个IP,第一个是你自己的真实IP,另外一个是对外展示的IP

      "origin": "121.17.25.194, 191.235.72.144",

      "url": "http://httpbin.org/get"

    }

    由于上述示例使用的是免费代理 IP,因此其质量、稳定性较差,可能会随时失效。如果想构建一个稳定的代理 IP 池,就需要花费成本。

    4) 付费代理IP

    网上有许多提供代理 IP 服务的网 站,比如快代理、代理精灵、齐云代理等。这些网站也提供了相关文档说明,以及 API 接口,爬虫程序通过访问 API 接口,就可以构建自己的代理 IP 池。

    付费代理 IP 按照资源类型可划分为:开发代理、私密代理、隧道代理、独享代理,其中最常使用的是开放代理与私密代理。

    开放代理:开放代理是从公网收集的代理服务器,具有 IP 数量大,使用成本低的特点,全年超过 80% 的时间都能有 3000 个以上的代理 IP 可供提取使用。

    私密代理:私密代理是基于云主机构建的高品质代理服务器,为您提供高速、可信赖的网络代理服务。私密代理每天可用 IP 数量超过 20 万个,可用率在 95 %以上,1 次可提取 IP 数量超过 700 个,可以为爬虫业务提供强大的助力。

    付费代理的收费标准根据 IP 使用的时间长短,以及 IP 的质量高低,从几元到几百元不等。89 免费代理(http://www.89ip.cn/)是一个专门提供免费代理 IP 的网站,不过想找到一个质量较高的免费代理好比大海捞针。

    用户认证-auth参数

    Requests 提供了一个auth参数,该参数的支持用户认证功能,也就是适合那些需要验证用户名、密码的网站。auth 的参数形式是一个元组,其格式如下:

    auth = ('username','password')

    其使用示例如下所示:

    1. class xxxSpider(object):
    2. def __init__(self):
    3. self.url = 'http://code.tarena.com.cn/AIDCode/aid1906/13Redis/'
    4. # 网站使用的用户名,密码
    5. self.auth = ('c语言中文网','c.biancheng.net')
    6. ?
    7. def get_headers(self):
    8. headers = {'User-Agent':"Mozilla/5.0"}
    9. return headers
    10. ?
    11. def get_html(self,url):
    12. res = requests.get(url,headers=self.get_headers(),auth=self.auth)
    13. html = res.content
    14. return html
    15. ...

    如果想更多地了解关于 Requests 库的参数,可以参考官方文档:https://requests.readthedocs.io/zh_CN/latest/

    19Proxy SwitchyOmega

    Proxy SwitchyOmega 是一款非常优秀的浏览器插件,适用于 Chrome 和 Firefox,它可以轻松快捷地管理和切换 IP 代理。

    下载安装插件

    Proxy SwitchyOmega 下载安装非常简单,除了通过 Chrome 应用商店安装之外,还可以直接访问官方网站下载相应的版本,网址为:https://proxy-switchyomega.com/download/,下载完成后,插件会被自动安装到浏览器扩展程序中,如下所示:


    1:Proxy SwitchyOmega


    安装完成后,将管理工具固定在浏览器地址栏的右侧,以方便后续使用。如下图所示:

     

     图2:固定扩展程序

    简单使用说明

    下面对该扩展程序做简单的使用说明。点击右上角刚刚安装的扩展程序,在弹出的会话框中点击“选项”,进入 SwitchyOmega 主界面, 如下所示:

     

    3:SwitchyOmega 界面

    1) 新建情景模式

    SwitchyOmega 自带  proxy(代理模式) 与 auto switch(自动切换模式),除此之外,你也可以自定义情景模式。如上图 2 所示,点击“新建情景模式” 会弹出如下会话框:


    4:新建情景模式


    按照图 3 进行相关操作,输入自定义的情景模式名称,并选择“代理服务器”类型,最后点击“创建”按钮。

    2) 配置代理服务器

    创建完成后,在弹出的会话框内完成代理服务器参数配置,如下图所示:


    5:代理服务器配置


    配置完成后切记要点击“应用选项”,否则配置不能生效。

    注意:在配置代理服务前,您应该拥有一个代理 IP,否则不能配置成功。SwitchyOmega 插件只帮助管理代理 IP,不提供代理 IP 服务器。

    3) 应用代理服务器

    最后一步:启动配置好的代理服务器,其流程如下图所示:


    5:启用代理服务器


    上图所示,“直接连接”是不使用任何代理,直接访问网页;“系统代理”则是使用当前计算机的 Internet 代理设置,而 "auto switch" 是根据自定义的列表规则,自动切换 IP 访问网站,从而避免手动切换代理 IP 的麻烦。

    4) 验证代理 IP

    按照上述步骤配置完成后,您就可以使用代理服务器去访问网站了。接下来,通过查询本机 IP 验证是否正在使用代理 IP,如下所示:


    6:查询本机IP


    此时本机的真实 IP 已经隐藏起来,当我们通过谷歌浏览器访问任何网站时,都不会留下真实的 IP 信息。如果想取消代理服务,可以直接点击“系统代理”或者“直接连接”,两者任选其一即可实现取消,当然您也可直接关闭拓展程序。