爬虫入门一

爬虫介绍

互联网由许许多多的超文本(HTML)组成,用户利用HTTP或者HTTPS协议访问网页。通俗来讲,爬虫就是我们编程来模拟用户访问网页的过程。

聚焦爬虫的基本过程如下:

  1. 访问目标url。
  2. 解析数据。
  3. 获取待访问url,回到步骤1。
  4. 数据持久化,即将爬取的数据保存到本地。

urllib介绍

urllib是Python自带的一个用于爬虫的库,其主要作用就是可以通过代码模拟浏览器发送请求。其常被用到的子模块在Python3中的为urllib.request和urllib.parse。许多第三方的爬虫库都是基于urllib,比如Requests。

最简单的爬虫

下面是get请求的爬虫

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from urllib import request
import urllib.request

def load_data():
url = "http://www.baidu.com/"
# 使用get请求获得相应
reponse = urllib.request.urlopen(url)
print(reponse)
data = reponse.read()
# 使用UTF-8解码数据
str_data = data.decode('utf-8')
print(str_data)
# 将数据保存到本地
with open("baidu.html", "w", encoding='utf-8') as f:
f.write(str_data)

if __name__ == '__main__':
load_data()

下面是post请求的爬虫,由于url只支持Ascii编码的字符,所以如果其包含中文字符,需要对其编码。

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
import urllib.request
import urllib.parse
import string

# 方法一:直接拼接,适合传少量参数时使用
def get_method_params():
url = "http://www.baidu.com/s?wd="
# 拼接字符串(汉字)
name = '风景'
final_url = url + name
print(final_url)
# 汉字没有转码
encode_new_url = urllib.parse.quote(final_url, safe=string.printable)
print(encode_new_url)
responses = urllib.request.urlopen(encode_new_url)
data = responses.read().decode('utf-8')
# 保存到本地
with open('02-encode.html', 'w', encoding='utf-8') as f:
f.write(data)

# 方法二:使用字典,适合大量参数时
def get_params():
url = 'http://www.baidu.com/s?'
params = {"wd":"中文",
"key":"zhang",
"value":"san"
}
str_params = urllib.parse.urlencode(params)
print(str_params)
final_url = url + str_params
end_url = urllib.parse.quote(final_url, safe=string.printable)
response = urllib.request.urlopen(end_url)
data = response.read().decode('utf-8')
print(data)

if __name__ == '__main__':
get_method_params()
get_params()

请求头和代理

添加请求头

许多网站直接通过请求头,判别一次访问是由浏览器还是爬虫程序发起的,这主要是通过User-Agent字段,下面显示如何给我们的爬虫添加请求头。

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
import urllib.request

def load_baidu():
url= "https://www.baidu.com"
header = {
#浏览器的版本
"User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36"
}

#创建请求对象
request = urllib.request.Request(url)
# 构建请求对象时添加header信息
# request = urllib.request.Request(url, headers=header)
#动态的去添加head的信息
request.add_header("User-Agent","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36")
#请求网络数据(不在此处增加请求头信息因为此方法系统没有提供参数)
response = urllib.request.urlopen(request)
print(response)
data = response.read().decode("utf-8")

#获取到完整的url
final_url = request.get_full_url()
print(final_url)

#响应头
# print(response.headers)
#获取请求头的信息(所有的头的信息)
# request_headers = request.headers
# print(request_headers)
#(2)第二种方式打印headers的信息
#注意点:首字母需要大写,其他字母都小写
request_headers = request.get_header("User-agent")
# print(request_headers)
with open("02header.html","w")as f:
f.write(data)

if __name__ == '__main__':
load_baidu()

设置代理服务器

有些网站会通过限制ip的访问频率来反爬虫,我们可以通过代理来通过这一限制,所谓代理就是我们通过中间服务器去访问网页,中间服务器再将访问结果传给我们。代理分为三种:

  1. 透明。目标主机知道这是代理,也知道我们主机的ip。
  2. 匿名。目标主机知道这是代理,但不知道我们主机的ip。
  3. 高匿。目标主机不知道这是代理,也不知道我们主机的ip。

下面演示免费代理的设置方法。

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
import urllib.request
def create_proxy_handler():
url = "https://blog.csdn.net/m0_37499059/article/details/79003731"

#添加代理
proxy = {
#免费代理的写法
"http":"120.77.249.46:8080",
#付费代理的写法
# "http":"username:pwd@115.123.23.2“


}
#代理处理器
proxy_handler = urllib.request.ProxyHandler(proxy)

#创建自己opener
opener = urllib.request.build_opener(proxy_handler)
#拿着代理ip去发送请求
response = opener.open(url)
data = response.read().decode("utf-8")


with open("03header.html", "w")as f:
f.write(data)

if __name__ == '__main__':
create_proxy_handler()

下面演示如何设置付费代理。

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
import urllib.request

#付费的代理发送
#1.用户名密码(带着)
#通过验证的处理器来发送

def money_proxy_use():
# #第一种方式付费代理发送请求
# #1.代理ip
# money_proxy ={"http":"username:pwd@192.168.12.11:8080"}
# #2.代理的处理器
# proxy_handler=urllib.request.ProxyHandler(money_proxy)
#
# #3.通过处理器创建opener
# opener = urllib.request.build_opener(proxy_handler)
# #4.open发送请求
# opener.open("http://www.baidu.com")
# #第二种方式发送付费的ip地址
use_name = "abcname"
pwd = "123456"
proxy_money = "123.158.63.130:8888"
#2.创建密码管理器,添加用户名和密码
password_manager = urllib.request.HTTPPasswordMgrWithDefaultRealm()
#uri定位 uri>url
#url 资源定位符
password_manager.add_password(None,proxy_money,use_name,pwd)
#3.创建可以验证代理ip的处理器
handle_auth_proxy = urllib.request.ProxyBasicAuthHandler(password_manager)
#4.根据处理器创建opener
opener_auth = urllib.request.build_opener(handle_auth_proxy)
#5.发送请求
response = opener_auth.open("http://www.baidu.com")
print(response.read())

if __name__ == '__main__':
money_proxy_use()

爬取免费代理

下面演示如何从免费代理网站爬取ip并验证有效性的程序。

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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
from http.client import responses
import urllib.request
import random
from bs4 import BeautifulSoup
import requests
import random



ip_pool = []
# 爬取代理ip
def get_ips(url, n=20):
for j in range(1, n):
current_url = url + str(j) +"/"
header = {"User-Agent":"Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9.1.6) ",
"Accept" : "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"}

response = requests.get(current_url, headers=header)
print(response.status_code)
html = response.text
soup = BeautifulSoup(html, 'lxml')
for tr in soup.find_all('tr'):
if tr.find('td') == None:
continue
ip = tr.find(attrs={'data-title':'IP'}).get_text()
port = tr.find(attrs={'data-title':'PORT'}).get_text()
typ = tr.find(attrs={'data-title':"类型"}).get_text()
ip_pool.append({typ.lower():ip + ":" + port})

valiation_url = 'https://blog.csdn.net/m0_37499059/article/details/79003731'
useragents = [
'Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19',
'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0',
'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36',
'Mozilla/5.0 (compatible; WOW64; MSIE 10.0; Windows NT 6.2)',
'Opera/9.80 (Windows NT 6.1; WOW64; U; en) Presto/2.10.229 Version/11.62',
'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; en-US) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27'
]


def get_proxy():
user_agent = random.choice(useragents)
ip = random.choice(ip_pool)
return user_agent, ip

def create_proxy_opener(ip):
handler = urllib.request.ProxyHandler(ip)
opener = urllib.request.build_opener(handler)
return opener

def valiation_proxy(ip_pool):
pools = []
for ip in ip_pool:
request = urllib.request.Request(valiation_url, headers={"User-Agent":'Mozilla/5.0 (compatible; WOW64; MSIE 10.0; Windows NT 6.2)'})
# request.add_header("User-Agent", user_agent)
opener = create_proxy_opener(ip)
try:

response = opener.open(request)
pools.append(ip)
except Exception as e:
print(e)

return pools

url = 'https://www.kuaidaili.com/free/inha/'
get_ips(url, 50)
print(ip_pool)
ip_pools = valiation_proxy(ip_pool)
import json
data = json.dumps(ip_pools)
with open("ip_pools.npz", 'w') as f:
f.write(data)
print(ip_pools)

HTTP认证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from urllib import request
import urllib.request

url = 'https://ssr3.scrape.center/'
# 构建一个密码管理对象,用来保存需要处理的用户名和密码
passwordmgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
# 指定 url 、username 、password
passwordmgr.add_password(None, url, 'admin', 'admin')
# 构建一个用户名/密码验证的处理器对象
handler = urllib.request.HTTPBasicAuthHandler(passwordmgr)
# 创建opener对象,这个opener对象在发送请求时就相当于验证成功了
opener = urllib.request.build_opener(handler)

response = opener.open(url)
print(response.read().decode('utf-8'))

处理cookies

下面演示如何登录网站,并保存下cookies

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
from http import cookiejar
import urllib.request
import urllib.parse


# 1. 代码登录
# 1.1 登录网址
log_url = 'https://www.yaozh.com/login'

# 1.2 登录上传的参数
data = {
'username': '*****',
'pwd': '******',
'formhash': '16364D7F2C',
'backurl': r'https%3A%2F%2Fwww.yaozh.com%2F'
}

# 参数转码
data = urllib.parse.urlencode(data).encode('utf-8')

# 构造request请求
# 添加请求头
headers = {
"User=Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36",
'Host': 'www.yaozh.com',
'Origin': 'https://www.yaozh.com',
'Referer': 'https://www.yaozh.com/login/proxy?time=1602222533216'
}
request = urllib.request.Request(log_url, headers=headers, data=data)

# http.cookiejar 模块定义了用于自动处理 HTTP cookie 的类
cookie_jar = cookiejar.CookieJar()
# 定义有添加cookie功能的处理器
cookie_handler = urllib.request.HTTPCookieProcessor(cookie_jar)
# 根据处理器生成opener
opener = urllib.request.build_opener(cookie_handler)
# 带着参数,发送post请求
# 如果登录成功,cookiejar自动保存cookie
responese = opener.open(request)

# 2. 代码带着cookie去访问个人中心
center_url = 'https://www.yaozh.com/member/'
request = urllib.request.Request(center_url, headers=headers)
response = opener.open(request)
data= response.read().decode('utf-8')
with open("02cookie.html", "w", encoding='utf-8') as f:
f.write(data)