Python:urllib.request的5个基本程序

爷,独闯天下 提交于 2019-12-14 09:51:16


一、基础版

from urllib import request

# 读取主页源码
url = "http://www.baidu.com/"
# url = "https://www.baidu.com/"
html = request.urlopen(url)
code = html.read().decode("UTF_8")
file = open("1.html", "w", encoding='UTF-8')
file.write(str(code))
file.close
print(code)
http请求方法 描述
GET 向指定url发送请求,返回网页的html代码
POST 向指定url提交数据,由服务端进行处理并返回结果。
http请求 / 响应过程 操作
1 客户端(浏览器)解析URL地址,将域名转换成IP
2 客户端(浏览器)与服务端(服务器)建立TCP/IP连接
3 客户端(浏览器)发送http请求,请求报文包括请求行(请求方式、URL、协议版本)、请求头部、空行和请求数据
4 服务端(服务器)响应请求返回数据,响应报文包括状态行、消息报头、空行和响应正文
5 服务端(服务器)释放TCP连接
6 客户端(浏览器)解析返回的数据并显示

  urllib.request最基本的运用,对于一些简单或友好的网址(url)是可以直接爬取的,但对于大的,要求比较严的网站就无能为力。request.urlopen相当于GET。
  **注意:**对于http(如url = “http://www.baidu.com/”)与https(如url = “https://www.baidu.com/”)其读取的html可能会不同。

二、异常处理版

from urllib import request, error

try:
    # 读取主页源码
    url = "http://www.baidu.com/"
    html = request.urlopen(url, timeout=10)  # 添加超时处理
    code = html.read().decode("UTF_8")
    file = open("1.html", "w", encoding='UTF-8')
    file.write(str(code))
    file.close
    print(code)
except error.URLError as e:  # 异常处理
    print(e.reason)

  request.urlopen运行时可能长时间没有响应,程序一直卡住,既不运行下去,也不提示错误。所以需要添加超时处理和异常处理,输出请求错误原因。

三、User-Agent版

from urllib import request, error

try:
    # 读取主页源码
    url = "http://www.baidu.com/"
    headers = {  # 用户代理,伪装浏览器用户访问网址
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3941.4 Safari/537.36'
    }
    req = request.Request(url + "/headers", headers=headers)
    html = request.urlopen(req, timeout=10)
    code = html.read().decode("UTF_8")
    file = open("1.html", "w", encoding='UTF-8')
    file.write(str(code))
    file.close
    print(code)
except error.URLError as e:
    print(e.reason)

  User-Agent即用户代理,存放于请求头部Header中,部分网站通过它识别爬虫。python可用其模拟浏览器点击访问网站。
  查看Chrome浏览器User-Agent方法:在地址栏输入about:version,回车即可查看。
Chrome浏览器User-Agent
  User-Agent可以直接使用自己浏览器的,也可以从网上收集。通过random.choice随机取出一个User-Agent进行浏览器模拟,由此可实现不同浏览器用户访问同一网站。

from urllib import request, error
import random

# 读取主页源码
url = "http://www.baidu.com/"
headers = [
        'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36 ',
        'Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50',
        'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0',
        'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2',
        'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36',
        'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko',
        'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrow ser/2.0 Safari/536.11',
        "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
        "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
        "Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
        "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
        "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
        "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
        "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
        "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
        "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
        "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
        "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
        "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5",
        "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20",
        "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52"
    ]
header = random.choice(headers)
print(header)
try:
    req = request.Request(url)
    req.add_header('User-Agent', header)
    html = request.urlopen(req, timeout=10)
    code = html.read().decode("UTF_8")
    file = open("1.html", "w", encoding='UTF-8')
    file.write(str(code))
    file.close
    print(code)
except error.URLError as e:
    print(e.reason)

  若不想找User-Agent,python库中有my_fake_useragent,手动安装后通过**UserAgent().random()**随机选择一个User-Agent。

from urllib import request, error
from my_fake_useragent import UserAgent


# 读取主页源码
url = "http://www.baidu.com/"
ua = UserAgent()
headers = {'User-Agent': ua.random()}
print(ua.random())
try:
    req = request.Request(url, headers=headers)
    html = request.urlopen(req, timeout=10)
    code = html.read().decode("UTF_8")
    file = open("1.html", "w", encoding='UTF-8')
    file.write(str(code))
    file.close
    print(code)
except error.URLError as e:
    print(e.reason)

四、IP代理版

from urllib import request, error
import random

# 读取主页源码
url = "https://www.csdn.net/"
proxy_list = [
    {'http': '171.35.223.182'},
    {'http': '183.164.239.21'},
    {'http': '1.197.16.178'},
]
proxy = random.choice(proxy_list)
print(proxy)
try:
    proxies = request.ProxyHandler(proxy)  # 创建代理处理器
    opener = request.build_opener(proxies)  # 创建opener对象
    html = opener.open(url)
    code = html.read().decode("UTF_8")
    print(code)
    file = open("1.html", "w", encoding='UTF-8')
    file.write(str(code))
    file.close
except error.URLError as e:
    print(e.reason)

  爬虫爬取数据时会频繁访问网站,故部分网站会通过检查IP访问频率识别爬虫。为避免单个用户因频繁访问而被禁止,便需要IP代理,使用不同IP访问网站。
  代理IP具有时效性,很容易过期。最新的有效免费代理可从西刺免费代理IP中获取。
西刺免费代理IP

五、Cookie版

注意:Cookie版的程序并不能运行,只是为了显示使用cookie的基本步骤而已。因为不同网页有不同的加密策略和防爬虫的手段。即使是同一网站,其不同时期的防爬虫手段也会有所变化,毕竟爬虫多了,网站工作人员自然而然会对技术进行升级换代。想查找此类可运行的代码,一定要对百度搜索进行时间筛选,起码是1年以内的文章,太久的文章(例如CSDN模拟账号登录)其内容和代码大部分都已经过期。

# -*- coding: UTF-8 -*-
from urllib import parse
import urllib.request
import http.cookiejar

# 1. 构建一个CookieJar对象实例来保存cookie
cookie = http.cookiejar.CookieJar()
# 2. 使用HTTPCookieProcessor()来创建cookie处理器对象,参数为CookieJar()对象
cookie_processor = urllib.request.HTTPCookieProcessor(cookie)
# 3. 通过 build_opener() 来构建opener
opener = urllib.request.build_opener(cookie_processor)
# 4. headers信息
header = {
    "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36",
}
# 5. 需要登录的账户和密码
data = {"username": "", "password": ""}
# 6. 通过urlencode()转码
postdata = parse.urlencode(data).encode(encoding='utf-8')
# 7. 构建Request请求对象,包含需要发送的用户名和密码
request = urllib.request.Request("https://passport.csdn.net/login", data=postdata, headers=header)
# 8. 通过opener发送这个请求,并获取登录后的Cookie值,
opener.open(request)
# 9. opener包含用户登录后的Cookie值,可以直接访问那些登录后才可以访问的页面
response = opener.open("https://i.csdn.net/#/uc/profile")
# 10. 打印响应内容
print(response.read().decode('utf-8'))

  因为http协议是无状态的,即两次登录同一网站,服务器并不知道登录的是同一用户,所以需要利用Cookie来识别用户个人信息。当用户初次登录网站时,服务器生成Cookie并保存在客户端上。当用户再次登录这一网站时,客户端自动将Cookie发送至服务端说明是同一用户。使用爬虫时可能需要频繁换页,为证明你是同一用户,便需要使用Cookie。
  与Cookie类似的还有Session和Token。Cookie是将用户信息(如账号密码等)保存客户端(浏览器端)上,发生请求会将cookie一起发给服务端。Session是将seesion_id(初次登录时由服务器分配)保存在客户端,发送请求会将Seesion_ID发送给服务端,由服务器在其数据库查找相关用户信息,即其用户信息是存放在服务端的。Token则是在初次登录时将用户信息加密生成token保存在客户端,再次发送请求时会将token发送给服务端,由服务器解密校验,即它不需要保存用户信息。详细信息可以参考彻底理解cookie,session,token这篇博客。

六、总结

  这5个程序都是对urllib.request的基本使用,它只能解决一小部分问题。实际所需爬取的网站要比这些复杂的多,python爬虫的道路还很远,这充分体现了python易学难精的特点。若想进一步学习,你还需要学习html(定义网页内容),css(描述网页布局),javascript(管理网页行为)以及熟悉一些常用工具如chrome的调试,fiddler的使用等。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!