Python爬虫

网络爬虫之网络请求

说明:此博客有关爬虫的内容均学习自B站:up主:神奇的老黄。视频链接:

urllib库

安装urllib库

  1. pip命令pip install urllib
  2. pycharm->菜单栏的file->setting->Project Interpreter->点击”+”号->搜索urllib库安装即可

使用

  1. urlopen打开网址并读取内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#encoding: utf-8
from urllib import request,parse


# 打开地址
req=request.urlopen("http://www.baidu.com")

# 读取页面所有内容代码
print(req.read())
# 读取一行
# print(req.readline())
# 读取多行
# print(req.readlines())
# 读取状态码
# print(req.getcode())
  1. urlretrieve函数保存数据到文件

    1
    2
    3

    # 保存文件
    ret = request.urlretrieve("http://www.baidu.com","baidu.html")
  2. 编码与解码

1
2
3
4
5
6
7
8
9
10
11
12
13
# 编码与解码
params={'name':'张三','age':'18','greet':'hallo word'}#字典
# 编码
qu = parse.urlencode(params)
print(qu)
url = "http://www.baidu.com/s"
url = url+"?"+qu
print(url)

qs = parse.parse_qs(url)
print(qs)

# 解码使用 urllib.parse.unquote()

运行结果:

1
2
3
name=%E5%BC%A0%E4%B8%89&age=18&greet=hallo+word
http://www.baidu.com/s?name=%E5%BC%A0%E4%B8%89&age=18&greet=hallo+word
{'http://www.baidu.com/s?name': ['张三'], 'age': ['18'], 'greet': ['hallo word']}

  1. urlparse和urlsplit函数分割网址
1
2
3
4
5
6
7
# 网址分割
url = 'http://www.baidu.com/s?wd=python&username=abc#1'
result1 = parse.urlparse(url)
print(result1)

result2 = parse.urlsplit(url)
print(result2)

运行结果:

1
2
ParseResult(scheme='http', netloc='www.baidu.com', path='/s', params='', query='wd=python&username=abc', fragment='1')
SplitResult(scheme='http', netloc='www.baidu.com', path='/s', query='wd=python&username=abc', fragment='1')

让你的爬虫更加人性化

这里要从urllib库中导入request

  1. 添加headers
    标头 (header) 是服务器以HTTP协议传HTML资料到浏览器前所送出的字串

  2. Referer也是包括在Request Headers里面的信息,添加此选项,可以让你的爬虫更人性化

  3. 添加data数据,GET请求的请求参数是直接包含在URL中了,而POST请求的请求参数则不会出现在URL中,而是要经过单独的封装处理,这就用到data了。

  4. 以下是包括上述的一个爬取电驴登录界面的例子
    代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #encoding: utf-8
    from urllib import request,parse

    url = 'http://secure.verycd.com/signin'

    headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.5944.400 LBBROWSER/10.1.3378.400',
    'Referer':'http://secure.verycd.com/signin'
    }

    data = {
    'username':'11111',
    'password':'1e312r',
    'continue':'http://www.verycd.com',
    'fk':'',
    'save_cookie':'1',
    'login_submit':'登录'
    }

    req = request.Request(url,headers=headers,
    data = parse.urlencode(data).encode('utf-8'),method = 'POST')
    # 也可以通过Request.add_header()来添加
    resp = request.urlopen(req)
    print(resp.read().decode('utf-8'))

ProxyHandler处理器(代理):

  1. 代理的原理:在请求目的网站之前,我们先请求代理服务器,然后让代理服务器去请求目的网站,代理服务器拿到目的网站的数据后,再转发给我们。
  2. 一些好用的网站:
  3. 在代码中使用代理:
    • 使用urllib.request.ProxyHandler,传入一个代理,这个代理是一个字典,字典的key依赖于代理服务器能够接收的类型,一般是http或者https,值是ip:port
    • 使用上一步创建的handler,以及request.build_opener创建一个opener对象。
    • 使用上一步创建的opener,调用open函数,发起请求。
      示例代码如下:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      from urllib import  request

      # 未使用代理
      url = 'http://httpbin.org/ip'
      req = request.urlopen(url)
      print(req.read())

      # 使用代理
      url = 'http://httpbin.org/ip'
      #下面的代理ip是通过我们网站得到的一些免费代理ip
      handler = request.ProxyHandler({"http":"114.113.220.192:80"})
      opener = request.build_opener(handler)
      req = opener.open(url)
      print(req.read())

你用的免费代理可能不会成功访问,所以要多试几个哦

Cookie模拟登录

Cookie,指某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密)。在网站中,http请求是无状态的。也就是说即使第一次和服务器连接后并且登录成功后,第二次请求服务器依然不能知道当前请求是哪个用户。cookie 的出现就是为了解决这个问题,第一次登录后服务器返回一些数据(cookie) 给浏览器,然后浏览器保存在本地,当该用户发送第二次请求的时候,就会自动的把上次请求存储的cookie 数据自动的携带给服务器,服务器通过浏览器携带的数据就能判断当前用户是哪个了。cookie 存储的数据量有限,不同的浏览器有不同的存储大小,但-般不超过4KB。因此使用cookie只能存储一些小量的数据。
cookie的格式:

1
Set-Cookie: NAME=VALUE; Expires /Max-age=DATE: Path=PATH; Domain=DOMAIN NAME: SECURE

参数意义:

- NAME: cookie的名字。
- VALUE: cookie的值。
- Expires : cookie的过期时间。
- Path: cookie作用的路径。
- Domain: cookie作用的域名。
- SECURE: 是否只在https协议下起作用。

比如说有些网站需要登录后才能访问某个页面,在登录之前,你想抓取某个页面内容是不允许的,他会给你自动跳转到登录或注册页面了。那么我们可以利用Urllib2库保存我们登录的Cookie,然后再抓取其他页面就达到目的了。

  1. 第一种解决方案:在headers里添加key:Cookie成员,value:也是包括在Request Headers里面的。
    这里用cookie爬取某一微博博主界面
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # coding:utf-8
    from urllib import request

    url = 'https://weibo.com/seize?refer_flag=0000015010_&from=feed&loc=avatar&is_all=1'

    headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.5944.400 LBBROWSER/10.1.3378.400',
    'Cookie':'数据太多省略'
    }

    req = request.Request(url = url,headers= headers)
    resp = request.urlopen(req)
    with open('weibo.html','w',encoding='utf-8') as fp:
    fp.write(resp.read().decode('utf-8','ignore'))

虽然最后结果是返回给你的是一个假的代码,但方法就是这样。
还要说明一点:这里的write函数写入的必须是str类型(read()读出来是一个bytes类型),bytes通过decode变成str,str通过encode变成bytes类型

  1. 第二种方法:http.cookiejar模板

http.cookiejar模块:

该模块主要的类有CookieJary FileCookieJar、 MoillaCookieJar、 LWPCookieJar。这四个类的作用分别如下:

  • CookieJar:管理HTTP cookie值、存储HTTP请求生成的cookie、向传出的HTTP请求添加cookie的对象。整个cookie都存储在内存中,对CookieJar实例进行垃圾回收后cookie也将丢失。
  • FileCookieJar (flename,delayload=None,policy=None):从CookieJar派生而来,用来创建FileCookieJar实例,检索cookie信息并将cookie存储到文件中。filename是存储cookie的文件名。delayload为True时支持延迟访问访问文件,即只有在需要时才读取文件或在文件中存储数据。
  • MoillaCookieJar (filename,delayload=None,policy=None):从FileCookieJa派生而来,创建与Mozilla浏览器cookies.txt兼容的FileCookieJar实例。
  • LWPCookieJar (filename,delayload=None,policy=None):从FileCookieJar派生 而来,创建与libwww-perl标准的Set-Cookie3文件格式兼容的FileCookieJar实例。

下面利用http.cookiejar和request .HTTPCookieProcessor登录人人网,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#encoding: utf-8

from urllib import request
from urllib import parse
from http.cookiejar import CookieJar

#全局
headers = {
'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36"
}

def get_opener():
# 1. 登录
# 1.1 创建一个cookiejar对象
cookiejar = CookieJar()
# 1.2 使用cookiejar创建一个HTTPCookieProcess对象
handler = request.HTTPCookieProcessor(cookiejar)
# 1.3 使用上一步创建的handler创建一个opener
opener = request.build_opener(handler)
return opener


def login_renren(opener):
# 1.4 使用opener发送登录的请求(人人网的邮箱和密码)
# 把这些cookie数据写到opener里面
data = {
'email':"970138074@qq.com",
'password': "pythonspider"
}
login_url = "http://www.renren.com/PLogin.do"
req = request.Request(login_url,data=parse.urlencode(data).encode('utf-8'),headers=headers)
opener.open(req)


def visit_profile(opener):
# 2. 访问个人主页
dapeng_url = "http://www.renren.com/880151247/profile"
# 获取个人主页的页面的时候,不要新建一个opener
# 而应该使用之前的那个opener,因为之前的那个opener已经包含了登录所需要的cookie信息
req = request.Request(dapeng_url,headers=headers)
resp = opener.open(req)
with open('renren.html','w',encoding='utf-8') as fp:
fp.write(resp.read().decode('utf-8'))


if __name__ == '__main__':
opener = get_opener()
login_renren(opener)
visit_profile(opener)

保存cookie到本地

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#encoding: utf-8

from urllib import request
from http.cookiejar import MozillaCookieJar

cookiejar = MozillaCookieJar('cookie.txt') # 建立对象
handler = request.HTTPCookieProcessor(cookiejar) #
opener = request.build_opener(handler)

resp = opener.open('http://httpbin.org/cookies/set?course=anzhusen')
# # 浏览器会话结束cookie信息就会删掉,到达过期时间了
cookiejar.save()#运行结果为空
# 解决办法:
# 保存cookie即将过期的cookie信息
# cookiejar.save(ignore_discard=True)
# 运行结果
# httpbin.org FALSE / FALSE course anzhusen

加载本地的cookie信息并使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#encoding: utf-8

from urllib import request
from http.cookiejar import MozillaCookieJar

cookiejar = MozillaCookieJar('cookie.txt')
# 把本地的cookie信息(以前用过的cookie信息),加载到cookiejar对象中。
cookiejar.load(ignore_discard=True) # 参数表示把已经过期的cookie信息也加载进来
handler = request.HTTPCookieProcessor(cookiejar)
opener = request.build_opener(handler)

resp = opener.open('http://httpbin.org/cookies')
for cookie in cookiejar:
print(cookie)

# 运行结果:
# <Cookie course=anzhusen for httpbin.org/>

Requests库

发送get请求:

发送get请求,直接调用requests.get就可以了。想要发送什么类型的请求,就调用什么方法。

1
response = requests.get("https://www.baidu.com/")

response的一些属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import requests

kw = {'wd':'中国'}

headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}

# params 接收一个字典或者字符串的查询参数,字典类型自动转换为url编码,不需要urlencode()
response = requests.get("http://www.baidu.com/s", params = kw, headers = headers)

# 查看响应内容,response.text 返回的是Unicode格式的数据
print(response.text)

# 查看响应内容,response.content,返回的字节流数据
print(response.content)

# 查看完整url地址
print(response.url)

# 查看响应头部字符编码
print(response.encoding)

# 查看响应码
print(response.status_code)
response.text和response.content的区别:
  1. response.content:这个是直接从网络上面抓取的数据。没有经过任何解码。所以是一个bytes类型。其实在硬盘上和在网络上传输的字符串都是bytes类型。
  2. response.text:这个是str的数据类型,是requests库将response.content进行解码的字符串。解码需要指定一个编码方式,requests会根据自己的猜测来判断编码的方式。所以有时候可能会猜测错误,就会导致解码产生乱码。这时候就应该使用response.content.decode('utf-8')进行手动解码。这里不一定是’utf-8’,你可以检查元素网页的编码格式

发送post请求:

发送post请求非常简单。直接调用requests.post()方法就可以了。
如果返回的是json数据。那么可以调用response.json()来将json字符串转换为字典或者列表。

使用代理:

在请求方法中,传递proxies参数就可以了。例示代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
import  requests

url = 'http://httpbin.org/get'
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.5944.400 LBBROWSER/10.1.3378.400'

}
proxy = {
'http':'163.204.243.182:9999'
}
resp = requests.get(url ,headers = headers,proxies = proxy)

print(resp.text)

处理cookie:

如果想要在多次请求中共享cookie。那么应该使用session。示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import requests
url = "http://www.renren.com/PLogin.do"
data = {"email":"970138074@qq.com",'password':"pythonspider"}
headers = {
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36"
}

session = requests.Session()
# 访问登录页面,并把信息存储在seesion里面
session.post(url,data=data,headers=headers)
# 用这个session去获取需要登录后才能访问的界面
response = session.get('http://www.renren.com/880151247/profile')
with open('renren.html','w',encoding='utf-8') as fp:
fp.write(response.text)

处理没有授权的https协议:

对于那些已经不被信任的SSL整数的网站,添加一个verify参数,示例代码如下:

1
2
resp = requests . get( http://www.12386. cn/mormhweb/' ,verify=False)
print(resp. content . decode("utf-8'))

你可以对我进行打赏哦