python爬虫笔记

4、urllib库
  模拟浏览器发送请求的库,Python自带
  Python2: urllib urllib2
  Python3: urllib.request urllib.parse

  字符串==》字节类型之间的转化
  encode() 字符串==》字节类型
  如果小括号里面不写参数,默认是utf8
  如果写,就写gbk
  decode() 字节类型==》字符串
  如果不写 默认utf8
  如果写,就写gbk
  urllib.request
    urlopen(url)
    urlretrieve(url,image_path)
    urllib.parse
    quote(url) url编码函数,将中文进行转化为%xxx;注意,发请求的url不能包含中文和特殊字符,所以有特殊字符和中文则需要用此函数编码
    unquite(url) url解密函数,将%xxx转化成相应字符串
    urlencode(url) 将一个字典拼接为query_string,并且实现了编码的功能
  response
    read() 读取相应内容,内容是字节类型
    geturl() 获取请求的url
    getheaders() 获取头部信息,列表里面有元组
    getcode() 获取状态码
    readlines() 按行读取,法规列表,都是字节类型

5、get方式
  构建请求头部信息(这是反爬的第一步)
  a)伪装自己的UA,让服务端认为你是浏览器在上网
  b)构建请求对象 urllib.request.Request(url=url,headers=headers)
  c)ssl._create_default_https_context = ssl._create_unverified_context # 取消ssl验证
6、post方式
  1.【注】表单数据的处理
    urllib.parse.urlencode(form_data).encode()
    fidder抓包,一个本上面有个箭头,代表就是post请求
'    Accept-Encoding': 'gzip, deflate, br', # 此句不需要加
7、ajax
8、URLErrorHTTPError
  这两个类都在urllib.error模块中
  NameError TypeError FileNotFound 异常
  异常处理,结构 try-except
  URLError:
    (1)没有网
    (2)服务器连接失败(域名不存在)
    (3)找不到指定的服务器
  HTTPError:
    是URLError的子类
    【注】两个同时捕获的时候,需要将HTTPError写到上面,HTTPError写在下面
9、Handler处理器、自定义Opener
  a)urlopen() 给个url,发送请求,获取响应
  b)Request() 定制请求头,创建请求对象
10、高级功能:使用代理,cookie
  基本用法:
  a)代理
    1、代理是什么?
    2、生活中的代理:微商、代练
    3、程序中的代理:
      正向代理:代理客户端获取数据
      反向代理:代理服务端提供数据
    4、配置:
      浏览器配置
      代码代理
        handler = urllib.request.ProxyHandler({'http':'116.209.58.148:9999'})
        opener = urllib.request.build_opener(handler)
      后续都使用opener.open方法去发送请求即可
  b)cookie
    1、cookie是什么?
    2、http协议,无状态
    3、登录网站时候的问题,用来记录用户身份的
    模拟登录:

# 创建一个cookiejar对象
cj = http.cookiejar.CookieJar()
# 通过cookiejar创建一个handlder
handler = urllib.request.HTTPCookieProcessor(cj)
# 通过handler 创建一个opner
opener = urllib.request.build_opener(handler)

    再往下所有的操作都是用opener.open方法发送请求,因为这里面带着cookie过去了
11、正则表达式解析:
  a)单字符:
    . : 除换行符以外所有字符
    [] : [aoe] [a-w] 匹配集合中的任意一个字符
    d : 非数字
    w : 数字、字母、下划线、中文
    W : 非w
    s : 所有的空白字符
    S : 非空白
  b)数量修饰:
    * :任意多次 >=0
    + : 至少一次 >=1
    ? : 可有可无 0次或者1次
    {m} : 固定m次
    {m,} : 至少m次
    {m,n} : m-n次
  c)边界:
     B
    $ : 以某某结尾
    ^ : 以某某开头
  d)分组:
    (ab){3}
    (){4} 视为一个整体
    () 子模式组模式 1 2
  e)贪婪模式:
    .*? .+? # 加?取消贪婪
    re.I : 忽略大小写
    re.M : 多行匹配
    re.S : 单行匹配(多行变单行)

    matchsearchfindall
    re.sub(正则表达式,替换内容,字符粗)
12、bs4(BeautifulSoup)
  a)需要将pip源设置为国内源
    Windows:
    (1)打开文件资源管理器
    (2)地址栏上面输入%appdata%
    (3)在这里面 新建一个文件夹pip
    (4)在pip文件夹里面新建一个文件叫做 pip.ini,内容如下即可

[global]
timeout = 6000
index-url = https://mirrors,aliyun.com/pypi/simple/
trusted-host = mirrors.aliyun.com

    Linux:
    (1)cd ~
    (2)mkdir ~/.pip
    (3)vi ~/.pip/pip.conf
    (4)编辑内容,和windows一样
    (2)需要安装:pip install bs4
  b)bs4在使用时候需要一个第三方库lxml(pip install lxml)
  c)简单使用:
    1、说明:选择器
    2、导入:from bs4 import BeautifulSoup
    3、使用方式:可以将一个html文档,转换成指定的对象,然后通过对象的方法或者属性去查找指定的内容
    4、转化本地文件:

soup = BeautifulSoup(open('本地文件'),'lxml')

    5、转化网络文件:

soup = BeautifulSoup('字符串类型/字节类型','lxml')

    6、使用方法:

      1)根据标签名查找
        soup.a 只能找到第一个符合要求的标签
      2)获取属性
        soup.a.attrs 获取所以的属性和值,返回一个字典
        soup.a['title'],soup.a.attrs['title'] 两个等价

      3)获取内容
        soup.a.text:都能获取
        soup.a.string:只能是文本,如果标签里有标签的话,获取None
        soup.a.get_text():都能获取
      4)find(找到的都是第一个符合要求的节点)
        soup.find('a') 找到第一个符合要求的a标签
        soup.find('a',title='qing')
        soup.find('a',class_='aaa') # 注意class是关键字要用class_
        soup.find('div',class_='song').find('p',class_='li') 可以连缀查找
      5)find_all (返回所有符合要求的节点)
        soup.find_all('a','b') # 支持同时查找多标签
        soup.find_all('a',limit=2) # 支持查找数据量
      6)select
        根据选择器选择指定的内容
        常见选择器:标签选择器、类选择器、id选择器、组合选择器、层级选择器、伪类选择器、属性选择器
        select 选择器返回永远是列表,该方法也可以通过普通对象调用
13、xpath
  a)什么是xpath?
    xml是用来存储和传输数据
  b)和html的不同的两点:
    1)html用来显示数据,xml是用来传输数据
    2)html标签是固定的,xml标签是自定义的
  c)xpath用来在xml中查找指定的元素,它是一种路径表达式

    常用的路径表达式:
      // : 从不考虑位置的查找
      ./ : 从当前节点开始往下查找
      @ : 选取属性

  实例:

/bookstore/book 选取根节点bookstore下面所有直接子节点book
//book 选取所有book
bookstore//book 查找bookstore下面所有的book
/bookstore/book[1] bookstore里面的第一个book
/bookstore/book[last()] bookstore里面的最后一个book
/bookstore/book[position()<3] 选取bookstore里面的前两个book
//title[@lang] 选取所有拥有lang属性的tittle
//title[@lang='eng'] 选取所有拥有lang属性值为eng的title

      * :匹配任何元素节点

  d)安装xpath插件
    1、将xpath插件拖动到谷歌浏览器扩展程序中
    2、启动和关闭插件
    3、ctrl + shift + x
  e)属性定位
    //input[@id="wk"]
    //input[@class="bg s_btn"] # 多个class是个整体,不可拆分查找
  f)层级定位
  h)索引定位
    //div[@id="head"]/div/div[2]/a[@class="toindex"]
    【注】索引从1开始
    //div[@id="head"]//a[@class="toindex"]
    【注】双斜杠代表下面所有的a节点,不管位置
  i)逻辑运算
    //input[@class="s_ipt" and @name="wd"]
  j)模糊匹配【】

    1、contains
      //input[contains(@class,"s_i")]
      所有的input,有class属性,并且class中包含s_i
      //input[contains(text(),"爱")]
    2、starts-with
      //input[contains(@class,"s")]
      所有的input,有class属性,并且class中必须以s开头
  k)取文本
    

//div[@id="u1"]/a[5]/text()
//div[@id="u1"]//text() 获取节点里面不带标签的所有内容
string = ret[0].xpath('string(.)') # 直接将内容拼接起来返回
print(string.replace('
','').replace('	','').replace(' ',''))

  m)取属性
    //div[@id="u1"]/a[5]/@href
    代码里使用xpath
    导入库:from lxml import etree
    两种方式使用:将html文档变成一个对象,然后调用对象的方法查找指定的节点
      1、本地文件
        tree = etree.parse(文件名,etree.HTMLParser(encoding="utf-8"))
      2、网络文件
        tree = etree.HTML(网页字符串)
      3、换行问题:
        a)存储的时候显示的 是有效的
        b)在读取过来单独使用的时候换行符生效'
14、图片加载问题
  a)懒加载技术:用到的时候加载
    实现方式:

<img src2="图片路径"> 加载时变为下面格式
<img src="图片路径">

15、jsonpath
  jsonpath:用来解析json数据使用的
  python处理json格式用到的函数
  使用:import json
    json.dumps():将字典或者列表转化为json格式的字符串
    json.loads():将json字符串转化为Python对象
    json.dump():将字典或者列表转化为json格式字符串并且写入到文件中
    json.load():从文件中读取json格式字符串,转换为Python对象
  安装:
    pip install lxml
    pip install jsonpath
  用法:
    jsonpath用一个抽象的名字$来表示最外层对象。
    xpath的表达式:/store/book[1]/title
    jsonpath的表达式:x.store.book[0].title
    或 x['store']['book'][0]['title']

  xpath 和 jsonpath对比:
    / $ 表示跟元素
    . @ 当前元素
    / . 子元素
    // .. 任意位置查找
    * * 通配符
    [] ?() 过滤
    xpath 索引下标从1开始
    jsonpath 索引下标从0开始
16、selenium和PhantomJS
  1、selenium是什么?
    python的第三方库,对外提供接口可以操作你的浏览器,然后让浏览器自动化的操作
  2、使用selenium
    安装:pip install selenium
    操作谷歌浏览器,首先必须有谷歌浏览器的一个驱动
    谷歌驱动下载地址
      http://chromedriver.storage.googleapis.com/index.html
    谷歌驱动和谷歌浏览器版本关系映射表
      https://blog.csdn.net/huilan_same/article/details/51896672
  3、代码操作

from selenium import webdriver
browser = webdriver.Chrome(path)
browser.get()

  4、使用下面方法,找到指定的元素进行操作即可

find_element_by_id 根据id找节点
find_element_by_name 根据name找
find_element_by_xpath 根据xpath查找
find_element_by_tag_name 根据标签名找
find_element_by_class_name 根据class名字查找
find_element_by_css_selector 根据选择器查找
find_element_by_link_text 根据链接内容查找
getsend_keysclick

  5、PhantomJS
    a、是什么?是一款浏览器,无界面浏览器
    b、selenium+phantomjs 就是爬虫终极解决方案
      1、下拉滚动条到底部
      2、豆瓣电影下拉
      3、图片懒加载
      4、获取网页的代码:browser.page_source
17、Headless Chrome
  1、无头谷歌浏览器,无界面谷歌浏览器
  2、因为phantomjs现在都不维护了
  3、mac、linux,版本号59+以上,才支持这种模式
  4、windows,要求版本号的60+以上,才支持这种模式
  5、使用

from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')

18、requests
  安装:pip install requests
  官方文档:
    http://cn.python-requests.org/zh_CN/latest/
  用来做什么?
    和urllib是同一个为位置的,是对urllib的封装,底层是urllib3
  get请求
    定制头部
      data:是一个原生字典
      requests.get(url,headers=headers,params=data)
    响应对象
      r.text 字符串形式查看响应
      r.content 字节类型查看响应
      r.encoding 查看或者设置编码类型
      r.status_code 查看状态码
      r.headers 查看响应头部
      r.url 查看所请求的url

  post请求
    必应翻译
      formdata:是一个原生字典
      r = requests.post(url,headers=headers,data=formdata)
  ajax、get、post
    和上面一样
    代理
      r = requests.get(url=url,headers=headers,params=data,proxies=proxies)
    cookie
      s = requests.Session()
      r = s.get(url=url,headers=headers,params=data,proxies=proxies)
    chinaunix
      登录思路:先get,再post,再get
19、验证码
  a)tesseract简介
    光学识别,只能识别简单的验证码
    代码测试:pip install pytesseract pillow
  b)打码平台
    打码兔、云打码
23、线程回顾
  a、引入
    多任务,多个任务同时进行,多进程,多线程
    多进程:sublime、录屏、vnc服务器
    多线程:word(包括编辑,查看等线程同时执行)
  b、创建线程Thread
    1、面向过程:
      tsing = threading.Thread(target=sing,name='sing',args=(a, ))
      target:线程启动之后要执行的函数
      name:线程的名字
      获取线程名字:threading.current_thread().name
      # 启动线程
      tsing.start()
      # 让主线程等待子线程结束之后再结束
      tsing.join()
      # 这里是主线程
      print('这里是主线程')
    2、面向对象
      定义一个类,继承自threading.Thread,重写一个方法run方法,
      需要主线程名字、传递参数,重写构造方法,在重写构造方法的时候,
      一定要注意手动调用父类的构造方法。
    3、线程同步
      线程之间共享全局变量,很容易发生数据混乱问题,
      这个时候要使用线程锁,抢,谁抢到,谁上锁之后,谁就先用
    4、创建锁
        suo = threading.lock()
      上锁
        suo.acquire()
      释放锁
        suo.release()
    5、队列(queue)
      a)下载线程
        //解析线程,通过队列进行交互
        q = Queue(5)
        q.put('xxx') 如果队满,程序卡在这里等待
        q.put('xxx',False) 如果队满,程序直接报错
        q.put('xxx',True,3) 如果队列满,程序等待3s再报错

      b)获取数据
        print(q.get()) 如果队列为空,程序卡在这里等待
        print(q.get(False)) 如果队列为空,程序直接报错
        print(q.get(True,3)) 如果队列为空,程序等待3s报错

      c)q.empty() 判断队列是否为空
      d)q.full 判断队列是否已满
      e)q.qsize 判断队列长度

24、多线程爬虫
  分析:
    两类线程:下载(3)、解析线程(3)
    内容队列:下载线程往队列中put数据,解析线程从队列get数据
    url队列:下载线程从url队列get数据
    写数据:上锁

原文地址:https://www.cnblogs.com/liugp/p/10562708.html