爬虫基本库的使用

83 阅读5分钟

对爬虫中基本库的使用方法进行归纳和总结

1.urllib

        首先介绍一个库urllib,利用python中的urllib库,我们可以通过指定URL,请求头,请求体等来实现所需http请求的发送,并且可以将服务器返回的响应转换为python对象,进而更方便的获取响应信息。

1.1请求(request)

1.1.1直接通过urlopen函数

response = urllib.request.urlopen(url,data=None,timeout,cafile=None,capath=None,cadefault=False,context=None)

urllib提供了一个最基本的构造http请求的方法,其中:

url是请求的URL,也是该方法唯一的必需参数,剩下的都是可选参数

利用最基本的urllib方法可以进行对网页的GET请求抓取。

1.通过URL参数

举例如下:

import urllib.request
from pprint import pprint#美化输出模块
# Press Shift+F10 to execute it or replace it with your code.
# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.


def main():
    response = urllib.request.urlopen("https://www.baidu.com/")
    pprint(response.getheaders())
    pprint(response.read())
    pprint(type(response))

# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    main()
    print("获取网页源代码成功")

对www.baidu.com进行爬取,其得到的输出内容如下:

输出请求头

[('Accept-Ranges', 'bytes'),
 ('Cache-Control', 'no-cache'),
 ('Content-Length', '227'),
 ('Content-Security-Policy',
  "frame-ancestors 'self' https://chat.baidu.com http://mirror-chat.baidu.com "
  'https://fj-chat.baidu.com https://hba-chat.baidu.com '
  'https://hbe-chat.baidu.com https://njjs-chat.baidu.com '
  'https://nj-chat.baidu.com https://hna-chat.baidu.com '
  'https://hnb-chat.baidu.com http://debug.baidu-int.com;'),
 ('Content-Type', 'text/html'),
 ('Date', 'Sat, 30 Mar 2024 14:46:40 GMT'),
 ('Pragma', 'no-cache'),
 ('Server', 'BWS/1.1'),
 ('Set-Cookie', 'BD_NOT_HTTPS=1; path=/; Max-Age=300'),
 ('Set-Cookie',
  'PSTM=1711810000; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; '
  'path=/; domain=.baidu.com'),
 ('Set-Cookie',
  'H_PS_PSSID=40169_40080_40373_40368_40398_40416_40309_40459_40481_39662_40514_40446_60041_60030_40510; '
  'path=/; expires=Sun, 30-Mar-25 14:46:40 GMT; domain=.baidu.com'),
 ('Set-Cookie',
  'BAIDUID=A42F16C36B56F67916E9DCCE5F8616FF:FG=1; Path=/; Domain=baidu.com; '
  'Max-Age=31536000'),
 ('Set-Cookie',
  'BAIDUID_BFESS=A42F16C36B56F67916E9DCCE5F8616FF:FG=1; Path=/; '
  'Domain=baidu.com; Max-Age=31536000; Secure; SameSite=None'),
 ('Traceid', '1711810000364990695416469053921881009841'),
 ('X-Ua-Compatible', 'IE=Edge,chrome=1'),
 ('X-Xss-Protection', '1;mode=block'),
 ('Connection', 'close')]

输出网页源码

(b'<html>\r\n<head>\r\n\t<script>\r\n\t\tlocation.replace(location.href.repl'
 b'ace("https://","http://"));\r\n\t</script>\r\n</head>\r\n<body>\r\n\t<nosc'
 b'ript><meta http-equiv="refresh" content="0;url=http://www.baidu.com/"></nosc'
 b'ript>\r\n</body>\r\n</html>')

输出返回类型

<class 'http.client.HTTPResponse'>

由此可以看出通过请求返回的response对象的类型是HTTPResponse

该对象包含了几种常用的方法和属性,其中有:

read()获取网页源码

getheader(str)获取请求头的某一项

getheaders()获取全部请求头

msg,version,status,reason,debuglevel,closed等属性

2.使用data参数

添加data参数可以向目标网站传递参数,此时请求模式不再是GET而是POST

注意:添加参数时需要将data转化为bytes类型

def main():
    data = bytes(urllib.parse.urlencode({'name':'germey'}),encoding='utf-8')#urlencode方法将字典参数转化为字符串,再用utf-8编码
    response = urllib.request.urlopen('https://www.httpbin.org/post',data=data)
    print(response.read().decode('utf-8'))
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    main()
    print("获取网页源代码成功")

输出结果如下:

{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "name": "germey"
  }, 
  "headers": {
    "Accept-Encoding": "identity", 
    "Content-Length": "11", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "www.httpbin.org", 
    "User-Agent": "Python-urllib/3.10", 
    "X-Amzn-Trace-Id": "Root=1-66082eda-1365c31c6515444a1f883304"
  }, 
  "json": null, 
  "origin": "42.234.23.197", 
  "url": "https://www.httpbin.org/post"
}

从form字段中发现了germey,这表明是在以POST方式传递数据

3.使用timeout参数

timeout参数意为设置超时时间,单位为秒,如果请求超出了这个时间还没有收到响应,就会抛出异常。如果不设置该参数,则会使用全局默认时间,这个参数支持http,https和ftp协议。

def main():
    response = urllib.request.urlopen('https://www.httpbin.org/get',timeout=0.1)
    print(response.read())
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    main()
    print("获取网页源代码成功")

设置timeout为0.1,抛出URLError超时异常

也可以利用try-except进行异常处理

def main():
    try:
        response = urllib.request.urlopen('https://www.httpbin.org/get',timeout=0.1)
    except urllib.error.URLError as e:
        if isinstance(e.reason,socket.timeout):
            print('time out......')

1.1.2通过Request

如果需要向请求中加入请求头,那么直接通过urlopen显然是不够用的,于是我们就可以用Request类来构建含有更多信息的请求头

具体方法如下:

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

1.URL必选参数,用于请求URL

2.上传data参数,必需为bytes类型,如果数据是字典必需使用parse模块的urlencode方法进行编码

3.headers是一个字典,也就是请求头,可以直接构造也可以请求方法添加

4.是指请求方的host地址或者IP地址

5.method表示请求方法,如GET,POST,PUT

6.表示用户有没有足够的权限来接收响应,例如请求网页中的图片,但没有抓取图片的权限,那么该值设为True

传入多个参数构建Request类

def main():
    url = 'https://www.httpbin.org/post'
    headers = {
        'User-Agent':'Mozilla/4.0(compatible;MSIE 5.5;Windows NT)',
        'Host':'www.httpbin.org'
    }
    dict = {'name':'germey'}
    data = bytes(parse.urlencode(dict),encoding='utf-8')
    req = request.Request(url=url,data=data,headers=headers,method='POST')
    response = request.urlopen(req)
    print(response.read().decode('utf-8'))
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    main()
    print("获取网页源代码成功")

返回结果如下:

{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "name": "germey"
  }, 
  "headers": {
    "Accept-Encoding": "identity", 
    "Content-Length": "11", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "www.httpbin.org", 
    "User-Agent": "Mozilla/4.0(compatible;MSIE 5.5;Windows NT)", 
    "X-Amzn-Trace-Id": "Root=1-66083875-0ddb23e34425ee743ece6bcb"
  }, 
  "json": null, 
  "origin": "42.234.23.197", 
  "url": "https://www.httpbin.org/post"
}

从返回结果可知,成功设置了data,headers和method

其中对User-Agent的设置通常是为了伪装浏览器。从上图可知我们成功伪装成了浏览器对网站进行访问

1.1.3验证,代理和cookie用法

待续......