网络爬虫系列的第二篇,使用python自带的urllib库开发爬虫

这里只做简单的介绍,以便后续使用


urllib库简介

urllib 是一个 Python 内置包,不需要额外安装即可使用,包里面包含了几个用来处理 url 的模块,是一个最基本的网络请求库,可以模拟浏览器的行为,向指定的服务器发送一个请求,并可以保存服务器返回的数据。[1]

  • urllib.request,用来打开和读取 url,意思就是可以用它来模拟发送请求,就像在浏览器里输入网址然后敲击回车一样,获取网页响应内容。
  • urllib.error,用来处理 urllib.request 引起的异常,保证程序的正常执行。
  • urllib.parse,用来解析 url,可以对 url 进行拆分、合并等。
  • urllib.robotparse,用来解析 robots.txt 文件,判断网站是否能够进行爬取。[2]

urllib.request 模块

request.urlopen 函数

urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
  • url,必选参数,是一个 str 字符串或者Request 对象
  • data,如果传递 data 参数,urlopen 将使用 HTTP POST 方式请求,否则为 HTTP GET 请求。
  • timeout,可选参数,设置超时时间(未设置时使用全局默认超时时间),以秒为单位计时,若请求超出了设置时间还未得到响应则抛出异常。
  • 剩余的参数不常用,不再详细介绍

示例:[3]

from urllib import request

resp = request.urlopen("http://www.baidu.com")
print(resp.read())

运行结果是输出 http://www.baidu.com 的源代码

也可以通过这种方式获取状态码

from urllib import request

resp = request.urlopen("http://www.baidu.com")
print(resp.getcode())

运行结果:

200

request.urlretrieve 函数

urlretrieve(url, filename=None, reporthook=None, data=None)

python3中urllib.request模块提供的urlretrieve()函数。urlretrieve()方法直接将远程数据下载到本地。[4]

  • 参数url:下载链接地址
  • 参数filename:指定了保存本地路径(如果参数未指定,urllib会生成一个临时文件保存数据。)
  • 参数reporthook:是一个回调函数,当连接上服务器、以及相应的数据块传输完毕时会触发该回调,我们可以利用这个回调函数来显示当前的下载进度。
  • 参数data:返回一个包含两个元素的(filename, headers) 元组,filename 表示保存到本地的路径,header表示服务器的响应头

示例:

from urllib import request

request.urlretrieve("http://www.baidu.com","baidu.html")

通过这个代码可以下载百度的网页到当前文件夹

urllib.parse 模块

parse.urlencode函数

urlencode 可以把字典数据转换为 URL 编码的数据,用浏览器发送请求的时候,如果url 中包含了中文或者其他特殊字符,那么浏览器会自动编码,如果使用代码发送请求,那么就必须手动的进行编码

示例:

from urllib import parse
params = {'name': '姓名', 'age': '18', 'greet': 'hello world'}
result = parse.urlencode(params)
print(result)

运行结果:

name=%E5%A7%93%E5%90%8D&age=18&greet=hello+world

parse.parse_qs函数

对URL进行解码,可以理解为urlencode的逆过程

urlparse和urlsplit函数

两个函数都用来对URL进行分割,两者用法相同,区别在于urlparse可以分割出URL的params属性,urlsplit则不能[5]
示例:

from urllib import parse
url = 'http://www.baidu.com/s?wd=demo&time=2021#3'
result = parse.urlsplit(url)
print(result)
print('scheme:',result.scheme)
print('netloc:',result.netloc)
print('path:',result.path)
print('query:',result.query)

运行结果:

SplitResult(scheme='http', netloc='www.baidu.com', path='/s', query='wd=demo&time=2021', fragment='3')
scheme: http
netloc: www.baidu.com
path: /s
query: wd=demo&time=2021

Request类

class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)

Request类是request下一个非常强大的类,用于在请求的时候加上请求头,例如User-Agent,以及POST请求所需要的data

示例:

from urllib import request, parse

url = 'https://www.lagou.com/jobs/positionAjax.json?needAddtionalResult=false'

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537'
                  '.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36',
    'Referer': 'https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput=',
    'cookie': ''
}

data = {
    'first': 'ture',
    'pn': 1,
    'kd': 'python'
}
req = request.Request(url, headers=headers, data=parse.urlencode(data).encode('utf-8'), method='POST')
resp = request.urlopen(req)
print(resp.read().decode('utf-8'))

这段代码用于从“拉勾网”获取有关“python”的职位信息,拉勾网具有一定反爬机制,比较适合来做练习,关于代码的解释如下:

  • URLheadersdata 如何获取?

    如下图,在拉勾网上搜索python,用f12或右键“检查”调出开发者工具,在Network上找到如下的JS文件,职位信息就在这个文件中,可以在Response页面查看职位信息,而URLheadersdata的信息在Headers中,找的对应项补充在代码中即可

从控制台找数据

  • 为何在Request中要对data的格式进行处理?
    data要先采用urlencode进行编码,但转化之后是unicode字符串,要转化成所支持的bytes数据类型,用encode进行转化

  • 最后输出时的decode作用是什么?
    默认输出为bytes数据类型,用decode解码成易读的unicode类型并采用UTF-8编码

  • 注意:cookie信息这里并没有填,找到自己的cookie填上去即可运行

TODO

⛳urlllib库的简单介绍大概就这些了,接着是关于IP代理的设置与应用

to be continued,Photo by Reuben Juarez on Unsplash