zoukankan      html  css  js  c++  java
  • python爬虫

    爬虫概念:按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。
                      通俗的来说就是:就是爬虫可以模拟浏览器的行为做你想做的事,订制化自己搜索和下载的内容,并实现自动化的操作。


    爬虫实现: 实现爬虫技术的编程环境有很多种,Java,Python,C++等都可以用来爬虫

    爬虫包含6个模块:

    • url管理器
    • download下载器
    • parser解析器
    • output导出数据
    • crawler爬虫调度器
    • useragent代理池

    爬虫学习知识点:
    1、首先学会基本的Python语法知识
    2、学习Python爬虫常用到的几个重要内置库urllib, http等,用于下载网页
    3、学习正则表达式re、BeautifulSoup(bs4)、Xpath(lxml)等网页解析工具
    4、开始一些简单的网站爬取(博主从百度开始的,哈哈),了解爬取数据过程
    5、了解爬虫的一些反爬机制,header,robot,时间间隔,代理ip,隐含字段等
    6、学习一些特殊网站的爬取,解决登录、Cookie、动态网页等问题
    7、了解爬虫与数据库的结合,如何将爬取数据进行储存
    8、学习应用Python的多线程、多进程进行爬取,提高爬虫效率
    9、学习爬虫的框架,Scrapy、PySpider等
    10、学习分布式爬虫(数据量庞大的需求)

    一个请求过程在浏览器输入网址搜索后----->DNS服务器进行域名解析----->找到对应服务器并通过GET或POST方法请求数据----->
    -       ---->若请求成功,我们就得到了我们想看到的网页----->
                            ---->若请求不成功,服务器会返回给我们请求失败的状态码,常见到的503,403等


    爬虫的原理:Python爬虫通过URL管理器,判断是否有待爬URL,如果有待爬URL,通过调度器进行传递给下载器,下载URL内容,并通过调度器传送给解析器,解析URL内容,并将价值数据和新URL列表通过调度器传递给应用程序,并输出价值信息的过程;

    爬虫的基本流程,主要可以分为三部分:

    • 获取网页
    • 解析网页(提取数据)
    • 存储数据

    爬虫相关的包与工具

    • 一些爬虫工具:Octoparse、Cyotek WebCopy、HTTrack、Getleft、Scraper等;
    • 获取网页:request、urllib、selenium | 多进程多线程抓取、登陆抓取、突破IP封锁、服务器抓取;
    • 解析网页:re正则表达式、BeautifulSoup、Ixml | 解决中文乱码
    • 存储数据:存入txt文件、存入csv文件 | 存入数据库


    python请求:urllib库:向服务器发出请求并获得网页的功能
    Python2.x中使用的urllib2和urllib库,而Python3.x中合并成一个唯一的urllib库。
    python属性:error,parse,request,response。

    1、Error:“Exception classesraised by urllib.”----就是由urllib举出的exception类
    2、Parse:“Parse (absolute andrelative) URLs.”----解析绝对和相对的URLs
    3、Request:“An extensiblelibrary for opening URLs using a variety of protocols”
    ----用各种协议打开URLs的一个扩展库
    4、Response:“Response classesused by urllib.”----被urllib使用的response类

    一个简单例子:获取python网页

    import urllib.request
    response = urllib.request.urlopen('http://python.org/')
    result = response.read().decode('utf-8')
    print(result)

    其中urlopen方法

    def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TI
    MEOUT,*, cafile=None, capath=None,
    cadefault=False, context=None):

    参数介绍:
    url:即是我们输入的url网址,(如:http://www.xxxx.com/);
    data: 是我们要发给服务器请求的额外信息(比如登录网页需要主动填写的用户信息)。如果需要添加data参数,
                那么是POST请求,默认无data参数时,就是GET请求;
                一般来讲,data参数只有在http协议下请求才有意义
               data参数被规定为byte object,也就是字节对象
               data参数应该使用标准的结构,这个需要使用urllib.parse.urlencode()将data进行 转换,
               而一般我们把data设置成字典格式再进行转换即可;data在以后实战中会介绍如何使用
    timeout:是选填的内容,定义超时时间,单位是秒,防止请求时间过长,不填就是默认的时间;
    cafile:是指向单独文件的,包含了一系列的CA认证 (很少使用,默认即可);
    capath:是指向文档目标,也是用于CA认证(很少使用,默认即可);
    cafile:可以忽略
    context:设置SSL加密传输(很少使用,默认即可);

    打开链接后其他操作:

    geturl(): 返回URL,用于看是否有重定向。
    result = response.geturl()
    结果: https://www.python.org/
    info():返回元信息,例如HTTP的headers。
           result = response.info()
    结果:
    x-xss-protection: 1; mode=block
    X-Clacks-Overhead: GNU Terry Pratchett
    ...
    Vary: Cookie
    Strict-Transport-Security: max-age=63072000;includeSubDomains
    getcode():返回回复的HTTP状态码,成功是200,失败可能是503等,可以用来检查代理IP的可使用性。
    result = response.getcode()
    结果:200
    Request方法
    class Request:
          def __init__(self, url, data=None, headers={},origin_req_host=None, unverifiable=False,method=None):


    参数介绍:
    url,data和上面urlopen中的提到的一样。
    headers是HTTP请求的报文信息,如User_Agent参数等,它可以让爬虫伪装成浏览器而不被服务器发现你正在使用爬虫。
    origin_reg_host, unverifiable, method等不太常用


    headers很有用,有些网站设有反爬虫机制,检查请求若没有headers就会报错,
    因此为保证爬虫的稳定性,基本每次都会将headers信息加入进去,这是反爬的简单策略之一

    import urllib.request
    headers = {'User_Agent': ''}
    response = urllib.request.Request('http://python.org/', headers=headers)
    html = urllib.request.urlopen(response)
    result = html.read().decode('utf-8')
    print(result)

    error的使用:error属性里面主要包括了两个重要的exception类,URLError类和HTTPError类。

    1. URLError类
    
    def __init__(self, reason, filename=None):
        self.args = reason,
        self.reason = reason
        if filename is not None:
            self.filename = filename
    URLError类是OSError的子类,继承OSError,没有自己的任何行为特点,但是将作为error里面所有其它类型的基类使用。
    URLError类初始化定义了reason参数,意味着当使用URLError类的对象时,可以查看错误的reason。
    2. HTTPErro类
    
    def __init__(self, url, code, msg, hdrs, fp):
        self.code = code
        self.msg = msg
        self.hdrs = hdrs
        self.fp = fp
        self.filename = url
    HTTPError是URLError的子类,当HTTP发生错误将举出HTTPError。
    HTTPError也是HTTP有效回应的实例,因为HTTP协议错误是有效的回应,包括状态码,headers和body。所以看到在HTTPError初始化的时候定义了这些有效回应的参数。
    当使用HTTPError类的对象时,可以查看状态码,headers等
    案例1:
    import urllib.request
    import urllib.error
    try:
        headers = {'User_Agent': 'Mozilla/5.0 (X11; Ubuntu; 
                    Linux x86_64; rv:57.0) Gecko/20100101 
                    Firefox/57.0'}
        response = urllib.request.Request('http://python.org/', 
                                           headers=headers)
        html = urllib.request.urlopen(response)
        result = html.read().decode('utf-8')
    except urllib.error.URLError as e:
        if hasattr(e, 'reason'):
            print('错误原因是' + str(e.reason))
    except urllib.error.HTTPError as e:
        if hasattr(e, 'code'):
            print('错误状态码是' + str(e.code))
    else:
        print('请求成功通过。')

    项目实战:

    import requests  # 发送请求
    from lxml import etree  # 数据解析
    import time  # 线程暂停,怕封ip
    import os  # 创建文件夹
    
    # 由于目标网站更新了反爬虫机制,简单的UA伪装不能满足我们的需求,所有对整个消息头进行了伪装
    headers = {
        'Accept':
            'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        'Accept-Encoding':
            'gzip, deflate, br',
        'Accept-Language':
            'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
        'Cache-Control':
            'max-age=0',
        'Connection':
            'keep-alive',
        'Cookie':
            '__gads=undefined; Hm_lvt_aecc9715b0f5d5f7f34fba48a3c511d6=1614145919,1614755756; '
            'UM_distinctid=177d2981b251cd-05097031e2a0a08-4c3f217f-144000-177d2981b2669b; '
            'sctj_uid=ccf8a73d-036c-78e4-6b1d-6035e961b0d3; '
            'CNZZDATA300636=cnzz_eid%3D1737029801-1614143206-%26ntime%3D1614759211; '
            'Hm_lvt_398913ed58c9e7dfe9695953fb7b6799=1614145927,1614755489,1614755737; '
            '__gads=ID=af6dc030f3c0029f-226abe1136c600e4:T=1614760491:RT=1614760491:S=ALNI_MZAA0rXz7uNmNn6qnuj5BPP7heStw; '
            'ASP.NET_SessionId=3qd454mfnwsqufegavxl5lbm; Hm_lpvt_398913ed58c9e7dfe9695953fb7b6799=1614760490; '
            'bbsmax_user=ce24ea68-9f80-42e3-8d4f-53b13b13c719; avatarId=a034b11b-abc9-4bfd-a8b2-bdf7fef644bc-; '
            'Hm_lpvt_aecc9715b0f5d5f7f34fba48a3c511d6=1614756087',
        'Host':
            'sc.chinaz.com',
        'If-None-Match':
            '',
        'Referer':
            'https://sc.chinaz.com/jianli/free.html',
        'Upgrade-Insecure-Requests':
            '1',
        'User-Agent':
            'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0',
    }
    
    # 如果该文件夹不存在,则创建文件夹
    if not os.path.exists('E:moban'):
        os.mkdir('E:moban')
    
    for i in range(2, 701):  # 预计可爬700*20套简历模板
        print(f"正准备爬取第{i}页简历模板")
        print("怕封ip,操作暂停中......")  # 操作暂停提示语
        time.sleep(15)  # 每获取一个列表页暂停15s,一个列表页有20分简历模板的链接
        url = f'https://sc.chinaz.com/jianli/free_{str(i)}.html'  # 设置相应的路由i
        try:  # 异常处理
            response = requests.get(url=url, headers=headers)  # 获取响应
        except Exception as e:  # 给异常取名为e
            print(e)  # 打印异常名称
            print('连接失败,选择跳过!!!')  # 连不上就不要连了,头铁容易出事
            print("怕封ip,获取列表页操作暂停中......")  # 操作暂停提示语
            time.sleep(5)  # 每出现一次异常暂停5s
            continue  # 跳过本次循环
        response.encoding = 'utf-8'  # 中文编码为utf-8
        page = response.text  # 获取响应的文本数据
        tree = etree.HTML(page)  # 用etree进行数据解析
        a_list = tree.xpath("//div[@class='box col3 ws_block']/a")  # 用xpath提取目标内容形成20份一起的列表
     
        for a in a_list:
            resume_href = 'https:' + a.xpath('./@href')[0]  # 根据爬取的链接设置新的网页
            resume_name = a.xpath('./img/@alt')[0]  # 爬取名字,并对列表进行切片取第一个
            resume_name = resume_name.strip()  # 去掉首尾的空格
            try:
                resume_response = requests.get(url=resume_href, headers=headers)  # 进入简历模板详情页面
            except Exception as e:
                print(e)
                print('连接失败,选择跳过!!!')
                print("怕封ip,获取个人简历详情页操作暂停中......")
                time.sleep(5)
                continue
            resume_response.encoding = 'utf-8'  # 中文编码为utf-8
            resume_page = resume_response.text  # 获取响应的文本数据
            resume_tree = etree.HTML(resume_page)  # 用etree进行数据解析
            resume_link = resume_tree.xpath('//ul[@class="clearfix"]/li/a/@href')[0]  # 用xpath提取目标内容的下载链接
            try:
                download = requests.get(url=resume_link, headers=headers).content  # 获取二进制数据
            except Exception as e:
                print(e)
                print('连接失败,选择跳过!!!')
                print("怕封ip,下载个人简历操作暂停中......")
                time.sleep(5)
                continue
            download_path = 'E:moban' + resume_name + '.zip'  # 设置保存路径以及文件名称
            with open(download_path, 'wb') as fp:  # 设置文件制作,以二进制形式
                fp.write(download)  # 保存文件
                print(resume_name, '下载成功!!!')  # 下载成功提示语

     本文转载:https://segmentfault.com/a/1190000012681700






    心有猛虎,细嗅蔷薇
  • 相关阅读:
    项目结束后一点心得
    提交disabled按钮的几种方法
    发现VS2005一个BUG
    单一文件上传防止粘帖及格式限制
    MessageBox.Show常用的2个方法
    一点感受一点体会
    EXCEL导入GridView,然后再汇入数据库.
    2根ECC内存
    (转载)gridview添加删除确认对话框
    反射调用Method
  • 原文地址:https://www.cnblogs.com/1314520xh/p/14769702.html
Copyright © 2011-2022 走看看