首页
课程详情
师资团队
新闻资讯
开班报名
关于云脉
Java
Web
UI
数据分析
软件测试
Python
大数据
网络工程
爬虫之urllib(一)

一,urllib.request

1.1 urllib.request.urlopen

request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)

参数含义:

url:打开一个url,该url可以是一个字符串或者一个 Request 对象

data:参数必须是一个字节对象 ,该对象指明发送到服务器的附加数据。如果不需要发送数据,可以是None]

timeout:可选的参数 timeout 参数在秒的级别规定了一个连接尝试的阻塞等待时间(如果没有指定该参数,全局的默认的超时时间将被启用),这个参数实际上只对http,https,ftp链接有效

cafile和capath:可选的 cafile 和 capath 参数用来为https请求指明一套可信的CA证书。cafile 必须是包含了一套证书的单独的文件,capath则应该指定这些证书文件的目录。

ssl.SSLContext.load_verify_locations()函数中可以找到更多信息

context:如果 context 参数被指定,它必须是一个带有各样SLL选项的ssl.SSLContext实例

cadefault:参数已经被弃用,可以不用管了。

接下来让我看看怎么应用

我们使用 urllib.request.urlopen() 去请求百度贴吧,并获取到它页面的源代码。

 

import urllib.request 

url = "http://tieba.baidu.com" 

response = urllib.request.urlopen(url) 

html = response.read() # 获取到页面的源代码 

print(html.decode('utf-8')) # 转化为 utf-8 编码


设置请求超时,有些请求可能因为网络原因无法得到响应。因此,我们可以手动设置超时时间。当请求超时,我们可以采取进一步措施,例如选择直接丢弃该请求或者再请求一次。

使用 data 参数提交数据,在请求某些网页时需要携带一些数据,我们就需要使用到 data 参数params 需要被转码成字节流。而 params 是一个字典。我们需要使用urllib.parse.urlencode() 将字典转化为字符串。再使用 bytes() 转为字节流。***后使用 urlopen() 发起请求,请求是模拟用 POST 方式提交表单数据。


import urllib.parse

import urllib.request

url = "http://xx.xx.xx.xx/chitchat"

params = { "session":"1111","question":"你好" }

data = bytes(urllib.parse.urlencode(params), encoding='utf8')

response = urllib.request.urlopen(url, data=data)

print(response.read().decode('utf-8'))


1.2 urllib.request.Request

由上我们知道利用 urlopen() 方法可以发起简单的请求。但这几个简单的参数并不足以构建一个完整的请求,如果请求中需要加入headers(请求头)、指定请求方式等信息,我们就可以利用更强大的Request类来构建一个请求。

按照国际惯例,先看下 Request 的构造方法:

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

url: 参数是请求链接,这个是必传参数,其他的都是可选参数。

data: 参数跟 urlopen() 中的 data 参数用法相同。

headers: 参数是指定发起的 HTTP 请求的头部信息。headers 是一个字典。它除了在 Request 中添加,还可以通过调用 Request实例的 add_header() 方法来添加请求头。

origin_req_host: 参数指的是请求方的 host 名称或者 IP 地址。

unverifiable: 参数表示这个请求是否是无法验证的,默认值是False。意思就是说用户没有足够权限来选择接收这个请求的结果。例如我们请求一个HTML文档中的图片,但是我们没有自动抓取图像的权限,我们就要将 unverifiable 的值设置成 True。

method: 参数指的是发起的 HTTP 请求的方式,有 GET、POST、DELETE、PUT等

接下来看一个demo吧:


import urllib.parse

import urllib.request

url = 'https://fanyi.baidu.com/'

headers = {

    'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'

}

values = {

    'from': 'zh',

    'to':'en',

    'query':'肥猪',

    'transtype':'translang',

    'simple_means_flag':'3'

}

data = urllib.parse.urlencode(values).encode("utf-8")

request = urllib.request.Request(url,data,headers)

response = urllib.request.urlopen(request).read().decode("utf-8")

print(response)


1.3 urllib.request.install_opener(opener)

urllib.request.build_opener([handler, ...])

urllib.request.ProxyHandler(proxies=None)

在抓取一个网站的信息时,如果我们进行频繁的访问,就很有可能被网站检测到而被屏蔽,解决这个问题的方法就是使用ip代理 。在我们接入因特网进行上网时,我们的电脑都会被分配一个全球******地ip地址供我们使用,而当我们频繁访问一个网站时,网站也正是因为发现同一个ip地址访问多次而进行屏蔽的,所以这时候如果我们使用多个ip地址进行随机地轮流访问,这样被网站检测的概率就很小了,这时候如果我们再使用多个不同的headers,这时候就有多个ip+主机的组合,访问时被发现率又进一步减小了

步骤:

1、ProxyHandler类可以使用ip代理访问网页

proxy_support = urllib.request.ProxyHandler({}),其中参数是一个字典{‘类型’:'代理ip:端口号'}

2、定制、创建一个opener

opener = urllib.request.build_opener(proxy_support)

3、安装opener

urllib.request.install_opener(opener)

调用默认的opener

opener.open(url)

对于没有设置反爬虫机制的网站,我们只需要直接像上面那样引入ProxyHandler类进行处理,不需要考虑模仿浏览器

接下来看段例子:


import urllib.request

url="https://www.baidu.com"

for i in range(0,10000):

    html = urllib.request.urlopen(url)

    print(html.info())

    print(i)


上面程序行351行就出错了这是由于我们在访问的时候,网站会记下我们的ip,当我们的ip访问量在一段时间内超过网站设定的上限值的时候,这个请求就会被拒绝了

改进后代码:

#coding:utf-8

from urllib.request import Request

from urllib.request import urlopen

import urllib

import random

 

def gethtml(url,proxies):

    proxy = random.choice(proxies)

    proxy_support = urllib.request.ProxyHandler({"http":proxy})

    opener = urllib.request.build_opener(proxy_support)

    urllib.request.install_opener(opener)

    html = urlopen(url)

    return html

url = "https://www.baidu.com"

proxies=["101.53.101.172:9999","171.117.93.229:8118","119.251.60.37:21387","58.246.194.70:8080"]

 

for i in range(100):

    try:

        html = gethtml(url,proxies)

        print(html.info())

        print(i)

    except:

        print("故障")






©2021 版权所有 技术支持:龙采科技
校区地址:哈尔滨市南岗区华润大厦10层
咨询热线:0451-51098402
备案号:黑ICP备2021003952号