zoukankan      html  css  js  c++  java
  • 20200225 爬虫-bs4使用及简单代理破解验证码

    昨日回顾

    ## 1 什么是爬虫?
    
    ## 2 爬虫的流程
    
    发送http请求----》别人服务器响应----》拿到响应自己解析(re、bs4、lxml)------》入库(mongodb)
    
    分布式爬虫---redis(blpop/brpop:列表,阻塞队列)
    
    集群和分布式:单实例的项目
    
    集群化的部署:一个项目部署在多台机器上
    
    分布式(微服务):一个项目拆成多个部分,放到不同的服务器上,每个项目单独开发,单独上线
    
    ## 3 requests模块
    
    模拟发送http请求
    
    ​```python
    # 1 可以发送任意请求get,post,delete。。。
    requests.get()
    requests.post()
    # 2 携带头信息
    #user-agent   referer cookie(cookie池)
    requests.get(headers={})
    # 3 cookie单独拿出来
    requests.get(cookies={})
    # 4 get请求携带参数两种方式
    
    # 5 post请求请求体 data/json
    
    # 6 响应对象response 有好多属性
    
    # 7 发送请求,使用代理,随机取一个代理,在列表中通过random
    
    # 8 ssl,timeout,上传文件(项目)
    
    
    1.链式调用
    
    ​```
    在方法中实现 返回自己
    return  self
    即可实现一直...属性
    ​```
    
    2.bs4的搜索文档树的find有几种方式可以查找标签
    
    ​```
    五种过滤器
    
    字符串
    	soup.find(name='标签名',attrs={'属性':'值'})
    列表
    	soup.findall(name=['标签名','标签2'])
    正则
    	使用re.compile('正则规则')
    bool
    	soup.findall(id=true)
    方法
    	定义方法
    	sopu.find_all(方法)
    ​```
    
    3.bs4获取标签属性的方式
    
    ​```
    直接.
    标签.name
    p['class']
    p.attrs.get('class')
    ​```
    
    4.bs4获取标签内容的三种方式,有什么不同
    
    ​```
    text	: 获取所有的文本,包括子标签的文字
    string	: 获取当前第一级目录的文字
    strings	: 获得一个生成器,每层文字放在列表中
    ​```
    
    5.你验证码如何破解
    
    ​```
    打码平台申请调用接口
    ​```
    
    
    

    bs4

    简介

    安装

    pip install beautifulsoup4
    

    导入

    from bs4 import BeautifulSoup4
    

    参数

    # 实例化得到对象
    soup = beautifulsoup(ret.text,'lxml')
        '''
        第一个参数 可以是字符串,或者文件对象
        第二个参数 解析的方式(解析库)
        	html.parser		# python自带的
        	lxml	# 需要另外安装解析库 pip install lxml
        '''
    

    使用

    html_doc = """
    <html><head><title>The Dormouse's story</title></head>
    <body>
    <p class="title"><b>The Dormouse's story</b></p>
    
    <p class="story">Once upon a time there were three little sisters; and their names were
    <a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
    <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
    <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
    and they lived at the bottom of a well.</p>
    
    <p class="story">...</p>
    """
    
    # 实例化得到对象
    soup = BeautifulSoup(html_doc,'lxml')
    
    # 美化,对标签进行闭合
    # soup.prettify()
    

    1 遍历文档树

    # 用法: 直接 . 取下一个标签
    
    p = soup.p
    print(p)    # 对象 <p class="title"><b>The Dormouse's story</b></p>
    

    基本使用

    # 获取标签的名称
    print(p.name)   # p
    
    
    
    # 获取标签的属性
    #     当你获取class的时候,获取的是列表
    print(p['class'])   # ['title']
    print(p.attrs.get('class'))  # ['title']
    
    
    
    # 获取标签的内容
    #     text: 获取所有的文字,包括子标签的文字
    #     string: 获取当前第一级目录的文字,如果嵌套多层,就取不出文字
    #     strings: 获取一个生成器,每层文字分别放在列表中
    p = soup.body.p
    print(p.text)   # The Dormouse's story
    print(p.string)  # The Dormouse's story
    print(p.strings) # <generator object _all_strings at 0x00000206A5DE3A98>
    print(list(p.strings)) # ["The Dormouse's story"]
    

    用的较少(了解)

    # 嵌套选择
    p = soup.body.p
    
    
    
    # 子节点,子孙节点
        # 子节点
    print(soup.body.p.contents)     # [<b>The Dormouse's story</b>]
    
        # 子孙节点
    print(soup.body.p.children)   # <list_iterator object at 0x0000014DDE79CF60>
    print(list(soup.body.p.children))   # [<b>The Dormouse's story</b>]
    
        # 子子孙孙
    print(list(soup.body.p.descendants))   # [<b>The Dormouse's story</b>]
    
    
    
    # 父节点,祖先节点
    print(soup.body.p.parent)   # 直接父节点
    print(soup.body.p.parents)   # 所有父集,祖先的节点 生成器
    
    
    
    # 兄弟节点
    print(soup.a.next_sibling)  # 下一个兄弟
    print(soup.a.previous_sibling)  # 上一个兄弟
    

    2.搜索文档树

    搜索的查找速度比遍历低

    • find()与find_all()
    • 五种过滤器 : 字符串,列表,正则,bool,方法
    # 字符串: 精准匹配
    
        # 属性查找的方式一
    p = soup.find(name='p',class_='story')  # p是标签对象,和soup是一样的
    print(p)
        # 属性查找方式二
    p = soup.find(name='p',attrs={'class':'story'})
    print(p)
    
    
    
    
    # 列表查
    ret = soup.find_all(name=['p','a'])
    ret = soup.find_all(id=['id_1','link1'])
    print(ret)
    
    
    
    
    # 正则  re.compile()
    import re
    ret = soup.find_all(name=re.compile('^b'))  # 查找名字以b开头的标签
    
    
    
    
    # bool布尔
    ret = soup.find_all(id=True)  # 查找所有有ID的标签
    
    
    
    
    # 方法
    def has_class_but_no_id(tag):
        return tag.has_attr('class') and not tag.has_attr('id')
    
    # 查找有class属性没有id属性的
    ret = soup.find_all(has_class_but_no_id)
    print(ret)
    

    联合使用

    # 取属性,取文字
        # tag对象['src']  tag对象.attrs.get('src')
        # tag对象.text  string
    
        
        
    # 遍历文档树和搜索文档树可以同时用
    soup.body.find(name='p').b
    soup.body.find(name='p').find(id='link')
    
    
    
    # tag对象与beautifulsoup对象用起来完全一样
    soup = BeautifulSoup(html_doc,'lxml')
    print(type(soup))
    body = soup.body
    print(type(body))
    

    3.拓展

    链式调用

    跟语言没关系jq

    # 链式调用在python中如何实现? 点多少次,其实还是对象本身
    class A:
        # 每个函数返回self,把对象本身返回
        def test(self,name):
            self.name = name
            return self
        def test2(self,age):
            self.age = age
            return self
    a =A()
    x = a.test('小明').test2(18)
    print(x.age)  # 18
    
    # 每个函数返回self,把对象本身返回
    

    bs4 其他用法

    # limit 限制查找的个数
    
    ret = soup.find_all(name='p',limit=1)
    print(ret)      # [<p class="title"><b>The Dormouse's story</b></p>]
    
    # recursive 是否递归查找
    
    ret = soup.find_all(name='p',recursive=False)   # 只找同级的标签
    ret = soup.find_all(name='p',recursive=True)    # 子孙的都找
    print(ret)
    

    3.css选择

    # select 方法中写css选择器
    
    ret = soup.select('.title')
    ret = soup.select('#link1')     # 查找id为link1的标签
    
    # 重点  > 与 空格 的区别  (>选择子元素,空格选择子孙中的)
    
    ret = soup.select('.title>b')   # 查找class是title标签下的子元素b标签
    ret = soup.select('.title b')   # 查找class是title标签下的子元素或子孙中的b元素
    
    
    使用select提取出的元素如果是Tag标签,
    可以使用属性a['herf'] 和名称提取,
    还可以使用.string  .stripped_strings  .strings  .get_text()  获取内容
    

    4.xpath选择(BeautifulSoup4没有xpath选择)

    XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。
    
    XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 XPointer 都构建于 XPath 表达之上。
    
    因此,对 XPath 的理解是很多高级 XML 应用的基础。
    

    代理池的搭建

    # 收费: 稳定
        网站注册,向该网站的api接口发送请求,获取IP
        
        
        
    # 免费:
        自己搭建:flask框架搭建服务,后台用爬虫(requests爬取免费),放入redis
          访问127.0.0.1/get 随机给一个ip代理
        
        
        
    # 网上开源的:
        #1  下载下来,打开
        #2 安装依赖  pip3 install -r requirements.txt
        #3 修改配置文件Config/setting.py
        35行左右,意思是爬取的代理放到redis中,
        DB_TYPE = getenv('db_type', 'redis').upper()
        DB_HOST = getenv('db_host', '127.0.0.1')
        DB_PORT = getenv('db_port', 6379)
        DB_PASSWORD = getenv('db_password', '')
        #4  跑项目 可以在cli目录下通过ProxyPool.py启
        python3 proxyPool.py schedule:爬取代理
        python3 proxyPool.py webserver:启动服务
        #5 测试
        http://127.0.0.1:5010/get/ 发一次,取一个代理ip
    

    验证码的破解

    花钱,从网上的验证码图片,传给它,他就给你识别,(12306的验证码,模拟登陆12306)

    -超级鹰

    -模拟登陆某些网站
    -http://www.chaojiying.com/price.html
      # 注册用户
      # 创建软件
      # 充值
      # 下载demo
      # 修改demo,账号密码该上
      # 运行代码
    

    -云打码

    案例

    爬取汽车之家新闻

    # 爬取汽车之家新闻
    # pip3 install beautifulsoup4
    # pip3 install lxml
    import requests
    
    # 引入
    from bs4 import BeautifulSoup
    
    
    for i in range(1,10):
    
        ret = requests.get('https://www.autohome.com.cn/news/%s/#liststart'%i)
        ret.encoding = 'gbk'
        # print(ret.text)
        # 实例化得到对象(
        # 第一个参数,可以是字符串,或者是文件对象
        # 第二个参数,解析的方式(html.parser    lxml)
        soup = BeautifulSoup(ret.text, 'lxml')
    
        # 以后查找属性,都是操作soup这个对象
        # 查找文档树之查找所有
        # div=soup.find_all(name='div',id='auto-channel-lazyload-article')[0]
        # #查找div下的ul标签
        # ul=div.find_all(name='ul')
        # print(ul)
        # class是一个关键字
        ul = soup.find(name='ul', class_='article')
        # 找到ul下所有的li标签
        li_list = ul.find_all(name='li')
        # 循环列表
        for li in li_list:
            img = li.find(name='img')
            if img:
                # 获取标签的属性两种方式
                # img_ul=img['src']
                img_ul = 'http:' + img.attrs.get('src')
                title = li.find(name='h3').text
                desc = li.find('p').text
                url = 'http:' + li.find(name='a')['href']
                # print(img_ul)
                # print(title)
                # print(desc)
                # print(url)
                #图片保存
                img_name=img_ul.rsplit('/',1)[-1]
                ret2=requests.get(img_ul)
                with open(img_name,'wb') as f:
                    for line in ret2.iter_content():
                        f.write(line)
                print('''
                文章标题:%s
                文章链接:%s
                文章图片地址:%s
                文章摘要:%s
                '''%(title,url,img_ul,desc))
    
    
    #总结:bs4 查找文档树
    # 标签对象=soup.find(name='div',href='',class_='')
    # 标签对象可以继续使用find
    # 获取属性两种方式   标签对象['属性名']   标签对象.attrs.get('属性名')
    # 获取文本  标签对象.text
    
  • 相关阅读:
    优雅的将hbase的数据导入hive表
    大数据技术-spark+hive+hbase研究
    第0001课
    线程池-实际生产使用
    H5学习系列之文件读取API--本文转自http://blog.csdn.net/jackfrued/article/details/8967667
    H5学习系列之Communication API
    H5学习系列之Geolocation API
    H5学习系列之Audio和Video
    H5学习系列之webSocket入门
    百度UEditor基本使用
  • 原文地址:https://www.cnblogs.com/fwzzz/p/12460453.html
Copyright © 2011-2022 走看看