Py2.x:
- Urllib库
- Urllib2库
Py3.x:
- Urllib库
变化:
-
在python2.x中使用import urllib2 对应的,在python3.x会使用import urllib.request, urllib.error。
-
在Python2.x使用import urllib 对应的,在python3.x中会使用import urllib.request,urllib.error, urllib.parse。
-
在python2.x中使用import urlparse 对应的,在python3.x中会使用import urllib.parse。
-
在python2.x中石油import urlencode 对应的,在python3.x中会使用import urllib.parse.urlencode。
-
在python2.x中使用import urlencode 对应的,在python3.x中会使用import urllib.parse.urlencode。
-
在python2.x中使用import urllib.quote 对应的, 在python3.x中会使用import urllib.request.quote。
-
在python2.x中使用import urlib.CookieJar 对应的, 在python3.x中会使用http.CookieJar。
-
在python2.x中使用urllib2.Request 对应的,在python3.x中会使用urllib.request.Request。
快速爬取一个网页
#!/usr/bin/env python
# -*- utf-8 -*-
import urllib.request
file = urllib.request.urlopen('http://www.baidu.com')
data = file.read() # 读取全部
dataline = file.readline() # 读取一行内容
fhandle = open("./1.html", "wb") # 将爬取网页保存在同目录下,命名为1
fhandle.write(data)
fhandle.close()
浏览器的模拟
应用场景:有些网页为了防止别人恶意采集其信息所以进行了一些反爬虫的设置,而我们又想进行爬取。
解决方法:设置一些Headers信息(User-Agent),模拟成浏览器去访问这些网站。
#!/usr/bin/env python
#-*- utf-8 -*-
# 浏览器的模拟
# 应用场景:有些网页为了防止别人恶意采集其信息所以进行了一些反爬虫的设置,而我们又想进行爬取。
# 解决方法:设置一些Headers信息(User-Agent),模拟成浏览器去访问这些网站。
import urllib.request
import urllib.parse
url = 'http://www.baidu.com'
header = {
'User-Agent':'Mozilla/5.0 (Window NT 6.1; WOW64) AppleWebkit/537.36 (KHTML,like Gecko) Chrome/58.0.3029.96 Safari/537.36'
}
request = urllib.request.Request(url, headers=header)
reponse = urllib.request.urlopen(request).read()
fhandle = open("./baidu.html", "wb")
fhandle.write(reponse)
fhandle.close()
代理服务器的设置
应用场景:使用同一个IP去爬取同一个网站上的网页,久了之后会被该网站服务器屏蔽。
解决方法:使用代理服务器。(使用代理服务器去爬取某个网站的内容的时候,在对方的网站上,显示的不是我们真是的IP地址,而是代理服务器的IP地址。)
免费代理ip的地址http://www.xicidaili.com/
如果在使用代理服务器进行网站爬取时,出现异常,需要考虑是否对应的代理ip失效了,如果是换个ip继续爬。
#!/usr/bin/env python
#-*- utf-8 -*-
#代理服务器的设置
# 应用场景:使用同一个IP去爬取同一个网站上的网页,久了之后会被该网站服务器屏蔽。
# 解决方法:使用代理服务器。(使用代理服务器去爬取某个网站的内容的时候,在对方的网站上,显示的不是我们真是的IP地址,而是代理服务器的IP地址。)
def use_proxy(proxy_addr, url):
"""
使用代理服务器爬取网页
"""
import urllib.request
proxy = urllib.request.ProxyHandler({'http':proxy_addr}) # 设置代理服务器的信息,设置格式为:ProxyHandler({'http'.{代理服务器的地址}})
opener = urllib.request.build_opener(proxy, urllib.request.HTTPHandler) # 创建一个自定义的opener对象,第一个参数为代理信息,第二个参数为urllib.request.HTTPHandler类
urllib.request.install_opener(opener) # 为了方便,设置opener为全局默认的opener对象,那么在使用urlopen的时候就会使用我们安装的opener对象。
data = urllib.request.urlopen(url).read().decode('utf-8') # 读取解码并并存储在data中
return data
def get_proxys():
"""
捉取免费代理ip
"""
import socket
socket.setdefaulttimeout(3) # 设置全局超过时间为3s,如果一个请求3s还没有响应,就结束访问。
f = open('./proxy')
lines = f.readlines()
proxys = []
for i in range(0, len(lines)):
ip = lines[i].strip("\n").split("\t") # 去掉每行末尾的换行符,然后以制表符分割字符数组
proxy_host = "http://"+ip[0]+":"+ip[1]
#proxy_temp = {"http":proxy_host}
proxys.append(proxy_host)
return proxys
if __name__ == '__main__':
for proxy in get_proxys():
from urllib import request
# print(proxy)
try:
res = use_proxy(proxy, "http://ip.chinaz.com/getip.aspx")
#res = request.urlopen("http://ip.chinaz.com/getip.aspx", proxies=proxy).read()
print(res)
except Exception as e:
print(proxy)
print(e)
continue
Cookie的使用
应用场景:爬取得网页涉及登录信息,我们登录成功了一个页面进行爬取后。如果要爬取该网站的其他网页的时候,仍然会是未登录状态。如果有了Cookie,当我们登录成功后,爬取该网站的其他网页时,则会保持登录状态进行内容爬取。**
要爬取的网站http://bbs.chinaunix.net/。先注册一个账号,然后点击登录按F12,随便输入账号密码登录,可以看到提交表单数据的真是URL:http://bbs.chinaunix.net/member.php?mod=logging&action=login&loginsubmit=yes&loginhash=Lq8Qi
image.png往下拉找到FormData,发现账号关键字是username,密码关键字是password
知道这些就可以爬了
image.png
#/usr/bin/env python
#-*- utf-8 -*-
# Cookie的使用
import urllib.request
import urllib.parse
import urllib.error
import http.cookiejar
url = 'http://bbs.chinaunix.net/member.php?mod=logging&action=login&loginsubmit=yes&loginhash=LcHFP'
data = {
'username':'shenyoujian2',
'password':'csy123456',
}
postdata = urllib.parse.urlencode(data).encode('utf8') # username=123&password=123,b'username=123&password=123'
# print(postdata)
# 添加头部信息
header = {
'User-Agent':'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
'Referer': 'http://bbs.chinaunix.net/member.php?mod=logging&action=login&logsubmit=yes',
}
request = urllib.request.Request(url, postdata, header)
try:
reponse = urllib.request.urlopen(request)
except urllib.error.HTTPError as e:
print(e.code)
print(e.reason)
fhandle = open('./test.html', 'wb') # 保存登录后的页面文件
fhandle.write(reponse.read())
fhandle.close()
url2 = "http://bbs.chinaunix.net/forum-327-1.html" # 再次访问该网站别的页面
# reponse2 = urllib.request.urlopen(url, timeout=1) # 没有模拟浏览器是捉取不到的
try:
request2 = urllib.request.Request(url2, headers=header)
reponse2 = urllib.request.urlopen(request2) # 设置超时时间
except urllib.error.HTTPError as e:
print(e.code)
print(e.reason)
fhandle2 = open('./test2.html', 'wb') # 保存到文件中
fhandle2.write(reponse2.read())
fhandle2.close()
然后我们打开test.html可以发现已经登录
而当我们打开test2.html可以发现是没有登录的
image.png
出现这样的情况是因为我们没有设置Cookie处理,HTTP协议是一个无状态的协议,我们访问了新页面,自然会话信息会消失,如果希望登录状态一直保持,则需要进行Cookie处理。进行Cookie处理的一种常用思路:
- 导入Cookie处理模块http.cookiejar
- 使用http.cookiejar.CookieJar()创建CookieJar对象
- 使用HTTPCookieProcessor创建cookie处理器,并以其为参数构建opener对象。
- 创建全局默认opener对象
#/usr/bin/env python3
#-*- utf-8 -*-
import urllib.request
import urllib.error
import urllib.parse
import http.cookiejar
url = 'http://bbs.chinaunix.net/member.php?mod=logging&action=login&loginsubmit=yes&loginhash=LcHFP'
data = {
'username':'shenyoujian2',
'password':'csy123456',
}
postdata = urllib.parse.urlencode(data).encode('utf8')
header = {
'User-Agent':'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
'Referer':'http://bbs.chinaunix.net/member.php?mod=logging&action=login&logsubmit=yes'
}
request = urllib.request.Request(url, postdata, headers=header)
# 使用http.cookiejar.CookieJar()创建CookieJar对象
cjar = http.cookiejar.CookieJar()
# 使用HTTPCookieProcessor创建cookie处理器,并以其为参数构建opener对象
cookie = urllib.request.HTTPCookieProcessor(cjar)
opener = urllib.request.build_opener(cookie)
# 将opener安装为全局
urllib.request.install_opener(opener)
try:
reponse = urllib.request.urlopen(request)
except urllib.error.HTTPError as e:
print(e.code)
print(e.reason)
fhandle = open('./test3.html', 'wb')
fhandle.write(reponse.read())
fhandle.close()
url2 = "http://bbs.chinaunix.net/forum-327-1.html"
# reponse2 = urllib.request.urlopen(url2, timeout=1) # 没有模拟浏览器是捉取不到的
try:
request2 = urllib.request.Request(url2, headers=header)
reponse2 = urllib.request.urlopen(request2)
except urllib.error.HTTPError as e:
print(e.code)
print(e.reason)
fhandle2 = open('./test4.html', 'wb')
fhandle2.write(reponse2.read())
fhandle2.close()
可以看到html4已经登录了
总结:
- 如果urlopen(url)报504网关超时,就设置timeout=1,但是还是会timeout,只是为了不要妨碍其他的爬取,一般都得设置超时的时间。
- 捉取不到就用模拟浏览器,创建Request对象,加入header信息。
参考:https://www.cnblogs.com/hearzeus/p/5157016.html
https://blog.csdn.net/duxu24/article/details/77414298
https://blog.csdn.net/fengxinlinux/article/details/77340666
网友评论