上一篇文章我们对爬虫有了一个初步认识, 本篇文章我们开始学习 Python 爬虫实例.
在 Python 中有很多库可以用来抓取网页, 其中内置了 urllib 模块, 该模块就能实现我们基本的网页爬取.
在 Python2.x 和 Python3.x 中 urllib 模块是不一样的, 但是用法上差不多, 我们先用 Python2.x 中的 urllib 来实现一个 demo.
在 Python2.x 中内置了 urllib 模块, 但是 Python 创始人 Guido van Rossum 觉得其太臃肿了, 于是又写了一个 urllib2, 两者有很多不同, 最显著的如下:
(1)urllib 仅可以接受 URL, 不能创建, 设置 headers 的 request 类实例;
(2)但是 urllib 提供 urlencode()方法用来 GET 查询字符串的产生, 而 urllib2 则没有(这是 urllib 和 urllib2 经常一起使用的主要原因)
(3)编码工作使用 urllib 的 urlencode()函数, 帮我们讲 key:value 这样的键值对转换成'key=value'这样的字符串, 解码工作可以使用 urllib 的 unquote()
函数
我们就使用 urllib2 来实现一个简单的爬虫:
- # 导入 urllib2 库
- import urllib2
- # 向指定的 url 发送请求, 并返回服务器响应的类文件对象
- response = urllib2.urlopen("http://www.baidu.com")
- # 类文件对象支持 文件对象的操作方法, 如 read()方法读取文件全部内容, 返回字符串
- html = response.read().decode("utf-8")
- # 打印字符串
- print(HTML)
在上面的代码中我们其实就相当于模拟了查看百度首页, 然后获取百度首页的 HTML 内容.
urllib2 在 python3.x 中被改为 urllib.request,python2.x 的 urllib 和 urllib2 在 python3.x 中合并为 urllib
在 Python3.x 中实现上面的代码如下:
- # 导入 urllib 库
- import urllib.request
- # 向指定的 url 发送请求, 并返回服务器响应的类文件对象
- response = urllib.request.urlopen("http://www.baidu.com")
- # 类文件对象支持 文件对象的操作方法, 如 read()方法读取文件全部内容, 返回字符串
- HTML = response.read().decode("utf-8")
- # 打印字符串
- print(HTML)
最终的打印结果如下, 内容太长就截一小段:
历史的车轮滚滚而来, 虽然大部分 Python 使用者还在使用 Python2.x, 但 Python3.x 肯定有其之长才被发布的, 本人作为小白, 就选取 Python3.x 学习吧.
在我们上面的例子中, urlopen()的参数就是一个 url 地址;
但是如果需要执行更复杂的操作, 比如增加 HTTP 报头, 必须创建一个 Request 实例来作为 urlopen()的参数; 而需要访问的 url 地址则作为 Request 实例的参数.
- # 导入 urllib 库
- import urllib.request
- # url 作为 Request()方法的参数, 构造并返回一个 Request 对象
- request = urllib.request.Request("http://www.baidu.com")
- # Request 对象作为 urlopen()方法的参数, 发送给服务器并接收响应
- response = urllib.request.urlopen(request)
- # 类文件对象支持 文件对象的操作方法, 如 read()方法读取文件全部内容, 返回字符串
- HTML = response.read().decode("utf-8")
- # 打印字符串
- print(HTML)
最终的打印结果一致.
新建 Request 实例, 除了必须要有 url 参数之外, 还可以设置另外两个参数:
data(默认空): 是伴随 url 提交的数据(比如要 post 的数据), 同时 HTTP 请求将从 "GET" 方式 改为 "POST" 方式.
headers(默认空): 是一个字典, 包含了需要发送的 HTTP 报头的键值对.
这两个参数下面会说到.
但是这样直接用 urllib 给一个网站发送请求的话, 确实略有些唐突了, 就好比, 人家每家都有门, 你以一个路人的身份直接闯进去显然不是很礼貌. 而且有一些站点不喜欢被程序 (非人为访问) 访问, 有可能会拒绝你的访问请求.
但是如果我们用一个合法的身份去请求别人网站, 显然人家就是欢迎的, 所以我们就应该给我们的这个代码加上一个身份, 就是所谓的 User-Agent 头.
浏览器 就是互联网世界上公认被允许的身份, 如果我们希望我们的爬虫程序更像一个真实用户, 那我们第一步, 就是需要伪装成一个被公认的浏览器. 用不同的浏览器在发送请求的时候, 会有不同的 User-Agent 头.
现在我们就来加一个 User-Agent 的报头.
当我们打开 https://www.baidu.com/ , 我们在开发者工具的 Network 下, 我们会找到一个
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) ApplewebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36
当然还有 Accept,Host,Cookie 等信息, 这里我们先不考虑, 后期会讲到.
- # 导入 urllib 库
- import urllib.request
- import ssl
- # 取消代理验证
- ssl._create_default_https_context = ssl._create_unverified_context
- # User-Agent
- headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"}
- # url 作为 Request()方法的参数, 构造并返回一个 Request 对象
- request = urllib.request.Request("http://www.baidu.com",headers=headers)
- # Request 对象作为 urlopen()方法的参数, 发送给服务器并接收响应
- response = urllib.request.urlopen(request)
- # 类文件对象支持 文件对象的操作方法, 如 read()方法读取文件全部内容, 返回字符串
- HTML = response.read().decode("utf-8")
- # 打印字符串
- print(HTML)
在上面的代码中, 我们又引入了 ssl 模块, 由于现在百度使用的是 https 协议, 进入页面需要代理验证, 为了不必要的麻烦, 我们干脆取消代理验证, 所以用到了 ssl 模块.
然后我们定义了一个 headers 的变量, 即响应头信息, 然后我们在 Request 的第二个形参中将 headers=headers, 这样我们在请求 https://www.baidu.com/ , 就相当于我们手动在浏览器输入 url 链接是一样的效果.
来源: https://www.cnblogs.com/weijiutao/p/10735533.html