爬虫体验

作者:桂。

时间:2017-02-14  12:29:34

链接:http://www.cnblogs.com/xingshansi/articles/6397083.html 

声明:转载请注明出处,谢谢。


前言

网上一些数据一个个下载/复制太慢,爬虫是个不错的工具,先接触一下,用到了再研究。

 一、安装明细

  • Wins 8.1,64位
  • Anaconda集成安装;
  • 版本:Anaconda3-4.1.0-Windows-x86_64.exe-,默认python 3.5版本
Anaconda可通过下面的链接下载:

选用Anaconda主要考虑:

  • 不需要配置PYTHON环境变量;
  • 集成很多packages,省去一一下载的麻烦;
  • packages的安装很简单,conda一键解决;
  • 可以配置python3.5版本的环境,方便切换,互不干扰,兼容性强。

Anaconda官网有相应的文档介绍:

二、Python简介

  A-编辑器选择

网上有各种IDE推荐,起步定位是:熟悉功能,编写直接采用Anaconda自带的spyder

  B-工具包安装

Python工具包的下载主要通过运行Anaconda Prompt

该模块主要基于conda指令,关于conda的细节,可以参考:

用到的packages主要包括:

  • urllib
  • requests
  • beautifulsoup
  • scrapy

requests具有良好的树状分析特性,可以省区正则表达式带来的麻烦,打算从urllib学起,先熟悉爬虫的一般特性,如果加载成功,则说明对应的packages已经install完成。

  C-程序管理

Run—>Configure,设置.py文件的存储路径:

三、页面爬取(以下基于python2.7, 3.5类似)

跳出细节信息,先想想爬取需要哪些操作:

  • 爬取网页内容
  • 定位目标信息链接
  • 读取链接,并将读取的内容写入本地/数据库

步骤一:爬取页面信息

打开网页的流程可以简化为:HTTP是用户发出请求—>对方返回协议—>页面解析并显示。

对于某风景网站,借助python基本的爬取代码:

import urllib2

def download(url):
    headers = {'User-Agent':"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1"}
    request = urllib2.Request(url,headers = headers)
    try:
       html = urllib2.urlopen(request).read()
    except urllib2.URLError as e:
        print 'error:', e.reason
        html = None
    return html

url = 'http://www.onlytease.com/'
page = download(url)
print page

  关于解码信息,打开网页并按F12,在head下拉单里即可看到编码方式,解码与其对应。

至此,对于基本的网页已经实现爬取功能,然而满页内容,只有极少数是自己关心的,对于基本框架的搭建仅剩一个问题:如何爬取自己想要的内容。

步骤二:定位目标信息

打开任意网页(以chrome为例),选中感兴趣的内容,右键:检查(或快捷键:Crtl + shift + I),既可以查看对应的细节信息:

例如选中一张图片: 

 

 电脑User-agent的查看方式很多,可以直接登陆网站

这是人为观察的方式,如果希望自动定位目标信息可以通过正则表达式、beautifulsoup等工具。常用正则表达式参考这篇文章

步骤三:写入目标内容

先撇开前面两个步骤,以图片为例,网上可以搜索python 网页 图片下载。看看具体的操作,文本/压缩包等文件以此类推。

url = 'http://pics.sc.chinaz.com/files/pic/pic9/201705/bpic1322.jpg'
f = open('1.jpg',"wb")    #命名并打开文件  
req = urllib2.urlopen(url)  
buf = req.read()              #读出文件  
f.write(buf)                  #写入文件 

 这样网上的图片就进入了本地:

 爬取小图片:

code:

import urllib2
import re

def download(url): #Step1:读取网页内容
    headers = {'User-Agent':"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1"}
    request = urllib2.Request(url,headers = headers)
    try:
       html = urllib2.urlopen(request).read()
    except urllib2.URLError as e:
        print 'error:', e.reason
        html = None
    return html
#Step2:获取目标信息链接,我要的是jpg的链接
url = 'http://sc.chinaz.com/tupian/fengjingtupian.html'
page = download(url)
imglist = re.findall('src2="(.*?)"',page)      #re.findall() 方法读取html 中包含 imgre(正则表达式)的    数据
#Step3:文件保存至本地
i = 1
for imgname in imglist:
    f = open('.\\sightsee\\'+str(i)+'.jpg',"wb")    #命名并打开文件  
    print i
    i = i+1
    req = urllib2.urlopen(imgname)  
    buf = req.read()              #读出文件  
    f.write(buf)                  #写入文件 

  收入囊中:

为什么是src2而不是src,复制download的文本到txt文件,搜索.jpg,

看到是src2,但网页里是src:

上面爬取的是一页的图片,如果想获取总共的呢?可以通过正则表达式匹配并计算总页数,这里为了方面观察一下:

打开网站,http://sc.chinaz.com/tupian/,发现总共是2217页:

除了第一页有点不同:

其它依次类推:

好了,现在进一步完善代码:

import urllib2
import re
import numpy as np

def download(url): #Step1:读取网页内容
    headers = {'User-Agent':"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1"}
    request = urllib2.Request(url,headers = headers)
    try:
       html = urllib2.urlopen(request).read()
    except urllib2.URLError as e:
        print 'error:', e.reason
        html = None
    return html
urllen = 2217
tag = np.arange(1,urllen+1)
base = 'http://sc.chinaz.com/tupian/'
i = 1
for j in tag:   
    if j==1:
        url = base+'index.html'
    else:
        url = base+'index_'+str(j)+'.html'
    page = download(url)
    imglist = re.findall('src2="(.*?)"',page)      #re.findall() 方法读取html的.jpg链接
    for imgname in imglist:
        f = open('.\\sightsee\\'+str(i)+'.jpg',"wb")    #命名并打开文件  
        print i
        i = i+1
        req = urllib2.urlopen(imgname)  
        buf = req.read()              #读出文件  
        f.write(buf)                  #写入文件         
        f.close()    

  都已经成功下载出来了:

有一个问题:

没有设置timeout参数,结果在网络环境不好的情况下,时常出现read()方法没有任何反应的问题,程序卡死在read()方法里,给urlopen加上timeout就ok了,设置了timeout之后超时之后read超时的时候会抛出socket.timeout异常,想要程序稳定,还需要给urlopen加上异常处理,再加上出现异常重试。

修改这一句:

html = urllib2.urlopen(request,timeout=2).read()

  问题就解决了。

但还是会有其他错:

 参考下面的图片,添加异常处理,问题解决。

 

四、渲染动态网页爬取

python的工具包都可以在这里下载。安装selenium工具包,安装lxml,python2中需要单独下载:cssselect,顾名思义,css+select就是前段css样式select。

这里仅仅记录应用,偷个懒:用selenium+phantomjs的爬取方式。

phantomjs简介:

PhantomJS 是一个基于 WebKit 的服务器端 JavaScript API。它全面支持web而不需浏览器支持,其快速,原生支持各种Web标准: DOM 处理, CSS 选择器, JSON, Canvas, 和 SVG。 PhantomJS 可以用于 页面自动化 , 网络监测 , 网页截屏 ,以及 无界面测试 等。

很多网页不一次性把内容加载完,如果每次都刷新页面又不理想,因此借助动态加载,看到哪里只加载这一部分内容。phantomjs可以不用通过打开浏览器,却获得了网页加载后的内容,这样再用urllib2.request操作读取就可以获取网页的整个内容,而不是没有动态加载的内容。

两点注意:

1-phantomjs的\bin需要在环境变量PATH里添加绝对路径;

2-代码里:路径前要添加r

browser = webdriver.PhantomJS(executable_path=r"C:\Users\Nobleding\Anaconda3\Lib\site-packages\phantomjs-2.1.1-windows\bin\phantomjs.exe")
#coding=utf-8


from selenium import webdriver
import re
import urllib2

browser = webdriver.PhantomJS(executable_path=r"C:\Users\Nobleding\Anaconda3\Lib\site-packages\phantomjs-2.1.1-windows\bin\phantomjs.exe")
browser.implicitly_wait(50)
#browser.get("https://www.baidu.com/")
urllink = "网址名称"
browser.get(urllink)
page = browser.execute_script("return document.documentElement.outerHTML")
imglist = re.findall('src=(.*?).jpg', page)      #re.findall() 方法读取html的.jpg链接
i=1
for imgname in imglist:
    f = open('.\\sightsee\\'+str(i)+'.jpg',"wb")    #命名并打开文件 
    print i
    i = i+1
    try:
        imglink = imgname+'.jpg'
        n = len(imglink)
        req = urllib2.urlopen(imglink[1:n],timeout = 3)
    except urllib2.URLError, e:
        print 'error:', e.reason
        continue
    except socket.error as e:
        continue
    except socket.timeout as e:   
        continue
    except urllib2.HTTPError:
        continue
    buf = req.read()              #读出文件 
    f.write(buf)                  #写入文件
    f.close()

  基于urllib2/urllib3/urllib经常会报timeout错,直接用requests更直接,且不再报time out错误:

# -*- coding: utf-8 -*-
"""
Created on Sun May 07 09:48:39 2017

@author: Nobleding
"""

import requests
import re
import socket
import numpy as np
import urllib
from socket import timeout

def download(url): #Step1:读取网页内容
    header = {'User-Agent':"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1"}
#    request = requests.Request(url,headers = headers)
    try:
       htmll = requests.get(url,headers=header)
       html = htmll.text
#    except requests.URLError:
#        print ('error:')
#        html = None
    except socket.error as e:
        html = None
    except socket.timeout as e:   
        html = None
    except urllib.request.HTTPError:
        html = None
    return html
urlmain =网址
pagemain = download(urlmain)
#pagemain = pagemain.decode('utf-8')
imglistmain = re.findall('<a href=\'/pictures/(.*?)/\'',pagemain)
i=1
nums = np.arange(0,len(imglistmain)+1)
for j in nums:
    url = urlmain+imglistmain[j]+'/'
    print (111)
    page = download(url)
    if page == None:
        continue
    else:
#        page = page.decode('utf-8')
        imglist = re.findall('src=(.*?).jpg',page)
    for imgname in imglist:
        f = open('.\\sightsee\\'+str(i)+'.jpg',"wb")    #命名并打开文件
        print (i)
        i = i+1
        try:
            imglink = imgname+'.jpg'
            nlen = len(imglink)
            req = requests.get(imglink[1:nlen],timeout = 5)
#        except requests.URLError:
#            print ('error:')
#            continue
        except timeout:
#            print(e)
            continue
        except socket.error as e:
#            prin1t(e)
            continue
#        buf = req.read()              #读出文件
        f.write(req.content)                  #写入文件
        f.close() 

总结一下,以后需要python爬取内容,需要提到的地方:

  • 网页读取:如果有JS动态加载以及验证码、账号密码登cookies等问题,需要进一步深入
  • 目标信息获取:需要注意两方面——
    • 快速定位目标信息,需要熟悉正则表达式、beautifulsoup工具包或者其他高级辅助工具
    • 异常情况处理:如等待时间过长、爬取速度过快被管理员监视、进入死循环等等问题,需要调研汇总并研究解决,如:
    • 嵌套的处理:比如通过A网页可以打开B网页,而内容C的链接要在B网页进一步获取,依次类推
  • 内容的存储
    • 需要熟悉不同格式文件的存储方法,如文本、pdf、PPT、压缩文件、视频、音乐、图片等等常用格式的存储办法
    • 如果数据过大,且需要与他人共享,需要涉及并行下载、数据库等方面的知识
posted @ 2017-02-14 13:14  LeeLIn。  阅读(1579)  评论(0编辑  收藏  举报