美文网首页
Python网络爬虫学习笔记

Python网络爬虫学习笔记

作者: KevinCool | 来源:发表于2016-01-29 12:14 被阅读766次

    Python 爬虫学习笔记


    学习自崔庆才的个人博客http://www.cnblogs.com/xin-xin/p/4297852.html,以及静觅http://cuiqingcai.com/
    第7章的安装方法是我自己摸索出来的,因为按照崔庆才的文章没有安装成功。

    1. Urllib库的使用

    import urllib2
    
    response = urllib2.urlopen("http://www.baidu.com")
    print response.read()
    

    首先我们调用的是urllib2库里面的urlopen方法,传入一个URL,这个网址是百度首页,协议是HTTP协议。

    urlopen(url, data, timeout)

    第一个参数url即为URL,第二个参数data是访问URL时要传送的数据,第三个timeout是设置超时时间。

    response对象有一个read方法,可以返回获取到的网页内容。

    其实上面的urlopen参数可以传入一个request请求,它其实就是一个Request类的实例,构造时需要传入Url,Data等等的内容.

    import urllib2
    
    request = urllib2.Request("http://www.baidu.com")
    response = urllib2.urlopen(request)
    print response.read()
    

    2.数据传送方式

    • post

    post方式就是在向服务器发送request的时候将data数据包含其中。


    import urllib
    import urllib2
    
    values = {}
    values['username'] = "1016903103@qq.com"
    values['password'] = "XXXX"
    data = urllib.urlencode(values) 
    url = "http://passport.csdn.net/account/login?from=http://my.csdn.net/my/mycsdn"
    request = urllib2.Request(url,data)
    response = urllib2.urlopen(request)
    print response.read() 
    
    • GET

    而GET方式则是直接将data数据融入到请求链接之中


    import urllib
    import urllib2
    
    values={}
    values['username'] = "1016903103@qq.com"
    values['password']="XXXX"
    data = urllib.urlencode(values) 
    url = "http://passport.csdn.net/account/login"
    geturl = url + "?"+data
    request = urllib2.Request(geturl)
    response = urllib2.urlopen(request)
    print response.read()
    

    3. Urllib库的高级用法

    • 设置Headers

    目的是完全模拟浏览器浏览网页的特征,以防有些网站禁止爬虫程序的运行。

    首先是设置User-Agent

    import urllib  
    import urllib2  
    
    url = 'http://www.server.com/login'
    user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'  
    values = {'username' : 'cqc',  'password' : 'XXXX' }  
    headers = { 'User-Agent' : user_agent }  
    data = urllib.urlencode(values)  
    request = urllib2.Request(url, data, headers)  
    response = urllib2.urlopen(request)  
    page = response.read() 
    

    下来有对付反盗链的方式,在headers中加入referer,即将这个属性设置为服务器自己。

    headers = { 'User-Agent' : 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'  ,
                        'Referer':'http://www.zhihu.com/articles' }  
    

    总之呢,尽量来模拟真实浏览器的headers的内容,构建的时候写入同样的数据

    • Proxy代理设置

    这个主要是对付有的网站会检测IP的访问次数,次数过多,则会禁止访问,所以设置代理服务器。

    import urllib2
    enable_proxy = True
    proxy_handler = urllib2.ProxyHandler({"http" : 'http://some-proxy.com:8080'})
    null_proxy_handler = urllib2.ProxyHandler({})
    if enable_proxy:
        opener = urllib2.build_opener(proxy_handler)
    else:
        opener = urllib2.build_opener(null_proxy_handler)
    urllib2.install_opener(opener)
    
    • 超时的设置

    urlopen函数的第三个参数是超时的设置,它有一个默认参数,因此如果要设置timeout的话,需要以默认参数的形式设置timeout=10

    import urllib2
    response = urllib2.urlopen('http://www.baidu.com', timeout=10)
    

    4. URLError的处理

    即是用try except语句来捕获异常并加以处理,其中有一个小tip是,父类的异常应当写到子类异常的后面,这样子类异常捕获不到就可以捕获父类异常。

    这里HTTPError是URLError的子类,因此捕获异常的代码可以这么写,另外加入 hasattr属性提前对属性进行判断,首先对异常的属性进行判断,以免出现属性输出报错的现象:

    import urllib2
    
    req = urllib2.Request('http://blog.csdn.net/cqcre')
    try:
        urllib2.urlopen(req)
    except urllib2.HTTPError, e:
        if hasattr(e,"code"):
            print e.code
    except urllib2.URLError, e:
        if hasattr(e,"reason"):
            print e.reason
    else:
        print "OK"
    

    5. Cookie的使用

    Cookie是网站为了辨别用户身份,进行session跟踪而存储到用户本地终端上的数据。(加密)

    登录之后才能访问的页面,可以利用Urllib2库保存登录的Cookie,然后再抓取页面。

    目的就是模拟登录的状态。

    • opener

    前面使用的opener都是默认的,使用urlopen来获取的,相当于opener的一个特殊实例,但是使用cookie等高级功能,必须创建更加一般的opener才能实现这些功能。

    下面就是使用一个cookie处理器然后调用build_opener函数来创建一般的opener对象,然后调用open方法打开url或者request

    • 获取Cookie保存到变量

    使用Cookielib模块,该模块作用是提供可存储cookie的对象,用CookieJar类的对象捕获cookie。

    import urllib2
    import cookielib
    #这里声明一个CookieJar对象实例来保存cookie
    cookie=coolielib.CookieJar()
    #然后使用urllib2的HTTPCookieProcessor对象来创建cookie处理器
    handler=urllib2.HTTPCookieProcessor(cookie)
    #然后通过handler来创建opener
    opener=urllib2.build_opener(handler)
    #然后调用opener的open方法,当然也可以传入request
    response=opener.open('http://www.baidu.com')
    

    这样就把cookie保存到变量之中了

    • 保存Cookie到文件

    则使用FileCookieJar这个类的对象了,在这里使用MozillaCookieJar对象

    CookieJar —-派生—->FileCookieJar —-派生—–>MozillaCookieJar和LWPCookieJar

    cookie的获取和处理和上面类似,只不过最后调用了save方法存入之前已经传入MozillaCookieJar的文件里了。

    import cookielib
    import urllib2
    
    #设置保存cookie的文件,同级目录下的cookie.txt
    filename = 'cookie.txt'
    #声明一个MozillaCookieJar对象实例来保存cookie,之后写入文件
    cookie = cookielib.MozillaCookieJar(filename)
    #利用urllib2库的HTTPCookieProcessor对象来创建cookie处理器
    handler = urllib2.HTTPCookieProcessor(cookie)
    #通过handler来构建opener
    opener = urllib2.build_opener(handler)
    #创建一个请求,原理同urllib2的urlopen
    response = opener.open("http://www.baidu.com")
    #保存cookie到文件
    cookie.save(ignore_discard=True, ignore_expires=True)
    

    最后的ignore_discard是即使cookies被丢弃也将其保存下来,ignore_exporres是如果cookie文件存在则覆盖原文件写入。

    • 从文件中获取Cookie并访问

    先创建MozillaCookie实例对象,然后调用load方法,载入上次生成的文件,接着创建带有cookie的opener对象,这里传入build_opener函数的是一个cookie处理器对象。和之前的一样。

    import cookielib
    import urllib2
    
    #创建MozillaCookieJar实例对象
    cookie = cookielib.MozillaCookieJar()
    #从文件中读取cookie内容到变量
    cookie.load('cookie.txt', ignore_discard=True, ignore_expires=True)
    #创建请求的request
    req = urllib2.Request("http://www.baidu.com")
    #利用urllib2的build_opener方法创建一个opener
    opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie))
    response = opener.open(req)
    print response.read()
    

    总之流程就是这样,创建管理cookie的实例,,创建cookie处理器,创建opener,然后创建request,open该request。

    • 模拟登录

    这里是先登录进去获取cookie写入文件,这样就可以访问登陆后才能访问的页面了。主要是使用了一个opener对象。

    import urllib
    import urllib2
    import cookielib
    
    filename = 'cookie.txt'
    #声明一个MozillaCookieJar对象实例来保存cookie,之后写入文件
    cookie = cookielib.MozillaCookieJar(filename)
    opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie))
    postdata = urllib.urlencode({
            'stuid':'201200131012',
            'pwd':'23342321'
        })
    #登录教务系统的URL
    loginUrl = 'http://jwxt.sdu.edu.cn:7890/pls/wwwbks/bks_login2.login'
    #模拟登录,并把cookie保存到变量
    result = opener.open(loginUrl,postdata)
    #保存cookie到cookie.txt中
    cookie.save(ignore_discard=True, ignore_expires=True)
    #利用cookie请求访问另一个网址,此网址是成绩查询网址
    gradeUrl = 'http://jwxt.sdu.edu.cn:7890/pls/wwwbks/bkscjcx.curscopre'
    #请求访问成绩查询网址
    result = opener.open(gradeUrl)
    print result.read()
    

    一个处理有验证码的模拟登录代码,不过暂时不能成功登录,原因还不知道为什么,但是里面表单有一个lt值每次登录都在变化,估计是因为这个原因。

    #coding=utf-8
    import urllib2
    import cookielib
    import urllib
    import re
    import sys
    '''模拟登录'''
    reload(sys)
    sys.setdefaultencoding("utf-8")
    # 防止中文报错
    CaptchaUrl = "http://cas.nwpu.edu.cn/cas/Captcha.jpg"
    PostUrl = "http://cas.nwpu.edu.cn/cas/login"
    # 验证码地址和post地址
    filename="cookies.txt"
    cookie = cookielib.MozillaCookieJar(filename)
    handler = urllib2.HTTPCookieProcessor(cookie)
    opener = urllib2.build_opener(handler)
    # 将cookies绑定到一个opener,cookie由cookielib自动管理
    username = '******'
    password = '******'
    # 用户名和密码
    picture = opener.open(CaptchaUrl).read()
    # 用openr访问验证码地址,获取cookie
    #文件输入输出,local为文件引用句柄
    local = open('e:/image.jpg', 'wb')
    local.write(picture)
    local.close()
    # 保存验证码到本地
    SecretCode = raw_input('输入验证码: ')
    # 打开保存的验证码图片 输入
    postData = {
        'encodedService':'http%3a%2f%2fportal.nwpu.edu.cn%2fdcp%2findex.jsp',
        'service':'http://portal.nwpu.edu.cn/dcp/index.jsp',
        'serviceName':'null',
        'loginErrCnt':'0',
        'username': username,
        'password': password,
        'lt':'LT_nwpuapp1_-527299-2Mb1S8cdQco6UOnf7WNb',
        'autoLogin':'false',
        'captcha':SecretCode
        }
    # 根据抓包信息 构造表单
    headers = {
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        'Accept-Language': 'zh-CN,zh;q=0.8',
        'Connection': 'keep-alive',
        'Content-Type': 'application/x-www-form-urlencoded',
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36',
        'Referer':'http://cas.nwpu.edu.cn/cas/login?service=http%3A%2F%2Fportal.nwpu.edu.cn%2Fdcp%2Findex.jsp'
    }
    # 根据抓包信息 构造headers
    data = urllib.urlencode(postData)
    # 生成post数据 ?key1=value1&key2=value2的形式
    request = urllib2.Request(PostUrl, data, headers)
    # 构造request请求
    try:
        response = opener.open(request)
        cookie.save(ignore_discard=True, ignore_expires=True)
        anotherurl='http://portal.nwpu.edu.cn/dcp/forward.action?path=/portal/portal&p=HomePage'
        response = opener.open(anotherurl)
        result = response.read()
        print result
        # 打印登录后的页面
    except urllib2.HTTPError, e:
        print e.code
        # 利用之前存有cookie的opener登录页面
    

    6. 正则表达式

    对字符串进行过滤,Python里的数量词默认是贪婪的,匹配尽可能多的字符,不过一般使用非贪婪模式进行提取,?是一个非贪婪字符。

    反斜杠问题将使用原生字符串解决,比如匹配\,则使用这样的正则表达式:r"\"
    这个问题得实践验证,因为在Python核心编程里有这么一个pattern来进行匹配的:

    patt='\w+@(\w+\.)?\w+\.com'

    这个是匹配一个电子邮件地址的,@之前是匹配至少一个字符或者数字的字符,之后是进行分组,匹配添加主机名称,然后是域名。

    这里\也没说受到什么影响,因此实践是检验真理的唯一选择。

    • Python里的Re模块

    首先在进行匹配之前,最好使用compile()函数进行预编译,预编译之后是返回regex对象,再使用re模块里面的方法即可完成匹配。

    如果没有进行预编译的话,则使用的是re模块里面的函数,函数名与作用与上述方法是一致的。

    compile()用法如下:pattern=re.compile(r'hello')

    另外除了regex对象,还有另外一种对象类型,匹配对象,是match或者search被成功调用后返回的结果,有两个主要的方法是group和groups

    group方法返回所有匹配对象或者是根据要求返回某个特定子组

    groups方法是返回一个包含唯一或者所有子组的元组

    • re模块里面的函数与方法

    match(pattern,string,flags=0)

    使用正则表达式匹配string,是从字符串开头开始匹配,失败则返回None

    一个匹配实例,最后一个匹配子组是给该子组取了个别名sign,它的作用就是匹配!(任意字符)。

    import re
    # 匹配如下内容:单词+空格+单词+任意字符
    m = re.match(r'(\w+) (\w+)(?P<sign>.*)', 'hello world!')
    

    re.search(pattern,string,flags=0)

    search()是搜索字符串中模式首次出现的位置,是在任意位置而不是尝试在起始处匹配。

    import re
    
    # 将正则表达式编译成Pattern对象
    pattern = re.compile(r'world')
    # 使用search()查找匹配的子串,不存在能匹配的子串时将返回None
    # 这个例子中使用match()无法成功匹配
    match = re.search(pattern,'hello world!')
    if match:
        # 使用Match获得分组信息
        print match.group()
    ### 输出 ###
    # world
    

    re.findall(pattern,string[,flags])

    搜索string,以列表形式返回全部能匹配的子串。

    import re
    
    pattern = re.compile(r'\d+')
    print re.findall(pattern,'one1two2three3four4')
    
    ### 输出 ###
    # ['1', '2', '3', '4']
    

    re.split(pattern,string[,maxsplit])

    使用了正则表达式的split方法将成为一个功能更为强大的工具。maxsplit指定最大分隔次数,不指定则全部分隔。

    import re
    
    pattern = re.compile(r'\d+')
    print re.split(pattern,'one1two2three3four4')
    
    ### 输出 ###
    # ['one', 'two', 'three', 'four', '']
    

    re.sub(pattern,repl,string,max=0)

    使用repl替换string中所有被正则表达式匹配的地方,max最大替换次数,如果不指定则将所有替换。当repl是一个字符串时,可以使用\id或\g、\g引用分组,但不能使用编号0。

    import re
    
    pattern = re.compile(r'(\w+) (\w+)')
    s = 'i say, hello world!'
    
    print re.sub(pattern,r'\2 \1', s)
    ### output ###
    # say i, world hello!
    

    另外subn方法将返回替换次数,替换后的字符串和表示替换次数的数字作为一个元组的元素返回。

    ### output ###
    # ('say i, world hello!', 2)
    

    7. 爬虫框架Scrapy的安装与配置

    • 安装Python

    这个自不必说,安装完最重要的是将Python安装文件夹和底下的Scripts文件夹加入环境变量,这样cmd命令行就可以直接执行Python命令了。

    • 安装pywin32

    安装地址:http://sourceforge.net/projects/pywin32/

    安装完进入Python执行环境,输入import win32com如果没有错误则安装成功。

    • 安装pyOPENSSL

    下载地址:https://launchpad.net/pyopenssl

    下载下来之后拷贝到Python根目录下的Scripts文件夹里,然后在cmd命令里进入到Scripts文件夹,执行easy_install.exe pyOpenSSL-0.11-py3.2-win32.egg就可以进行安装了。

    或者是在Scripts文件夹下执行easy_install pyOpenSSLcryptography

    或者是下载可执行安装文件进行安装,在打开的页面找到all downloads然后找到pyOpenSSL-0.11.winxp32-py2.7.exe,直接点击该链接可以下载Python2.7的,如果需要其他版本前往该网站下载。

    同样安装完成后在Python环境里执行import OpenSSL验证是否安装成功。

    pyOpenSSL出错解决尝试

    首先安装了Twisted,easy_install Twisted,还是不行。

    下来安装了cffi,easy_install cffi,提示VC++9.0for Python命令错误

    然后下载了VC++9.0 for python,发现电脑已经安装过了,仍然没有解决。

    然后看到枪杆子的博客文章,Windows7 (64位)系统下安装Scrapy详细教程,他将所有需要的依赖打包到百度网盘里了,然后正在下载的时候,网络没流量了,只能等到下午充了之后再下载试试了。

    根据他的文章所述,要安装Scrapy框架,必须安装如下依赖:

    lxml,pywin32,Twisted,pyOpenSSL,zope.interface

    回来下载好这些文件,但是安装时候报错没有找到Python2.7可是我装的就是Python2.7,不解,然后又按照之前的教程去下载了pyOpenSSL for Python2.7,执行easy_install.exe pyOpenSSL-0.11-py2.7-win32.egg然后居然好了,pyOpenSSL安装成功。

    • 安装lxml

    一个Python库,可以迅速灵活的处理xml

    pip install lxml进行安装或者easy_install lxml

    • 安装Scrapy

    最后一步就是安装Scrapy框架。

    pip install Scrapy或者easy_install Scrapy

    验证一下,输入Scrapy,即可验证是否成功。

    7.1 安装依赖文件tips:

    再看了个教程,直接在官网上下载对应需要的依赖文件(.egg格式),然后下载下来使用easy_install来安装,直接就搞定,如果通过网络自动下载安装,会出现各种问题。在这里将所有依赖文件以及链接归纳如下:

    选择对应版本下载安装,这里都是可执行文件,直接点击安装。

    选择.egg格式的文件下载,下载之后放到Python根目录下的Scripts文件夹里,进入CMD执行easy_install 文件名即可完成安装。

    选择对应Python版本,同pyOpenSSL安装方法。

    • zope.interface:easy_install zope.interface

    • 最后一步就是安装Scrapy框架。pip install Scrapy或者easy_install Scrapy

    相关文章

      网友评论

          本文标题:Python网络爬虫学习笔记

          本文链接:https://www.haomeiwen.com/subject/ypujkttx.html