Python网络爬虫学习笔记(二)

Urllib库与URLError异常

    用Urllib快速爬取一个网页:

import urllib.request

if __name__=='__main__':
    file=urllib.request.urlopen("http://www.baidu.com")   #用urllib.request.urlopen打开并爬取一个网页
    data=file.read()         #将爬取的网页的内容全部读出
    dataline=file.readline() #读取爬取的网页的一行内容
    print(data)
    print("------------分割线------------")
    print(dataline)

    输出如下:

    注:读取内容的方式一般有如下三种

  1. file.read()读取全部内容,并将其赋值给一个字符串变量
  2. file.readlines()读取全部内容,但将读取的内容赋值给一个列表变量
  3. file.readline()读取一行的内容

    存在本地:

fhandle=open("D:\\PyCharm\\workplace\\Crawler\\test1.html","wb")   #将爬取的内容存在本地文件,wb以二进制方式存储
fhandle.write(data)
fhandle.close()

    除了以上的存储本地的方法,还可以直接使用urllib,request.urlretrieve()将对应的信息存入本地文件:

urllib.request.urlretrieve("http://www.baidu.com",filename="D:\\PyCharm\\workplace\\Crawler\\test2.html")

    urlretrieve执行时会产生一些缓存,利用urlcleanup()清除缓存:

urllib.request.urlcleanup()

    此外urllib中还有一些常见的用法:

file.info()#返回当前环境信息
file.getcode()#获取当前爬取网页的状态码,若返回200则正确,否则不正确
file.geturl()#获取当前爬取的URL地址
urllib.request.quote("http://www.sina.com.cn")#对当前URL进行编码,防止出现不符合标准URL的字符

模拟浏览器

    有些时候,爬取的网页会出现403错误,因为这些网页为了防止被恶意采集信息而进行了反爬虫的设置。这个时候我们可以将爬虫模拟成浏览器去访问这些网站——通过设置UserAgent信息。

    方法一:使用build_opener()修改报头

    由于urlopen()不支持一些HTTP的高级功能,所以如果我们要修改报头可以使用urllib.request.build_opener()来完成。

url="https://blog.csdn.net/qq_29599907/article/details/80734574"
headers=("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36")
opener=urllib.request.build_opener()
opener.addheaders=[headers]  #将元组列表化
data=opener.open(url).read()
fhandle = open("D:\\PyCharm\\workplace\\Crawler\\test3.html", "wb")
fhandle.write(data)
fhandle.close()

    方法二:使用add_header()添加报头

    使用urllib.request.Request()下的add_header()来实现浏览器的模拟

url = "https://blog.csdn.net/qq_29599907/article/details/80734574"
req=urllib.request.Request(url)
req.add_header("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36")
data=urllib.request.urlopen(req).read()
fhandle = open("D:\\PyCharm\\workplace\\Crawler\\test4.html", "wb")
fhandle.write(data)
fhandle.close()

超时设置

     访问一个网站时,如果该网页长时间未响应,那么系统会判断该网页超时,无法打开网页。很多时候,我们在用爬虫爬取时要根据自己的需要来设置超时的时长。即在urlopen中加入参数timeout

urllib.request.urlopen("https://blog.csdn.net/qq_29599907/article/details/80734574",timeout=30)

HTTP协议请求

     如果要进行客户端与服务器之间的消息传递,可以使用HTTP协议请求进行。

     HTTP协议请求主要分为6种类型:GET,POST,PUT,DELETE,HEAD,OPTIONS

     GET请求实例:

          GET请求会通过URL传递信息,可以直接在URL中写上要传递的信息,也可以由表单进行传递。如果使用表单进行传递,这表单中的信息会自动转为URL地址中的数据,通过URL地址传递。

           我们在百度上查询一个关键词时,会使用GET请求进行,其中关键词字段是wd,网址格式是:"https://www.baid.com/s?wd=关键词"。因此可以根据这个规律,通过构造GET请求,用爬虫实现在百度上自动查询某个关键词。

 keyword="hello"    #查询的关键词时hello
 url="http://www.baidu.com/s?wd="+keyword
 req=urllib.request.Request(url)
 data=urllib.request.urlopen(req).read()
 fhandle=open("D:\\PyCharm\\workplace\\Crawler\\test5.html","wb")
 fhandle.write(data)
 fhandle.close()

            对于中文,以上程序会因编码问题而报错,因此要用urllib.request.quote进行编码

keyword="我们LGD是不可战胜的"
keyword=urllib.request.quote(keyword)   #编码
url="http://www.baidu.com/s?wd="+keyword
req=urllib.request.Request(url)
data=urllib.request.urlopen(req).read()
fhandle=open("D:\\PyCharm\\workplace\\Crawler\\test6.html","wb")
fhandle.write(data)
fhandle.close()

            由此我们可知,要使用GET请求,思路如下:

  1. 构建对应的URL,该URL包含GET请求的字段名和字段内容等信息,并且URL地址满足GET请求的格式,即“http://网址?字段名1=字段内容1&字段名2=字段内容2&...&字段名n&字段内容n”
  2. 以对应的URL为参数,构建Request对象
  3. 通过urlopen()打开构建的Request对象
  4. 按需求进行后续的处理操作

      POST请求实例:

             POST请求可以向服务器提交数据,是一种比较主流也比较安全的数据传递方式,一般用于注册、登陆等操作。

             这里有一个用于测试登陆的网址“http://www.iqianyue.com/mypost”,我们通过爬虫自动实现登陆思路如下:

  1. 设置好URL
  2. 构建表单数据,并使用urllib.parse.urlencode对数据进行编码处理
  3. 创建Request对象,参数包括URL地址和要传递的数据
  4. 使用add_header()添加信息头,以模拟浏览器
  5. 使用urllib.request.urlopen()打开对应的Request对象,完成信息的传递
  6. 后续处理,例如读取网页内容等

             由于点击提交后,仍然是传递到当前页面进行处理,故处理的页面仍然是http://www.iqianyue.com/mypost,URL应该设置为http://www.iqianyue.com/mypost。然后构建表单数据。查看网页源代码,找到form部分

<html>
<head>
<title>Post Test Page</title>
</head>

<body>
<form action="" method="post">
name:<input name="name" type="text" /><br>
passwd:<input name="pass" type="text" /><br>
<input name="" type="submit" value="submit" />
<br />
</body>
</html>

发现form中包含两个字段name和pass,故我们构造的数据中包含两个字段,字段值设置为我们要传递的值。格式用字典形式:

                                 {字段名1:字段值1,字段名2:字段值2,...}

这里我们将数据设置为{"name":"Messi","pass":"messi123123"},然后用urllib.parse.urlencode对数据进行编码。然后创建Request对象,参数包括URL和要传递的数据,并用add_header()添加头信息,模拟浏览器。

    url="http://www.iqianyue.com/mypost"  
    postdata=urllib.parse.urlencode({"name":"Messi","pass":"messi123123"}).encode('utf-8')  #将数据使用urlencode处理后,使用encode设置为utf-8  
    req=urllib.request.Request(url,postdata)  
    req.add_header("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36")  
    data=urllib.request.urlopen(req).read()  
    fhandle=open("D:\\PyCharm\\workplace\\Crawler\\test7.html","wb")  
    fhandle.write(data)  
    fhandle.close()  

代理服务器设置

       使用同一个IP去爬取同一个网站上的网页,久了之后会被该网站服务器屏蔽,解决这个问题的办法就是使用代理服务器,在对方的服务器上显示别人的IP地址。完整的代理服务器IP格式为:"网址:端口号"

import urllib.request
import urllib.parse

def use_proxy(proxy_addr,url):
    proxy=urllib.request.ProxyHandler({'http':proxy_addr})   #设置对应的代理服务器信息
    opener=urllib.request.build_opener(proxy,urllib.request.HTTPHandler)  #创建一个自定义opener对象,第一个参数为代理信息,第二个参数是urllib.request.HTTPHandler类
    urllib.request.install_opener(opener)    #创建全局默认的opener,必须install后才可以直接用urlopen打开相应网页并读取
    data=urllib.request.urlopen(url).read().decode('utf-8')
    return data


if __name__=='__main__':
    proxy_addr="43.247.70.151:81"
    data=use_proxy(proxy_addr,"http://www.baidu.com")
    print(len(data))

DebugLog

      DebugLog的目的是在爬虫程序运行的过程中边运行边打印调试日志。开启DebugLog的思路如下:

  1. 分别使用urllib.request.HTTPHandler()和urllib.request.HTTPSHandler()将debuglevel设置为1
  2. 使用urllib.request.build_opener()创建自定义的opener对象,并使用第一步中设置的值作为参数
  3. 用urllib.request.install_opener()创建全局默认的opener对象,这样在使用urlopen()是,也会使用我们安装的opener对象
  4. 进行后续相应操作
  httphd=urllib.request.HTTPHandler(debuglevel=1)
  httpshd=urllib.request.HTTPSHandler(debuglevel=1)
  opener=urllib.request.build_opener(httphd,httpshd)
  urllib.request.install_opener(opener)
  data=urllib.request.urlopen("https://blog.csdn.net/qq_29599907/article/details/80734574")

异常处理——URLError

      首先导入urllib.error模块。主要使用两个类,URLError类和URLError的一个子类HTTPError类。

      一般来说产生URLError的原因有如下几种可能:

  1. 连接不上服务器
  2. 远程URL不存在
  3. 无网络
  4. 触发了HTTPError

      通常错误原因都是HTTPError,故只要用HTTPError处理就可以,但HTTPError不能处理前三种异常,因此更鲁棒的做法是先让其用HTTPError处理,若无法处理再用URLError处理。

    try:
        urllib.request.urlopen("https://blog.csdn.net/qq_29599907/article/details/80734574")
    except urllib.error.HTTPError as e:
        print(e.code)
        print(e.reason)
    except urllib.error.URLError as e:
        print(e.reason)

     注意URLError错误的前三种原因是没有e.code的,只有e.reason,因此不能直接用父类URLError来完全替代子类HTTPError。可以做如下整合:

       我们用URLError进行异常处理,然后做一个判断,如果有e.code则输出相应信息,如果没有则自动忽略。同理如果有e.reason就输出e.reason,没有则自动忽略。因为HTTPError和URLError均是类,故可以用类属性判断函数hasattr()来判断是否有这些属性。

    try:
        urllib.request.urlopen("https://blog.csdn.net/qq_29599907/article/details/80734574")
    except urllib.error.URLError as e:
        if hasattr(e,"code"):
            print(e.code)
        if hasattr(e,"reason"):
            print(e.reason)



猜你喜欢

转载自blog.csdn.net/qq_29599907/article/details/80742407