精通python网络爬虫笔记一

1. urllib使用

1.1 一个简单的例子

入门例子html源码

解析百度的

import urllib.request

file = urllib.request.urlopen("http://www.baidu.com")

#data = file.read()     
#dataline = file.readline()
datalines = file.readlines()

#print(data)
#print(dataline)
print(datalines)
  • read、readline和readlines会设置当前文件指针或者刷新流,直接一起用会有问题。比如先用read再用readlines就会得到空的列表
  • urllib文档地址
  • urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)函数文档

1.2 保存在文件中并查看部分信息

# -*- coding: utf-8 -*-
from urllib import request

urladd = "http://www.baidu.com"
file = request.urlopen(urladd)

data = file.read()
print(data)

htmlfile = open("baidu.html",'wb')
htmlfile.write(data)
htmlfile.close()

#直接写入html文件
htmlfile2 = request.urlretrieve(urladd,"baidu2.html") #retrieve 是取回的意思
request.urlcleanup()

print(file.info())    #
print(file.getcode()) #状态码
print(file.geturl())

## 1.3 对中文字符的处理

request 下面有一个quote函数,用来对中文等特殊字符进行编码

用法是:

urllib.parse.quote(string, safe=’/’, encoding=None, errors=None)文档地址

# -*- coding: utf-8 -*-
from urllib import request

urladd = u"https://www.baidu.com/s?ie=UTF-8&wd=urllib 手册"
urladd = request.quote(urladd,safe='/:=?') #不加这句会报错
file = request.urlopen(urladd)

data = file.read()
print(data)

1.4 User-Agent 和 模拟Header

在本机的浏览器按f12,在network下点击第一个url,在最下面有一行RequestHeader:

本机在本系统本网络环境中的user-agent

user-agent:

Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36

User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。

–from 百度百科

在某些网页设置了反爬虫的机制,没有user-agent的信息会返回403错误,当然有的时候也可以用来伪造user-agnet,header信息除了user-agnet之外还有其他的信息,比如Referer等

两种方法

  1. 使用build_opener:

    
    # -*- coding: utf-8 -*-
    
    from urllib import request
    
    urladd = u"https://www.baidu.com/"
    header = ("user-agent","Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36") #添加header信息
    opener = request.build_opener()
    opener.addheaders = [header]
    file = opener.open(urladd)
    
    #file = request.urlopen(urladd)
    
    
    data = file.read()
    print(data)

  2. 使用Request:

    
    # -*- coding: utf-8 -*-
    
    from urllib import request
    
    urladd = u"https://www.baidu.com/"
    key = "user-agent"
    value = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36"
    
    req = request.Request(urladd)
    req.add_header(key,value)
    
    print(req)
    
    file = request.urlopen(req)
    
    #file = request.urlopen(urladd)
    
    
    data = file.read()
    print(data)

    其实在request.urlopen()的参数中传入字符串会自动生成Request对象

1.5 超时设置

就是request.urlopen()中的timeout参数,单位为秒

# -*- coding: utf-8 -*-
from urllib import request

urladd = u"https://www.baidu.com/"
key = "user-agent"
value = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36"

for i in range(1,10):
    try:
        req = request.Request(urladd)
        req.add_header(key,value)

        print(req)

        file = request.urlopen(req,timeout=0.5)
        #file = request.urlopen(urladd)

        data = file.read()
        print(data)
    except Exception as e:
        print(str(e))

1.6 HTTP请求

1.6.1 使用get请求访问百度并搜索一个关键词

# -*- coding: utf-8 -*-
from urllib import request

urladd = "https://www.baidu.com/s?&wd=" + request.quote("我的老家") #此处需要编码
key = "user-agent"
value = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36"

req = request.Request(urladd)   #构造url请求对象
req.add_header(key,value)       #加入头

file = request.urlopen(req,timeout=1)   #设置时间
#file = request.urlopen(urladd)

data = file.read()
print(data)

file = open("baidu_wd.html",'wb')
file.write(data)
file.close()
  1. url地址请求的格式是”http://网址?字段名1=字段内容1&字段名2=字段内容2”

1.6.2 POST提交表单

要使用parse模块,parse模块是用来解析的

# -*- coding: utf-8 -*-
from urllib import request
from urllib import parse

urladd = "http://www.iqianyue.com/mypost/"
key = "user-agent"
value = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36"

postdata = parse.urlencode({
    "name":"ceo@iqianyue.com",
    "pass":"aA123456"
}).encode('utf-8')  #这里一定要调用encode方法来编码

req = request.Request(urladd,data=postdata)
req.add_header(key,value)
#req.data = postdata    #可以用这个来指定成员
file = request.urlopen(req,timeout=10)
#file = request.urlopen(urladd)

data = file.read()
print(data)

file = open("post.html",'wb')
file.write(data)
file.close()
  1. 传递的表单就是在html代码的form条目下,每项的名称就是name=后面的字段,每项的有值,需要用字典包起来。再编码,这是Request对象的一部分

1.6.3 代理服务器设置

# -*- coding: utf-8 -*-
from urllib import request
from urllib import parse

def use_proxy(proxy_addr,urladdr):
    proxy = request.ProxyHandler({'http':proxy_addr})   #设置代理的IP和端口
    opener = request.build_opener(proxy,request.HTTPHandler)
    request.install_opener(opener)      #安装全局的opener对象
    key = "user-agent"
    value = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36"

    postdata = parse.urlencode({
        "name": "ceo@iqianyue.com",
        "pass": "aA1234567"
    }).encode('utf-8')

    req = request.Request(urladd, data=postdata)
    req.add_header(key, value)
    # req.data = postdata
    file = request.urlopen(req, timeout=10)
    # file = request.urlopen(urladd)

    data = file.read()
    return  data

urladd = "http://www.iqianyue.com/mypost/"
proxy_addr = "118.114.77.47:8080"

data = use_proxy(proxy_addr=proxy_addr,urladdr=urladd)

file = open("post_proxy.html",'wb')
file.write(data)
file.close()
  1. 安装全局的opener需要传入句柄handler对象,上面的代码中proxy是代理的句柄,request.HTTPHandler也是一个句柄,据此构造了一个opener。install_opener安装全局的opener,这样就可以使用urlopen来打开网页了。
  2. 如果不调用install_opener(),则需要调用opener.open()来打开
  3. 代理的ip和端口可以在http://www.xicidaili.com/获取

1.6.4 打印日志

构造HTTPHandler或者HTTPSHandler对象的时候,设置debuglevel=1,即可,1.6.3的代码只需要修改

    opener = request.build_opener(proxy,request.HTTPHandler)

    opener = request.build_opener(proxy,request.HTTPHandler(debuglevel=1))

即可

这样日志就会打印在控制台中

1.6.5 异常处理

用到error模块,文档地址

主要就是用try except 来捕获错误

# -*- coding: utf-8 -*-
from urllib import request
from urllib import error

try:
    request.urlopen("http://blog.csdn.com")
except error.HTTPError as e:
    print(e.code)
    print(e.reason)
except error.URLError as e:
    print(e.reason)

HTTPError 是 URLError的子类,有code成员,所以要写成上面的形式。

http的常用错误码:

代码英文中文含义
200OK一切正常
301Moved Permanently永久重定向
302Found临时重定向到资源
304Not Modified请求的资源没有更新
400Bad Request非法请求
401Unauthorized请求未经授权
403Forbidden禁止访问
404Not Found没有找到对应页面
500Internal Server Error服务器内部出现错误
501Not Implement服务器不支持当前请求

1.7 总结

1.7.1 URL和域名

超文本传输协议统一资源定位符(url)将从因特网获取信息的四个基本元素包括在一个简单的地址中:

  1. 传送协议; 2. 服务器; 3. 端口号; 4. 路径。

典型的统一资源定位符看上去是这样的:

https://www.baidu.com/s?rsv_bp=0&rsv_sug2=0&ie=utf-8&word=url%E5%9C%B0%E5%9D%80%E6%A0%BC%E5%BC%8F&tn=99455684_hao_pg

其中:

  1. https,是协议;
  2. www.baidu.com,是服务器;
  3. 80,是服务器上的网络端口号(这里默认不填);
  4. /s,是路径;
  5. ?rsv_bp=0&rsv_sug2=0&ie=utf8&word=url%E5%9C%B0%E5%9D%80%E6%A0%BC%E5%BC%8F&tn=99455684_hao_pg,是询问。

www 是万维网的服务器,是网络名。baidu.com是在网络服务器上注册的主机名,默认端口是80。不加www是一级域名,加了就是二级域名,www只是声明提供的是web服务。

1.7.2 urllib及常用的函数总结

urllib由四个子模块组成

  • request 负责打开和读取url
  • error 负责获取request的错误
  • parse 负责解析url
  • robotparse 负责解析robot.txt文件,即爬虫协议

低端常用的是前三个模块,最重要的是第一个。

  1. request模块的常用函数和常用用法

    • urlopen(url , timeout) ,使用全局的opener,根据url对象打开一个网页,返回一个响应对象,调用响应对象的read,readline或readlines函数就可以获取内容。
    • urlretrieve(url , path) ,直接将url保存在本地路径中
    • build_opener(handler,…) , 使用句柄构造opener对象, 句柄可以是代理设置的句柄,如ProxyHandler的返回对象,HTTPHandler对象等,可以并排,HTTPHandler(debuglevel=1)可以打印日志。
    • opener.open() ,和urlopen()功能一样,只不过是设置不同。
    • opener_install(opener) , 把opener设置为全局的opener,这样就可以直接调用urlopen()来使用opener的设置了。
    • Request(url,data=postdata),构造url请求对象,可以调用add_header(key,value)来添加http头,data参数可以是post的表单对象
    • ProxyHandler({‘http’:proxy_addr}) 设置代理地址,返回代理句柄
  2. error的使用

    • URLError
    • HTTPError
  3. parse的使用

    • quote(str)

    • unquote(str) 编码与反编码

    • urlencode( ) 构造表单数据

       postdata = parse.urlencode({
           "name": "ceo@iqianyue.com",
           "pass": "aA1234567"
       }).encode('utf-8')
      
       req = request.Request(urladd, data=postdata)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值