自己整理的一些爬虫知识. 备忘!

很多文字内容都是通过自己的理解写的,如果有理解不到位的地方,还望指正.

selenium部分是通过看资料整理的,很多东西不是很懂,有待进一步学习.

一. requests 模块
    基于urllib的模块 , 用法比urllib简单
    1. requests的方法
        requests.get(url,params=None)
          用get方法获取请求  得到响应
          参数:
            url   要请求的地址
            params  请求地址要传的参数  以字典形式给出
              比如: dic = {'name':"Tom",'age':18}
                requests.get(url,params=data)
                传参也可以直接在url中拼接参数(仅限get请求)  如: 'http://www.baidu.com?name=tom&age=18/'
        其他请求方式:
        requests.post() --- post  put delete .....
    2. requests.get(url)  得到的响应的  属性 及 处理
        response = requests.get(url)
        得到响应对象的一些属性
        html = response.text  
            --- 该url的html字符串
               有些网站可能是以json格式返回,用txt属性得到的仍然是 字符串(字典形式的字符串)
               这里可以用json.loads(html)方法处理, --- 就可以得到 字典格式的数据
               更方便的方法 直接用 response.json() 这个方法获得的就是 字典格式的数据
               这个方法的实质就是,在函数内部,对 response.txt 获得的内容 进行了 json.loads() 处理
        response.status_code  -- 状态码   200+ 300+ 400+ 500+
        response.cookies  -- 得到cookie 对象  <class 'requests.cookies.RequestsCookieJar'>
        response.headers -- 响应头  返回一个字典
        response.url -- 返回网址url
        response.history -- 访问历史  返回一个列表  没有 历史就返回空列表
        ....
        ...
        获取二进制信息
        response.content
        可以读取图片 视频等信息 用于保存
        比如:
          response = requests.get(url)
          with open('tu.jpg','wb') as f:
              f.write(response.content)
        
        requests的高级操作:
          上传文件:
            files = {'file':open('文件路径','rb')}
            response = requests.post(url,files=files)
            post方式上传文件
            
          模拟会话:

            requests.get('http://httpbin.org/cookies/set/number/123456789')
            res = requests.get('http://httpbin.org/cookies')
            res.cookies
            以上操作获取不到cookies. 
            因为 两次get请求相当于模拟了两个不同的浏览器请求,
            第一个浏览器设置了cookies,但在另一个浏览器再次请求 肯定获取不到cookies

            # 先创建一个session对象, 然后用session对象访问时 , 设置cookies,
            # 再次用这个session对象访问时,相当于在同一浏览器发起的访问,这样就可以获取cookies
            s = requests.Session()
            s.get('http://httpbin.org/cookies/set/number/123456789')
            res = s.get('http://httpbin.org/cookies')
            以上操作可以获取到cookies,相当于在同一浏览器对url进行了访问

            因此,用session对象对url进行post登录访问,访问成功后,已经保存了cookies
            再次使用该对象对url进行get访问 可以成功访问登录后的主页
            相当于在一个浏览器操作,实现了模拟会话

          证书验证:
            requests.get(url)  # https...的url
            用这个方法访问https协议的url网站,会首先验证 网站证书
            如果网站证书不是正版授权的,会报出SSLError错误   --- 比如 https://12306.cn
            避免这种报错:
              只需要请求时加一个参数:  verify=是否进行证书验证
               requests.get('https://12306.cn',verify=False) 
               不会产生报错,会提示一个警告信息

               补充:  不显示警告信息
               ---- from requests.packages import urllib3
                    urllib3.disable_warnings()  不显示警告信息
                ---  还可以手动指定证书  本地证书
                    requests.get('https://www.12306',cert=('/path/server.crt','/path/key'))
          代理设置:
            设置代理的网址ip+port:
            proxies = {
                'https':'https://127.0.0.1:9999',
                'http':'http://127.0.0.1:9999',
            }
            直接把参数传进去,就可以通过代理访问网址
            res = requests.get('https://www.taobao.com',proxies=proxies)
            ---
              如果代理是私密代理,用用户名和密码时,
              proxies = {
                  'https':'http://user:password@ip:port'
              }
            ***
              有些代理不是http/https代理  可能是 socks5 代理
              这里需要安装模块  pip3 install 'requests[socks]'
              不需要导入 直接用requests使用
              proxies = {
                  'http':'socks5://ip:port'
                  'https':'socks5://ip:port'
              }
              下面同上 直接传入proxies参数即可

          超时设置:
            传入参数  timeout = 1  单位 s
          认证设置:
            有些网站在你访问的时候, 直接就会让你输入用户名和密码,如果没有就会返回401
            两种方式处理:
              一:
                from requests.auth import HTTPBasicAuth
                res = requests.get(url,auth=HTTPBasicAuth('user','123'))
              二:
              直接传参  传一个字典
                res = requests.get(url,auth=('user','123'))

          异常处理:
            from requests.exceptions import ReadTimeout,ConnectionError,RequestException
二.
    正则表达式
    import re 
    result = re.match(pattern,content,匹配模式) # 返回一个对象
    result.group()  # 不加任何参数  可获得完整的匹配内容
    result.group(1)  #  获取正则里第一个子组匹配到的内容
    match匹配  必须从第一个字符匹配,如果第一个字符不匹配,就直接返回None

    re.search  扫描整个字符串并返回第一个成功的匹配,只返回一个
    re.search(pattern,content)

    这里pattern一般用一个正则匹配对象,
    通过 pattern = re.complie('正则',匹配模式) 获得
    这个方法  将正则字符串编译成正则表达式对象,以便于复用该匹配模式

    匹配模式  re.S -- 让点 . 可以匹配到换行符\n

    re.findall(pattern,content)
    搜索字符串,以 列表形式 返回全部能匹配到的 子串(就是正则表达式中括号中的内容)

    re.sub(pattern,str,content)  
    把用正则pattern 在content中匹配到的内容,用str替换掉,最后返回替换后的字符串
    re.sub('***(**)**',r'\1 123')  这里的  \1  代表的是 正则中 括号里匹配到的内容
    --  '** 123'  这是最终要替换进去的内容

    BeautifulSoup
      install beautifulsoup4
      from bs4 import BeautifulSoup
      soup = BeautifulSoup(html,'lxml')
      参数: html -- 网页源码字符串    
            lxml -- 解析器 (其他解析器  'html.parser'  /   'xml'   /   'html5lib')
      返回一个对象,
      这个对象的方法/属性
      soup.prettify()   把html网页字符串 格式化, 使字符串更美观,便于观察
      soup.标签名.string  获得该标签对应的 内容

      标签选择器
      soup.标签名   --比如 soup.title
      返回 一个标签对象   -- 比如 <title>*******</title>
      如果有多个该标签,只会返回第一个匹配到的

      获取名称
      soup.title.name  --- 返回: title

      获取属性:
      soup.p.attrs['属性名']  -- 得到属性值
      soup.p['属性名'] -- 同上

      获取内容:
      soup.p.string  -- 得到 匹配到的 p 标签里的内容

      嵌套选择:
      获取到标签对象之后 还可以继续获取该标签内的 子标签的内容
      soup.head.title.string

      字节点 和  子孙节点
      soup.标签名.contents  -- 返回一个列表,列表中每个元素是该标签的所有子标签的字符串
      soup.标签名.children  
        -- 返回一个迭代器对象, 可用循环取到内容
        补充: for i,child in enumerate(soup.p.children):  枚举遍历
            返回的 i 是索引下标值 
             child 是子节点的内容(包括文本节点)
      soup.标签名.descendants
            返回所有的子孙节点 (换行符 和 每个标签中的文本内容 也会被单独输出)
            返回的是一个生成器,可循环遍历
      
      父节点 和 祖先节点
        soup.a.parent  首先匹配到第一个a标签,然后再匹配到该a节点的父节点
        soup.a.parents  匹配到第一个a元素的所有祖先节点  返回的是一个可迭代对象  可遍历得到结果
      兄弟节点
        soup.a.next_siblings  获取后面的所有的兄弟节点
        soup.a.previous_siblings 获取前面的所有的兄弟节点
      
      提供的一些API  标准选择器
        find_all()
        根据标签名,属性,内容查找
        把匹配到的结果,以列表的形式返回,
        列表中的每个元素是 标签对象 (与soup.标签名  返回的类型是一样的,因此,这个对象可以使用标签对象的所有方法)

        soup.find_all('标签名') -- 根据标签名查找
        soup.find_all(attrs={'属性名':'属性值',...})  -- 根据属性 查找
        soup.find_all(id='属性值') -- 查找id为该属性值的对象
            由于 class 是python中的关键字 ,根据class属性查的时候  用 class_='属性值' 查找
        soup.find_all(text='Foo')  返回['Foo','Foo']    返回的仅仅是内容 的列表

        find()
        返回匹配结果的第一个元素对象,不是一个列表
        查找不存在的标签,则会返回一个None

      CSS选择器
        通过select() 直接传入CSS选择器即可完成选择
        类选择器 -- 前面加点 .
        元素选择器 -- 直接写元素名
        id选择器 -- 前面加 # 号
        选择器以一个字符串的方式给出 选择器之间用空格隔开 : soup.select(".class #id p")
        多个选择器之间可以使层层嵌套的关系
        
        可能匹配到多个标签,,因此返回的是一个列表,列表中的元素是 便签对象
        由于是列表所以可以用 [] 索引取下标的 方法得到每个元素
        获取属性:
             获得 标签对象 之后,通过标签对象获取属性
             标签对象['属性名']   or   标签对象.attrs['属性名']
        获取文本:
            标签对象.get_text()
        
        总结:
            1. 建议使用 lxml 解析库  必要时使用 html.parser
            2. 建议使用 find()  find_all()
            3. 建议使用CSS选择器
            4. 记住常用的获取属性和文本值的方法

    PyQuery
        与jquery 无缝衔接, API接口 完全相同
        from pyquery import PyQuery as pq
        1) 字符串初始化
            html=''
            doc = pq(html)
            -> pq对象
            doc('标签名')
          URL初始化
            doc = pq(url='http://www.baidu.com')
            doc('标签名')
          文件初始化
            doc = pq(filename='路径文件名')
            doc('标签名')
        2) 基本CSS选择器
        
          doc('#id  .class li') 选择器之间空格隔开 不一定是父子关系  
        3) 查找元素
          items= doc('选择器') - > pyquery 对象
          查找子元素
            items.find('标签名')  -> 返回的仍然是pyquery对象,仍然可以继续使用find方法
                find(查找子孙元素中 所有符合条件的)
            items.children('选择器')
                查找子元素中 符合条件的元素
          父元素
            items.parent() -> 返回的仍然是pyquery对象
                返回整个父元素的内容
            items.parents() -> 
                返回所有的祖先节点元素
                parents('选择器') -> 在所有祖先元素中再次进行筛选
          兄弟元素
            items = doc('选择器1 选择器2选择器3')
              可以看到选择器2和3之间没有空格,表示的是并列关系,
              空格隔开表示的是嵌套关系
            items.siblings()
              返回所有的兄弟元素,这些兄弟元素也可以继续通过选择器进行筛选
          遍历:
            doc('选择器').items()  
                ->可得到一个生成器,从中可以获取用选择器匹配到的元素
        4) 获取属性/文本
            a = doc('选择器')
            a.attr('属性名') 方法 ---  a.attr.href 属性
            两种方式 都可以获得属性值
            a.text() --- 获取文本内容(如果有子节点,子节点中的文本也会被获取)

            a.html() 获取标签里的html内容 -- 类似 jquery

        5) DOM操作  - 动态修改节点内容
            各种api
            a = doc('选择器')
            a.removeClass('类名字')  在类属性中删除该类
            a.addClass('类名字')   在该元素中 添加类

            属性操作:
              a.attr('name','link')  -- 添加/修改 name属性的值
              添加/修改其他属性也一样
              a.css('font-size','14px') 
              -- 添加/设置css,也就是style属性
            
            a.find('选择器').remove()  把找到的元素从a这个pyquery对象中删除
        6) 伪类选择器
            doc('li:first-child')
            doc('li:last-child')
            doc('li:nth-child(2)')
            doc('li:gt(2)')
            doc('li:nth-child(2n)')  # 第偶数个
            doc('li:contains(second)')
    Selenium
        自动化测试工具,支持多种浏览器,
        爬虫中主要解决JavaScript渲染的问题

      基本用法:
        1) 声明一个浏览器对象
            引入一个 webdriver 包
            from selenium import webdriver

            browser = webdriver.Chrome()  创建一个 weddriver 对象,
           
            browser.page_source  获得网页内容

            单个元素  find_element
            多个元素  find_elements
        2) 通过webdriver对象 获取单个元素 
            
            browser.find_element_by_id('id值')  # 获取该元素,返回是一个WebElement对象
            browser.find_element_by_css_selector('#q') 通过css选择器获取元素
            browser.find_element_by_xpath('xpath路径')  通过xpath路径获取元素
            ....by_name()   通过元素名
            ...by_link_text()
            ...by_partial_link_text()
            ...by_tag_name()
            ...by_class_name()
          通用的查找方式:
            from selenium.webdriver.common.by import By
            browser.find_element(By.ID,'q')
            通用的查找方式, 
                 By.ID -- 表示通过ID属性方式查找,还有其他的
                 By.CSS_SELECTOR  选择器
        3) 查找多个元素
            与单个元素的区别 
            find_elements   复数形式
            返回的是一个列表,列表中每个元素是 WebElement对象
        4) 元素交互操作
            对获取的元素调用交互的方法
            input = browser.find_element_by_id('一个输入框的ID')
            input.send_keys('关键字') # 相当于在文本框中输入iphone
            input.clear()  # 清空文本框
            然后获取搜索按钮 button
            button.click()  # 相当于点击了按钮
        5) 交互动作 
            拖拽,双击等动作
            导入一个模块
            from selenium.webdriver import ActionChains
            broeser = webdriver.Chrome()
            先获取两个元素: 要移动的元素source  目标元素target
            再获取 ActionChains 对象
            actions = ActionChains(browser)
            actions.drag_and_drop(source,target)
            actions.perform() # 执行以上动作
            其他的 交互动作 可查官方文档API
        6) 执行 JavaScript
            browser.execute_script('window.scrollTo(0,document.body.scrollHeight)')
            把下拉框拉到最下面
        
        7) 获取元素信息
            获取属性
            元素对象.get_attribute('class')  获取class属性
        
            元素对象.text   文本值
            元素对象.id   id    
            标签对象.location   元素在网页中的位置{'y':7,'x':774}
            元素对象.tag_name  标签名
            元素对象.size  元素的大小 ('height':32,'width':66)

        8) 等待
            为防止因为网页加载慢,而获取不到元素的问题,通常需要等待
            隐式等待
            当使用了隐式等待执行的时候,如果webdriver没有在DOM中找到元素,
            将继续等待,超出设定时间后,将抛出异常.
            换句话说,当查找元素或者元素没有立即出现的时候,隐式等待将等待一段时间,再继续查找DOM,默认时间为0
            browser.implicitly_wait(10)
            browser.get(url)
            ...

            显式等待 -- 常用
            from selenium.weddriver.common.by import By
            from selenium.webdriver.support.ui import WebDriverWait
            from selenium.webdriver.support import expected_conditions as EC

            browser.get(url)
            wait = WebDriverWait(browser,10)  # 创建一个wait对象,关联browser,最长等待时间是10s
            input = wait.until(EC.presence_of_element_located((By.ID,'q')))
            最长时间之内 满足wait.until中的那条件,则正常获取到元素,
            超过最长时间还未获取到,则抛出异常

            判断条件 -- 查文档

        4) 前进后退
            browser.back()
            browser.forward()
            browser.close()
        5) cookies
            coo = browser.get_cookies()  # 获取cookies
            browser.add_cookie({一系列键值对}) # 把字典里的cookie添加进去
            browser.delete_all_cookies()
        6) 选项卡管理
            新打开一个选项卡
            通过执行一个 js 的方式打开 

            browser.execute_script('window.open')  # 通过JS打开一个新窗口选项卡
            print(browser.window_handles) # 查看所有的选项卡  返回选项卡代号  列表形式
            browser.switch_to_window(browser.window_handles[1]) #切换到选项卡
            browser.get(url1)
            time.sleep(1)
            browser.switch_to_window(browser.window_handles[0]) # 切换到其他选项卡
            browser.get(url2)
        
        7) 异常处理

            详细内容查看官方文档
            try:
                browser.get('http://www.baidu.com')
            except TimeoutException:
                print('Time Out')
            
            try:
                broeser.find_element_by_id('hello')
            except NoSuchElementException:
                print('No Element')
            finally:
                browser.close()
                    
          
        


                    


        

猜你喜欢

转载自blog.csdn.net/rs_hao/article/details/82701594