zoukankan      html  css  js  c++  java
  • 爬虫

    数据分析
    • 爬虫:通过编写程序员模拟浏览器上网,然后让其去互联网上爬取/获取数据的过程。
    • 分类(使用场景):
    • 通用爬虫:爬取一整张页面数据。“抓取系统”
    • 聚焦爬虫:爬取的就是页面中指定的内容
    • 增量式爬虫:用来检测网站数据更新的情况。只爬取网站最新更新的数据。
    • 协议:客户端和服务器端进行数据交互的某种形式
    • 请求头信息:
    • User-Agent:请求载体的身份标识
    • Connection:close
    • 响应头信息:
    • Content-Type:
    • https:安全
    • 加密方式:
    • 对称秘钥加密:
    • 非对称秘钥加密:
    • 证书秘钥加密:

    反爬机制: 反反爬:

    1.robots.txt协议                    忽略此协议
    2.UA测验                            在请求参数中添加headers(模拟网站发请求)
    3.验证码                            云打码、超级鹰、打码兔
    4.cookie                           用session发送请求
    5、检测ip                           找个代理(透明(能发现你的ip)、匿名(可以发现代理服务器的ip,不能发现你的ip)、高匿(既不能发现你的也不能发现代理的ip))
    6、动态参数                          动态获取
    7、动态加载                          selenium滑动加载
    - requests模块:网络请求的一个模块。
    - 环境的安装:pip install requests
    
    
    - reqeusts模块的作用:
        - 模拟浏览器发请求。
        
    - requests模块的编码流程:
        - 1.指定url
        - 2.发起请求
        - 3.获取响应数据
        - 4.持久化存储
    

    案例1:爬取sogou首页文本内容

    #导入模块
    import requests
    #指定url
    url = 'https://www.sogou.com/'
    #发起请求:get方法的返回值就是一个响应对象
    response = requests.get(url=url)
    #获取响应数据:text属性返回的是字符串形式的响应数据
    page_text = response.text
    #step_4:持久化存储
    with open('./sogou.html','w',encoding='utf-8') as fp:
        fp.write(page_text)

    案例2:爬取搜狗指定词条搜索后的页面数据

    import requests
    url = 'https://www.sogou.com/web'
    #处理url请求的参数
    wd = input('enter a word:')
    param = {
        'query':wd
    }
    response = requests.get(url=url,params=param)
    #设置响应数据的编码
    response.encoding = 'utf-8'
    page_text = response.text
    print(page_text)
    name = wd+'.html'
    with open(name,'w',encoding='utf-8') as fp:
        fp.write(page_text)
        print(name,'爬取成功!')
    
    
    
    如何实现聚焦爬虫(数据解析)
    • 编码流程:
    • 指定url
    • 发起请求
    • 获取响应数据
    • 数据解析
    • 持久化存储
    • 如何实现数据解析
    • 正则
    • bs4
    • xpath
    • 数据解析的原理
    • 实现标签定位
    • 将标签中存储的文本内容或者相关的属性值进行提取

    案例:如何爬取一张图片数据(方法一)

    import requests
    url = 'https://pic.qiushibaike.com/system/pictures/12176/121763419/medium/GKAGFQXQTVNBYK37.jpg'
    headers = {
        'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'
    }
    response = requests.get(url=url,headers=headers)
    #content二进制形式的图片数据
    img_data = response.content  
    
    
    with open('./qiutu.jpg','wb') as fp:
        fp.write(img_data)

    案例:如何爬取一张图片数据(方法二)

    import requests
    from urllib import request
    url = 'https://pic.qiushibaike.com/system/pictures/12176/121763419/medium/GKAGFQXQTVNBYK37.jpg'
    request.urlretrieve(url=url,filename='./qiubai.jpg')#filename存储文件路径

    案例:爬取所有的糗图数据

    import requests
    import os
    import re
    from urllib import request
    url = 'https://www.qiushibaike.com/pic/'
    headers = {
        'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'
    }
    page_text = requests.get(url=url,headers=headers).text
    #创建一个文件夹用来存储下载好的所有的图片
    if not os.path.exists('./qiutu'):   #指定路径
        os.mkdir('./qiutu')
    #进行数据解析(img标签)
    ex = '<div class="thumb">.*?<img src="(.*?)" alt.*?</div>'
    img_src_list = re.findall(ex,page_text,re.S)
    for src in img_src_list:
        src = 'https:'+src
        name = src.split('/')[-1]
        img_path = './qiutu/'+name
        request.urlretrieve(src,img_path)
        print(name,'下载成功!')
    print('下载完毕,共下载图片数量为:',len(img_src_list))
    bs4数据解析
    • 环境安装:
    • pip install bs4
    • pip install lxml
    • bs4解析原理
    • 实例化一个BeautifulSoup对象,必须把即将被解析的页面源码加载到该对象中
    • 调用该对象中相关的属性或者方法进行标签的定位和内容的提取
    • 如何实例化一个BeautifulSoup对象
    • 本地加载:
    • soup = BeautifulSoup(fp,'lxml')
    • 网络加载:
    • soup = BeautifulSoup(page_text,'lxml')
    相关的属性和方法
    • soup.tagName:定位标签(只可以定位到第一次出现的标签),返回的永远是一个单数
    • soup.find(tagName,attrName="value"):基于属性定位实现的标签定位。返回的永远是一个单数
    • soup.find_all():返回的永远是一个列表
    • 取文本:
    • string:取得标签中直系的文本内容
    • text/get_text():取得的是标签下面所有的文本内容
    • 取属性:tag['attrName']
    • select:使用选择器定位标签。返回的是列表
    • 标签,类,id选择器:select('选择器')
    • 层级选择器:
    • 单层级:'.tang > ul > li
    • 多层级:'.tang li

    案例:爬取三国演义整片小说内容

    import requests
    from bs4 import BeautifulSoup
    #获取页面源码数据
    url = ' http://www.shicimingju.com/book/sanguoyanyi.html'
    headers = {
        'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'
    }
    page_text = requests.get(url=url,headers=headers).text
    
    
    #实例化soup对象
    soup = BeautifulSoup(page_text,'lxml')
    #解析出章节标题和详情页的链接
    li_list = soup.select('.book-mulu > ul > li')
    fp = open('./sanguo.txt','w',encoding='utf-8')
    for li in li_list:
        title = li.a.string
        detail_url = 'http://www.shicimingju.com'+li.a['href']
        
        #对详情页url发起请求,进行章节内容的解析提取
        detail_page_text = requests.get(url=detail_url,headers=headers).text
        #将详情页中的章节内容解析提取
        detail_soup = BeautifulSoup(detail_page_text,'lxml')
        div_tag = detail_soup.find('div',class_="chapter_content")
        content = div_tag.text
        fp.write(title+':'+content+'
    ')
        print(title,'下载存储成功!')
        
    fp.close()
    xpath解析

    - 通用性比较强

    - 环境的安装:pip install lxml

    - 解析原理:

    - 1.实例化一个etree对象,且将解析的页面源码加载到该对象中

    - 2.使用该对象中的xpath方法结合着xpath表达式进行标签定位和数据解析提取

    - etree对象的实例化:

    - 本地加载:

    tree = etree.parse('filePath')

    - 网络加载:

    tree = etree.HTML(page_text)

    常用的xpath表达式:基于标签的层级实现定位. 返回的永远是一个列表

    • /:从根标签开始实现层级定位
    • //:从任意位置实现标签的定位
    • 属性定位:tag[@attrName="attrValue"]
    • 索引定位://div[@class="tang"]/ul/li[5] 索引值是从1开始
    • 取文本:
    • 取得直系文本内容:/text()
    • 取得所有的文本内容://text()
    • 取属性:/@attrName

    案例:爬取58二手房的房源信息

    from lxml import etree
    import requests
    headers = {
        'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'
    }
    url = 'https://bj.58.com/shahe/ershoufang/?PGTID=0d30000c-0047-e8f5-0211-cc2e07b06314&ClickID=1'
    page_text = requests.get(url=url,headers=headers).text
    
    
    
    
    #数据解析(房屋的名称和价格)
    tree = etree.HTML(page_text)
    li_list = tree.xpath('//ul[@class="house-list-wrap"]/li')
    all_data_list = []
    for li in li_list:
        name = li.xpath('./div[2]/h2/a/text()')[0]#  ./表示的就是li标签
        detail_url = li.xpath('./div[2]/h2/a/@href')[0]
        if 'https:' not in detail_url:
            detail_url = 'https:'+detail_url
            
        price = li.xpath('./div[3]//text()')
        price = ''.join(price)
    #     print(name,price,detail_url)
        #获取详情页的页面源码数据,提取解析出房屋概况
        detail_page_text = requests.get(url=detail_url,headers=headers).text
        tree = etree.HTML(detail_page_text)
        desc = tree.xpath('//div[@id="generalSituation"]//text()')
        desc = ''.join(desc)
        dic = {
            'name':name,
            'price':price,
            'desc':desc
        }
        all_data_list.append(dic)
    print(all_data_list,len(all_data_list)

    案例:需求爬取当前页面全部的城市名称https://www.aqistudy.cn/historydata/

    url = 'https://www.aqistudy.cn/historydata/'
    page_text = requests.get(url=url,headers=headers).text
    tree = etree.HTML(page_text)
    #热门城市://div[@class="bottom"]/ul/li/a/text()
    #全部城市://div[@class="bottom"]/ul/div[2]/li/a/text()
    all_city_names = tree.xpath('//div[@class="bottom"]/ul/li/a/text() | //div[@class="bottom"]/ul/div[2]/li/a/text()')
    print(all_city_names,len(all_city_names))
    模拟登陆的意义:

    - 爬取基于某些用户的用户信息

    验证码识别:云打码平台
    • 使用流程:
    • 注册
    • 登陆:
    • 普通用户:
    • 查询剩余提分(充值)
    • 开发者用户:
    • 创建软件:我的软件-》添加新软件(ID,秘钥)
    • 下载示例代码:开发文档-》点此下载:云打码接口DLL-》PythonHTTP示例下载
    import http.client, mimetypes, urllib, json, time, requests
    
    
    ######################################################################
    
    
    class YDMHttp:
    
    
    
    
        apiurl = 'http://api.yundama.com/api.php'
        username = ''
        password = ''
        appid = ''
        appkey = ''
    
    
        def __init__(self, username, password, appid, appkey):
            self.username = username  
            self.password = password
            self.appid = str(appid)
            self.appkey = appkey
    
    
    
    
        def request(self, fields, files=[]):
            response = self.post_url(self.apiurl, fields, files)
            response = json.loads(response)
            return response
        
        def balance(self):
            data = {'method': 'balance', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey}
            response = self.request(data)
            if (response):
                if (response['ret'] and response['ret'] < 0):
                    return response['ret']
                else:
                    return response['balance']
            else:
                return -9001
        
        def login(self):
            data = {'method': 'login', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey}
            response = self.request(data)
            if (response):
                if (response['ret'] and response['ret'] < 0):
                    return response['ret']
                else:
                    return response['uid']
            else:
                return -9001
    
    
        def upload(self, filename, codetype, timeout):
            data = {'method': 'upload', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey, 'codetype': str(codetype), 'timeout': str(timeout)}
            file = {'file': filename}
            response = self.request(data, file)
            if (response):
                if (response['ret'] and response['ret'] < 0):
                    return response['ret']
                else:
                    return response['cid']
            else:
                return -9001
    
    
        def result(self, cid):
            data = {'method': 'result', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey, 'cid': str(cid)}
            response = self.request(data)
            return response and response['text'] or ''
    
    
    
    
        def decode(self, filename, codetype, timeout):
            cid = self.upload(filename, codetype, timeout)
            if (cid > 0):
                for i in range(0, timeout):
                    result = self.result(cid)
                    if (result != ''):
                        return cid, result
                    else:
                        time.sleep(1)
                return -3003, ''
            else:
                return cid, ''
    
    
        def report(self, cid):
            data = {'method': 'report', 'username': self.username, 'password': self.password, 'appid': self.appid, 'appkey': self.appkey, 'cid': str(cid), 'flag': '0'}
            response = self.request(data)
            if (response):
                return response['ret']
            else:
                return -9001
    
    
        def post_url(self, url, fields, files=[]):
            for key in files:
                files[key] = open(files[key], 'rb');
            res = requests.post(url, files=files, data=fields)
            return res.text
    
    
    ######################################################################
    
    
    # 普通用户名
    username    = 'bobo328410948'
    
    
    # 密码
    password    = 'bobo328410948'                            
    
    
    # 软件ID,开发者分成必要参数。登录开发者后台【我的软件】获得!
    appid       = 6003                                    
    
    
    # 软件密钥,开发者分成必要参数。登录开发者后台【我的软件】获得!
    appkey      = '1f4b564483ae5c907a1d34f8e2f2776c'    
    
    
    # 图片文件
    filename    = 'getimage.jpg'                        
    
    
    # 验证码类型,# 例:1004表示4位字母数字,不同类型收费不同。请准确填写,否则影响识别率。在此查询所有类型 http://www.yundama.com/price.html
    codetype    = 1004
    
    
    # 超时时间,秒
    timeout     = 30                                    
    
    
    # 检查
    if (username == 'username'):
        print('请设置好相关参数再测试')
    else:
        # 初始化
        yundama = YDMHttp(username, password, appid, appkey)
    
    
        # 登陆云打码
        uid = yundama.login();
        print('uid: %s' % uid)
    
    
        # 查询余额
        balance = yundama.balance();
        print('balance: %s' % balance)
    
    
        # 开始识别,图片路径,验证码类型ID,超时时间(秒),识别结果
        cid, result = yundama.decode(filename, codetype, timeout);
        print('cid: %s, result: %s' % (cid, result))
    
    
    ###############################################

    案例:人人网携带验证码的模拟登陆

    import requests
    from lxml import etree
    from urllib import request
    # from CodeClass import YDMHttp
    
    
    #封装识别验证码图片的函数
    def getCodeText(codeType,filePath):
        result = None
            # 普通用户名
        username    = 'bobo328410948'
    
    
        # 密码
        password    = 'bobo328410948'                            
    
    
        # 软件ID,开发者分成必要参数。登录开发者后台【我的软件】获得!
        appid       = 6003                                    
    
    
        # 软件密钥,开发者分成必要参数。登录开发者后台【我的软件】获得!
        appkey      = '1f4b564483ae5c907a1d34f8e2f2776c'    
    
    
        # 图片文件
        filename    = filePath                        
    
    
        # 验证码类型,# 例:1004表示4位字母数字,不同类型收费不同。请准确填写,否则影响识别率。在此查询所有类型 http://www.yundama.com/price.html
        codetype    = codeType
    
    
        # 超时时间,秒
        timeout     = 40                                    
    
    
        # 检查
        if (username == 'username'):
            print('请设置好相关参数再测试')
        else:
            # 初始化
            yundama = YDMHttp(username, password, appid, appkey)
    
    
            # 登陆云打码
            uid = yundama.login();
            print('uid: %s' % uid)
    
    
            # 查询余额
            balance = yundama.balance();
            print('balance: %s' % balance)
    
    
            # 开始识别,图片路径,验证码类型ID,超时时间(秒),识别结果
            cid, result = yundama.decode(filename, codetype, timeout);
            print('cid: %s, result: %s' % (cid, result))
        return result
                
    url = 'http://www.renren.com/SysHome.do'
    headers = {
        'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'
    }
    page_text = requests.get(url=url,headers=headers,proxies={'http':'116.228.233.90:8082'}).text
    #解析出验证码图片的地址
    tree = etree.HTML(page_text)
    code_img_url = tree.xpath('//*[@id="verifyPic_login"]/@src')[0]
    request.urlretrieve(url=code_img_url,filename='./code.jpg')
    
    
    #使用打码平台识别验证码
    code_text = getCodeText(2004,'./code.jpg')
    # print(code_text)
    
    
    #模拟登陆
    login_url = 'http://www.renren.com/ajaxLogin/login?1=1&uniqueTimestamp=2019401113761'
    data = {
        "email": "www.zhangbowudi@qq.com",
        "icode": code_text,
        "origURL": "http://www.renren.com/home",
        "domain": "renren.com",
        "key_id": "1",
        "captcha_type": "web_login",
        "password": "17108719a8907d7a716631afc519561080a50ea31d92f64ae5f9ccd64b41e4b1",
        "rkey": "465733ef9b05bd790ec81e9347025808",
        "f": "http%3A%2F%2Fwww.renren.com%2F289676607",
    }
    #创建一个回话对象
    session = requests.Session()
    #产生cookie
    response = session.post(url=login_url,headers=headers,data=data,proxies={'http':'119.180.135.210:8060'})
    # print(response.status_code)
    
    
    # page_text = response.text
    # print(page_text)
    
    
    #该次请求发送必须携带cookie
    detail_url = 'http://www.renren.com/289676607/profile'
    detail_page_text = session.get(url=detail_url,headers
    代理:代理服务器

    - 快代理

    - 西祠代理

    - goubanjia

    • 匿名度:
    • 透明:对方服务器知道你使用了代理ip也知道你的真实ip
    • 匿名:知道你使用了代理ip但是不知道你的真实ip
    • 高匿:什么都不知道
    • 类型:
    • http:只可以发起http请求
    • https:只可以发起https的请求

    案例:简单代理池应用

    http_list = [
        {'http':'60.190.250.120:8080'},
        {'http':'60.190.250.120:8080'},
        {'http':'60.190.250.120:8080'}
    ]
    https_list = [
        {'https':'60.190.250.120:8080'},
        {'https':'60.190.250.120:8080'},
        {'https':'60.190.250.120:8080'}
    ]
    url = 'http://www.baidu.com/s?wd=ip'
    page_text = requests.get(url=url,headers=headers,proxies={'http':'60.190.250.120:8080'}).text
    with open('./ip.html','w',encoding='utf-8') as fp:
        fp.write(page_text)
    import random
    url = 'http://www.baidu.com/s?wd=ip'
    response = requests.get(url=url,headers=headers,proxies=)
    page_text = response.text
    if response.url.split(':')[0] == 'http'
    with open('./ip.html','w',encoding='utf-8') as fp:
        fp.write(page_text)
    cookie的应用和处理

    - cookie:服务器端记录客户端的相关状态

    - 处理cookie的方式:

    - 手动处理:不建议

    - 自动处理:回话对象Session,该对象可以像requests模块一样进行网络请求的发送(get,post)。session进行的请求发送可以自动携带和处理cookie。

    案例:基于cookie的案例分析:https://xueqiu.com/

    import requests
    headers = {
        'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'
    }
    #自动获取cookie,cookie就会自动存储到session中
    session = requests.Session()
    session.get('https://xueqiu.com/',headers=headers)
    
    
    
    
    #捕获ajax数据包获取的url
    url = 'https://xueqiu.com/v4/statuses/public_timeline_by_category.json?since_id=-1&max_id=-1&count=10&category=-1'
    #携带cookie进行的请求发送
    dic_json = session.get(url=url,headers=headers).json()
    print(dic_json)
    #从响应数据中获取详情页的url
    # for dic in dic_json['list']:
    # #     print(dic)
    #     d = dic['data']
    #     detail_url = 'https://xueqiu.com'+d['target']
    #     print(detail_url
    • 验证码处理:打码兔,云打码
    • 模拟登陆:点击登陆按钮对应的post发起请求(参数的处理和携带)
    • 爬取登陆后的先关的页面数据(模拟登陆后会产生cookie)
    • 如何处理cookie:
    • 手动:
    • 自动:回话对象。
    • 代理:
    • 网站
    • 匿名度:
    • 类型:
    • 代理应用在requests中
    • get和post(参数):
    • url
    • headers
    • data/prams
    • proxies
    如何提升requests模块爬取数据的效率
    • 多进程或者多线程(不建议)
    • 线程池或者进程池(适当使用)
    • 单线程+异步协程(推荐)

    案例:实例化一个线程池提高爬虫效率

    import requests
    import re
    from lxml import etree
    from multiprocessing.dummy import Pool
    import random
    headers = {
        'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'
    }
    def request_video(url):
        return requests.get(url=url,headers=headers).content
    def saveVideo(data):
        name = str(random.randint(0,9999))+'.mp4'
        with open(name,'wb') as fp:
            fp.write(data)
            print(name,'下载存储成功!!!')
    url = 'https://www.pearvideo.com/category_1'
    page_text = requests.get(url=url,headers=headers).text
    
    
    tree = etree.HTML(page_text)
    li_list = tree.xpath('//ul[@id="listvideoListUl"]/li')
    #实例化一个线程池对象
    pool = Pool(4)
    video_url_list = [] #所有的视频连接
    for li in li_list:
        detail_url = 'https://www.pearvideo.com/'+li.xpath('./div/a/@href')[0]
        detail_page_text = requests.get(url=detail_url,headers=headers).text
        ex = 'srcUrl="(.*?)",vdoUrl='
        video_url = re.findall(ex,detail_page_text,re.S)[0]
        video_url_list.append(video_url)
    #异步的获取4个视频的二进制数据
    video_data_list = pool.map(request_video,video_url_list)
    
    
    #进行视频的持久化存储
    pool.map(saveVideo,video_data_list
    selenium
    • 概念:用来完成浏览器自动化相关的操作。可以通过代码的形式制定一些基于浏览器自动化的相关操作(行为动作),当代码执行后,浏览器就会自动触发先关的事件
    • 环境安装:
    • pip install selenium
    • 下载对应浏览器的驱动程序
    • 编码流程:
    • 导包:from selenium import webdriver
    • 实例化某一款浏览器对象
    • 制定相关的行为动作

    案例:执行js实现滚轮向下滑动

    from selenium import webdriver
    from time import sleep
    bro = webdriver.Chrome(executable_path='./chromedriver.exe')
    
    
    bro.get('https://xueqiu.com/')
    sleep(5)
    
    
    #执行js实现滚轮向下滑动
    js = 'window.scrollTo(0,document.body.scrollHeight)'   #向下滑动一屏高度,
    bro.execute_script(js)
    sleep(2)
    bro.execute_script(js)
    sleep(2)
    bro.execute_script(js)
    sleep(2)
    bro.execute_script(js)
    sleep(2)
    
    
    a_tag = bro.find_element_by_xpath('//*[@id="app"]/div[3]/div/div[1]/div[2]/div[2]/a')
    a_tag.click()
    sleep(5)
    #获取当前浏览器页面数据(动态)
    print(bro.page_source)
    
    
    bro.qui

    案例:PhantomJs是一款无可视化界面的浏览器(免安装)

    from selenium import webdriver
    from time import sleep
    bro = webdriver.PhantomJS(executable_path=r'C:UsersAdministratorDesktop爬虫+数据爬虫day03phantomjs-2.1.1-windowsinphantomjs.exe')
    
    
    bro.get('https://xueqiu.com/')
    sleep(2)
    bro.save_screenshot('./1.png')
    #执行js实现滚轮向下滑动
    js = 'window.scrollTo(0,document.body.scrollHeight)'
    bro.execute_script(js)
    sleep(2)
    bro.execute_script(js)
    sleep(2)
    bro.execute_script(js)
    sleep(2)
    bro.execute_script(js)
    sleep(2)
    bro.save_screenshot('./2.png')
    # a_tag = bro.find_element_by_xpath('//*[@id="app"]/div[3]/div/div[1]/div[2]/div[2]/a')
    # bro.save_screenshot('./2.png')
    # a_tag.click()
    sleep(2)
    #获取当前浏览器页面数据(动态)
    print(bro.page_source)
    
    
    bro.quit(

    案例:谷歌无头浏览器

    from selenium import webdriver
    from time import sleep
    from selenium.webdriver.chrome.options import Options
    # 创建一个参数对象,用来控制chrome以无界面模式打开
    chrome_options = Options()
    chrome_options.add_argument('--headless')
    chrome_options.add_argument('--disable-gpu')
    
    
    bro = webdriver.Chrome(executable_path='./chromedriver.exe',options=chrome_options)
    bro.get('https://www.baidu.com')
    sleep(2)
    bro.save_screenshot('1.png')
    #标签定位
    tag_input = bro.find_element_by_id('kw')
    tag_input.send_keys('人民币')
    sleep(2)
    
    
    btn = bro.find_element_by_id('su')
    btn.click()
    sleep(2)
    
    
    print(bro.page_source)
    bro.quit

    案例:前进和后退

    from selenium import webdriver
    from time import sleep
    bro = webdriver.Chrome(executable_path='./chromedriver.exe')
    bro.get('https://www.baidu.com')
    sleep(1)
    bro.get('http://www.goubanjia.com/')
    sleep(1)
    bro.get('https://www.taobao.com')
    sleep(1)
    
    
    bro.back()
    sleep(1)
    bro.forward()
    sleep(1)
    print(bro.page_source)
    
    
    bro.quit(

    案例一:动作链

    from selenium import webdriver
    from time import sleep
    from selenium.webdriver import ActionChains  
    bro = webdriver.Chrome(executable_path='./chromedriver.exe')
    url = 'https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
    bro.get(url=url)
    #如果定位的标签存在于iframe标签之中,则必须经过switch_to操作在进行标签定位
    bro.switch_to.frame('iframeResult')
    source_tag = bro.find_element_by_id('draggable')
    #创建一个动作连的对象
    action = ActionChains(bro)
    action.click_and_hold(source_tag)
    
    
    for i in range(4):
        #perform表示开始执行动作链
        action.move_by_offset(20,0).perform()
        sleep(1)
    bro.quit()

    案例二:动作链

    from selenium import webdriver
    from time import sleep
    from selenium.webdriver import ChromeOptions
    from selenium.webdriver import ActionChains  
    
    
    option = ChromeOptions()
    option.add_experimental_option('excludeSwitches', ['enable-automation'])
    
    
    bro = webdriver.Chrome(executable_path='./chromedriver.exe',options=option)
    url = 'https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
    bro.get(url=url)
    #如果定位的标签存在于iframe标签之中,则必须经过switch_to操作在进行标签定位
    bro.switch_to.frame('iframeResult')
    source_tag = bro.find_element_by_id('draggable')
    taget_tag = bro.find_element_by_id('droppable')
    #创建一个动作连的对象
    action = ActionChains(bro)
    action.drag_and_drop(source_tag,taget_tag)
    action.perform()
    sleep(3)
    # bro.quit()
    
    单线程+异步协程(推荐)
    • event_loop:事件循环,相当于一个无限循环,我们可以把一些函数注册到这个事件循环上,当满足某些条件的时候,函数就会被循环执行。程序是按照设定的顺序从头执行到尾,运行的次数也是完全按照设定。当在编写异步程序时,必然其中有部分程序的运行耗时是比较久的,需要先让出当前程序的控制权,让其在背后运行,让另一部分的程序先运行起来。当背后运行的程序完成后,也需要及时通知主程序已经完成任务可以进行下一步操作,但这个过程所需的时间是不确定的,需要主程序不断的监听状态,一旦收到了任务完成的消息,就开始进行下一步。loop就是这个持续不断的监视器。
    • coroutine:中文翻译叫协程,在 Python 中常指代为协程对象类型,我们可以将协程对象注册到事件循环中,它会被事件循环调用。我们可以使用 async 关键字来定义一个方法,这个方法在调用时不会立即被执行,而是返回一个协程对象。
    • task:任务,它是对协程对象的进一步封装,包含了任务的各个状态。
    • future:代表将来执行或还没有执行的任务,实际上和 task 没有本质区别。
    • 另外我们还需要了解 async/await 关键字,它是从 Python 3.5 才出现的,专门用于定义协程。其中,async 定义一个协程,await 用来挂起阻塞方法的执行。

    案例:基本使用

    import asyncio
    #创建一个协程函数
    async def hello(name):
        print('hello to :',name)
    #获取了一个协程对象
    c = hello('bobo')
    #创建一个事件循环对象
    loop = asyncio.get_event_loop()
    #将协程对象注册到事件循环中,然后启动事件循环对象
    loop.run_until_complete(c)

    案例:task的使用

    import asyncio
    async def hello(name):
        print('hello to :',name)
    
    
    c = hello('bobo')
    loop = asyncio.get_event_loop()
    #就协程进行进一步的封装,封装到了task对象中
    task = loop.create_task(c)
    print(task)
    loop.run_until_complete(task)
    print(task)

    案例:future的使用

    import asyncio
    async def hello(name):
        print('hello to :',name)
    c = hello('bobo')
    task = asyncio.ensure_future(c)
    loop.run_until_complete(task)

    案例:绑定回调(task)

    def callback(task):
        print('i am callback:',task.result())
    import asyncio
    async def hello(name):
        print('hello to :',name)
        return name
    c = hello('bobo')
    task = asyncio.ensure_future(c)
    #给任务对象绑定一个回调函数
    task.add_done_callback(callback)
    loop.run_until_complete(task)

    案例:多任务异步协程(假)

    import asyncio
    async def request(url):
        print('正在下载:',url)
        sleep(2) #非异步模块的代码:在此处如果存在非异步操作代码,则会彻底让asyncio失去异步的效果
        print('下载成功:',url)
    urls = [
        'www.baidu.com',
        'www.taobao.com',
        'www.sogou.com'
    ]
    start = time.time()
    loop = asyncio.get_event_loop()
    tasks = [] #任务列表,放置多个任务对象
    for url in urls:
        c = request(url)
        task = asyncio.ensure_future(c)
        tasks.append(task)   
    #将多个任务对象对应的列表注册到事件循环中
    loop.run_until_complete(asyncio.wait(tasks))
    print('总耗时:',time.time()-start)

    案例:多任务异步协程(真)

    import asyncio
    async def request(url):
        print('正在下载:',url)
    #     sleep(2) #非异步模块的代码:在此处如果存在非异步操作代码,则会彻底让asyncio失去异步的效果
        await asyncio.sleep(2)
        print('下载成功:',url)
    urls = [
        'www.baidu.com',
        'www.taobao.com',
        'www.sogou.com'
    ]
    start = time.time()
    loop = asyncio.get_event_loop()
    tasks = [] #任务列表,放置多个任务对象
    for url in urls:
        c = request(url)
        task = asyncio.ensure_future(c)
        tasks.append(task)    
    #将多个任务对象对应的列表注册到事件循环中
    loop.run_until_complete(asyncio.wait(tasks))
    print('总耗时:',time.time()-start)

    实例:多任务异步操作应用到爬虫中(假)

    import requests
    async def get_page(url):
        print('正在下载:',url)
        #之所以没有实现异步操作,原因是因为requests模块是一个非异步的模块
        response = requests.get(url=url)
        print('响应数据:',response.text)
        print('下载成功:',url)
    start = time.time()
    urls = [
        'http://127.0.0.1:5000/bobo',
        'http://127.0.0.1:5000/jay',
        'http://127.0.0.1:5000/tom'
    ]
    tasks = []
    loop = asyncio.get_event_loop()
    for url in urls:
        c = get_page(url)
        task = asyncio.ensure_future(c)
        tasks.append(task)
    loop.run_until_complete(asyncio.wait(tasks))
    print('总耗时:',time.time()-start)

    实例:多任务异步操作应用到爬虫中(真)

    支持异步的网络请求的模块:aiohttp
    环境安装:pip install aiohttp
    
    
    import aiohttp
    import asyncio
    async def get_page(url):
        async with aiohttp.ClientSession() as session:
            async with await session.get(url=url) as response:
                page_text = await response.text() #read()  json()
                print(page_text)
    start = time.time()
    urls = [
        'http://127.0.0.1:5000/bobo',
        'http://127.0.0.1:5000/jay',
        'http://127.0.0.1:5000/tom',
        'http://127.0.0.1:5000/bobo',
        'http://127.0.0.1:5000/jay',
        'http://127.0.0.1:5000/tom',
        'http://127.0.0.1:5000/bobo',
        'http://127.0.0.1:5000/jay',
        'http://127.0.0.1:5000/tom'
    ]
    tasks = []
    loop = asyncio.get_event_loop()
    for url in urls:
        c = get_page(url)
        task = asyncio.ensure_future(c)
        tasks.append(task)
    loop.run_until_complete(asyncio.wait(tasks))
    print('总耗时:',time.time()-start)

    实例:如何实现数据解析---任务的绑定回调机制

    import aiohttp
    import asyncio
    #回调函数:解析响应数据
    def callback(task):
        print('this is callback()')
        #获取响应数据
        page_text = task.result()
        print('在回调函数中,实现数据解析')
        
    async def get_page(url):
        async with aiohttp.ClientSession() as session:
            async with await session.get(url=url) as response:
                page_text = await response.text() #read()  json()
    #             print(page_text)
                return page_text
    start = time.time()
    urls = [
        'http://127.0.0.1:5000/bobo',
        'http://127.0.0.1:5000/jay',
        'http://127.0.0.1:5000/tom',
        'http://127.0.0.1:5000/bobo',
        'http://127.0.0.1:5000/jay',
        'http://127.0.0.1:5000/tom',
        'http://127.0.0.1:5000/bobo',
        'http://127.0.0.1:5000/jay',
        'http://127.0.0.1:5000/tom'
    ]
    tasks = []
    loop = asyncio.get_event_loop()
    for url in urls:
        c = get_page(url)
        task = asyncio.ensure_future(c)
        #给任务对象绑定回调函数用于解析响应数据
        task.add_done_callback(callback)
        tasks.append(task)
    loop.run_until_complete(asyncio.wait(tasks))
    print('总耗时:',time.time()-start)
    回顾

    - 概述什么是http协议

    - 爬虫中常用头信息

    - https中涉及到的三种加密方式

    - requests模块的作用及编码流程

    - requests如何进行参数封装,为什么要进行参数封装

    - 简述目前接触到的反爬机制及其反反爬策略

    - 什么是动态加载数据

    • 爬虫的分类
    • 通用爬虫:
    • 聚焦爬虫:
    • 增量式:
    • 爬取图片的两种方式
    • 使用requests
    • urllib模块request中urlretrive
    • 数据解析的基本原理
    • 标签的定位
    • 取文本或取属性
    • xpath解析原理
    • 实例化etree对象,且将源码加载到该对象中
    • 使用xpath方法结合着xpath表达式进行标签定位和数据提取
    • 属性定位[@attrName="value"]
    • 索引定位:[1]
    • / //
    • 取文本: /text() //text()
    • 取属性:/@attrName
    • etree对象实例化的方式
    • 本地加载:parse
    • 网络加载:HTML
    • bs4解析原理
    • .tagName 单数
    • find(属性定位) 单数 find('tagName',attrName="value")
    • find_all 复数
    • Beautiful对象实例化方式
    • 面试题:如何爬取携带标签的指定页面内容
    • 验证码识别
    • 使用流程
    • 开发者用户登陆:
    • 创建一个软件
    • 下载示例代码
    • 模拟登录
    • 实现流程(携带验证码):
    • 对登陆页面进行请求,从请求到的页面源码中解析下载验证码图片
    • 使用打码平台对验证码进行识别
    • 基于登陆按钮发起一个post请求(处理参数)
    • 意义or作用:获取cookie
    • cookie处理
    • 处理方式:
    • 手动处理:不建议(通用性不强)
    • 自动处理:回话对象。requests.Session()
    • 代理操作
    • 为什么使用代理
    • 免费代理ip网站
    • 匿名度
    • 透明:
    • 匿名:
    • 高匿:
    • 类型:
    • http:
    • https:
    • requests如何应用代理
    • proxies = {'http':'ip:port'}
    • 代理池(列表):
    • selenium
    • 作用:可以让浏览器完成相关自动化的操作
    • 和爬虫的关联:
    • 模拟登陆
    • 可以获取动态加载的页面数据
    • 编码流程
    • 导包
    • 实例化浏览器对象(驱动)
    • 制定相关自动化的行为动作
    • 标签定位
    • find系列的函数
    • 节点交互
    • click
    • send_keys
    • 执行js
    • 获取页面源码数据
    • page_source
    • iframe包含标签定位:
    • switch_to.frame(id)
    • 规避selenium被检测
    • 无头浏览器
    • robots.txt
    • UA检测
    • 验证码
    • cookie
    • 检测ip
    • 动态参数(token,key)
    • 动态加载的数据
  • 相关阅读:
    安装SQL sever2008时显示重新启动计算机规则失败,应该怎么解决?
    C#获取当前日期时间(转)
    使用JQUERY实现页面局部刷新
    Metal渲染:实现画面比例功能
    Metal渲染:实现旋转/翻转功能
    依赖注入浅析
    iOS 消息推送实现 APNS
    使用#pragma阻止一些warnings
    github 多帐户使用
    Swift 实现Bitmask Option(Enum)
  • 原文地址:https://www.cnblogs.com/hahahu/p/10821854.html
Copyright © 2011-2022 走看看