zoukankan      html  css  js  c++  java
  • 爬虫基础

    HTTPS是以安全为目标的HTTP通道,安全基础是SSL,传输的内容全部是由SSL加密的,某些网站使用HTTPS协议,但仍然会被浏览器提示不安全,是因为有些网站的CA证书不是被CA机构信任的,如果要爬取这样的站点,就要设置忽略证书的选项

    请求头:

    Accept:请求报头域,用于指定客户端可接受那些类型的信息

    Accept-Language:指定客户端可接受的语言类型.

    Accept-Encoding:指定客户端可接受的内容编码

    Host:用于指定请求资源的主机IP和端口号,其内容为请求URL的原始服务器或网关的位置

    Cookie:是网站用于辨别用户进行会话跟踪而存储在用户本地的数据

    Referer:此内容用来标识这个请求是从哪个页面发过来的

    User-Agent:简称UA,是一个特殊的字符串头,可以使服务器识别客户使用的操作系统及版本,浏览器及其版本信息,爬虫需要加上此信息

    Content-Type:也叫互联网媒体类型,或者MIME类型,在HTTP协议消息头中,它用来表示具体请求的媒体类型信息

    响应头:

    Date:标识响应产生的时间

    Last-Modified:指定资源的最后修改时间

    Content-Encoding:指定响应内容的编码

    Server:包含服务器的信息,比如名称,版本号等

    Content-Type:文档类型,指定返回的数据类型是什么

    Set-Cookie:设置Cookies,响应头中的Set-Cookie告诉浏览器需要将此内容放在Cookies中下次请求携带Cookies请求.

    Expires:指定响应的过期时间,可以使代理服务器或浏览器将加载的内容更新到缓存中

    HTML定义了网页的内容和结构,CSS描述了网页的布局,JavaScript定义了网页的行为

    有时候我们在使用urllib或requests抓取网页时,得到的源代码实际和浏览器中看到的不一样,这是因为网页越来越多的采用Ajax,前端模块化工具来构建,整个网页可能都是由JavaScript渲染出来的

    HTTP的无状态是指HTTP协议对事物处理是没有记忆能力的,会话和Cookies用于保持HTTP连接状态的技术.会话在服务器保存用户的会话信息,Cookies在客户端保持信息,服务器通过识别Cookies鉴定那个用户

    文件上传:

    import requests

    files={'file':open('favicon.ico','rb')}

    r = requests.post('http:wwwcsb.com',files=files)

    会话维持:

    在requests中,如果直接利用get()和post()等方法的确可以做到模拟网页的请求,但是这实际上相当于两个不同的会话,类似于使用两个浏览器打开了不同的页面

    利用Session,可以做到模拟同一个会话而不担心Cookies的问题,通常用于模拟登陆成功之后再进行下一步的操作

    SSL证书验证:

    当发送HTTP请求时,他会检查SSL证书,通过使用verify参数控制是否检查此证书,默认值为True,

    import requests

    response=requests.get('https://www.12306.cn',verify=False)

    这时请求成功会发现警告,建议我们给他指定证书,我们可以通过设置忽略警告的方式来屏蔽这个警告

    from requests.packages import urllib3

    urllib3.disable_warning()....

    代理设置:

    设置代理使用proxies参数

    proxies={"http":"http://10.10.1.10:3128","https":"http://10.10.1.10:1080"}

    requests.get("https://www.taobao.com",proxies=proxies)

    若代理需要使用HTTP Basic Auth,可以使用类似http://user:password@host:port这样的语法设置代理

    proxies={"http":"http://user:password@10.10.1.10:3128/"}

    除了基本的HTTP代理外,requests还支持SOCKS协议的代理

    需要安装socks库: pip3 install 'requests[socks]'

    proxies={'http:'socks5://user:password@host:port','https':'socks5://user:password@host:port'}

    超时设置:

    设置超时时间需要使用timeout参数,

    r = requests.get("https://www.taobao.com",timeout=1)

    将超时时间设置为1秒.若1秒内没有响应就将抛出异常,实际上,请求分为两个阶段,连接与读取,timeout作用连接和读取的时间总和永久登台设置为None,默认为None

    身份认证

    访问网站遇到认证页面可以使用requests自带的身份认证功能

    from requests.auth import HTTPBasicAuth

    r = requests.get('http://loaclhost:5000',auth=HTTPBasicAuth('username','password'))

    requests提供了更简单的写法直接传入一个元组,就会默认使用HTTPBasicAuth这个类来认证

    r = requests.get('http://localhost:5000',auth=('username','password'))

    Prepared Request

    将请求表示为数据结构,各个参数可以通过Request对象表示

    from requests import Request,Sesson

    url = 'http://httpin.org/post'

    data={'name':'germey'}

    hedaders={'User-Agent':'Mozilla;Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/53.0.2785.116 Safari/537.36'}

    s =Session()

    req = Request('POST',url,data=data,headers=headers)

    preppd=s.prepare_request(req)

    r = s.send(prepped)   ------r.text

    这里引入了Request,然后用url,data和headers参数构造了一个Request对象,这是需要再调用Session的prepare_request()方法将其转换为一个Prepared Request对象,然后再调用send()方法发送即可,可以达到同样的post请求,

    有了Request对象,就可以将请求当做独立的对象来看待,这样在进行队列调度时十分方便,后面将用它来构造一个Request队列

     正则表达式:

    match()

    第一个参数传入正则表达式,第二个参数传入了要匹配的字符串

    result = re.match('^sd+',content)

    group方法可以输出匹配的内容,span()方法可以输出在原字符串的范围

    贪婪匹配匹配尽可能多的字符非贪婪匹配匹配尽可能少的字符

    re.I:使匹配对大小写不感兴趣

    re.S:使.匹配包括换行在内的所有字符

    可以使用转义匹配匹配非正常字符串

    match()方法从头开始匹配,不符合就匹配失败

    search()

    返回第一个匹配成功的结果

    findall()

    查找所有符合的结果,返回的是字符串

     sub():

    修改文本,cotent = re.sub('d+','',content),

    第一个参数为匹配的正则表达式,第二个参数为替换成的字符串,第三个参数为原字符串

    compile():

    可以将正则表达式编译成正则表达式对象,以便在后面的匹配中复用

    pattern = re.compile('d+:d+')

    result = re.sub(pattern,'',content)

    注意不要在Elements中直接查看源码,那里的源码可能经过JavaSCript操作而与原始请求不同,需要从Network选项卡部分查看原始请求得到的源码

    xpath解析器

    / 从当前节点选取直接子节点

    //从当前节点选取子孙节点

    .选取当前节点

    ..选取当前节点的父节点 parent::*同样是父节点

    @选取属性

    result = html.xpath('//li[@class='sb']')进行属性匹配

    text()方法用于获取文本

    /text()获取文本,//text()获取子孙节点所有文本

    属性获取:result=html.xpaht('//li/a/@href')返回值为列表类型

    ancestor::*可以获取所有祖先节点

    attribute::*可以获取所有属性值

    child::* 可以获取所有直接子节点

    descendant::*获取所有子孙节点

    following::*获取所有当前节点之后的节点,

    following-sibling::*获取当前节点之后的所有同级节点

    Beautiful Soup

    Beautiful Soup自动将输入文档转换为Unicode编码,输出文档转换为UTF-8编码

    基本用法:

    soup = BeautifulSoup(html,'lxml')

    soup.title.string

    其中html是一个HTML字符串,第二个参数为解析器类型,

    prettify()可以将要解析的字符串以标准的缩进格式输出,soup.title.string获取title节点的文本内容***且只能获取到第一个节点

    提取节点信息

    string属性用于获取文本的值,

    name属性获取节点的名称

    attrs可以获取所有属性,返回值为字典,

    attrs['name']用于获取name属性

    contents属性得到的结果是直接子节点的列表

    child属性返回的结果是生成器类型,

    descendants属性得到所有子孙节点返回结果是生成器

    parent获取某个元素的父节点

    parents得到所有该节点的祖先节点,返回结果是生成器类型

    next_sibling和previous_sibling分别获取节点的下一个和上一个兄弟元素

    next_siblings和previous_siblings分别返回后面的和前面的所有兄弟节点

    Pyquery

    from pyquery import PyQuery as pq

    doc=pq(html)

    print(doc('li'))

    也可以使用doc = pq(url='https://www.baidu.com')

    这样PyQuery对象会首先请求这个URL,然后用得到的HTML内容完成初始化

    也可以使用doc=pq(filename='sb.html')将读取本地的文件内容,然后以字符串的形式传递给PyQuery类来初始化

    Ajax数据爬取

    渲染网页:比如通过document.getElementById('sb').innerHTML=xmlhttp.responseText,就可以更换数据

    Ajax其实有其特殊的请求类型,他叫做xhr,就是Ajax请求,

    模拟Ajax请求需要在请求头中加入参数'X-Requestes-With':'XMLHttpRequest'

    若爬取一个网站,返回的html文本并没有页面中渲染的数据,需要查看ajax请求,查看返回值的data数据是否包含,

    动态渲染页面爬取:

    我们可以直接使用模拟浏览器运行的方式来实现可见即可爬

    Selenium:

    访问页面:

    from selenium import webdriver

    browser=webdriver.Chrome()

    browser.get('https://www.taobao.com')

    print(broweser.page_source)

    节点交互:

    Selenium可以驱动浏览器来执行一些操作,也就是说可以让浏览器模拟执行一些动作,常见的有:

    输入文字时:send_keys(),清空文字时:clear(),点击按钮时用click()方法:示例如下:

    input= browser.find_element_by_id('sb')

    input.send_keys('sb')

    input.clear()

    button=browser.find_element_by_class_name('btn')

    button.click()

    切换到具体框架switch_to.frame('name')

    执行JavaScript:

    可以通过使用execute_script()方法实现

    browser.execute_script('window.scrollTo(0,document.body.scrollHeight)')

    browser.execute_script('alert('To Bottom!')')

    获取属性值:(标签为logo):logo.get_attribute('class')参数为属性名,得到的就是属性值

    获取文本值:logo.text

    id获取节点id,location获取该节点在页面中的相对位置,tag_name属性可以获取标签名称,size属性可以获取节点的大小,也就是宽高

    延时等待

    隐士等待:当使用隐士等待执行测试时,如果Selenium没有在DOM中找到节点,将继续等待,超出设定时间后,则抛出找不到节点的异常,

    browser = webdriver.Chrome()

    browser.implicitly_wait(10)

    显示等待

    指定要查找的节点,制定一个最长等待时间,若果规定时间内加载出来了这个节点,就返回,若没有则抛出异常示例如下:

    from selenium.webdriver.common.by import By

    from selenium.webdriver.support.ui import WebDriverWait

    from selenium.webdriver.support import expected_conditions as EC

    browser = webdriver.Chrome()

    browser.get('http://www.taobao.com/')

    wait=WebDriverWait(browser,10)

    input=wait.until(EC.presence_of_element_located((By.ID,'sb')))

    button=wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'.btn-search')))

    前进和后退

    使用back()方法后退,使用forward()方法前进

    Cookies:

    使用Selenium,可以方便的对Cookies进行操作,例如获取删除,添加Cookies等,示例如下:

    browser=webdriver.Chrome()

    browser.get('http://www.zhihu.com/explore')

    browser.get_cookies()

    browser.add_cookie({'name':'sb'})

    browser.delete_all_cookies()

    选项卡管理:

    browser = webdriver.Chrome()

    browser.get('http://www.baidu.com')

    browser.execute_script('window.open()')

    print(browser.window_handles)

    browser.witch_to_window(browser.window_handles[1])

    图形验证码的识别:

    识别最简单的图形验证码:

    import tesserocr

    from PIL import Image

    image = Image.open('code.jpg')

    result = tesserocr.image_to_text(image)

    print(result)

    在这里我们新建了一个Image对象,调用了tesserocr的image_to_text()方法,传入该Image对象,即可完成识别,

    另外还有一种更简单的方法,这个方法可以直接将图片文件转为字符串

    print(tesserocr.file_to_text('image.jpg'))但是识别效果不如上一种

    在遇到验证码内有多余线条干扰了图片的识别,对于这种情况需要做额外的处理,如转灰度,二值化等操作

    可以利用Image对象的convert()方法参数传入L,即可将图像转化为灰度图像,代码如下,

    image = image.convert('L')

    image.show()

    传入1即可将图片先转为灰度图像,然后再指定二值化阈值,代码如下:

    image= image.convert('1')

    image.show()

    还可以指定二值化的阈值,上面采用的方法默认是阈值127,我们不能直接转化原图,要将原图先转为灰度图像,然后在指定二值化阈值,代码如下:

    image= image.convert('L')

    threshold = 80

    table =[]

    for i in range(256):

      if i <threshold:

        table.append(0)

      else:

        table.append(1)

    image = image.point(table,'1')

    image.show()

    在这里变量threshold代表二值化阈值,阈值设定为80,

    这时重新识别验证码:result = terrerocr.image_to_text(image)

    针对一些有干扰的图片,我们做一些灰度和二值化处理,会提高图片的识别率

    代理池:

    requests代理设置:我们只需要传入proxies参数即可

    proxy = '127.0.0.1:9743'

    proxies={'http':'http://'+proxy,'https':'https://'+proxy',}

    try:

      response = requests.get('http://httpbin.org/get',proxies=proxies)

      print(response.text)

    如果代理需要认证,需要在代理的前面加上用户名密码即可

    proxy = 'username:password@127.0.0.1:9743'

    如果需要使用SOCKS5代理,则可以使用如下方式来设置:

    proxies={'http':'socks5://'+proxy,'https':'socks5://'+proxy}

    在这里需要额外安装一个模块,这个模块是requests[socks]

    Selenium设置代理

    示例如下

    from selenium import webdriver

    proxy = '127.0.0.1:9743'

    chrome_options = webdriver.ChromeOptions()

    chrome_options.add_argument('--proxy-server=http://'+proxy)

    browser=webdriver.Chrome(chrome_options=chrome_options)

    认证代理实在麻烦不要用

    Pyspider

    如果要快速实现一个页面的抓取,推荐使用pyspider,开发更加便捷,如快速抓取某个普通新闻网站的新闻内容,如果要应对反爬程度很强,超大规模的抓取,推荐使用Scrapy,如抓取IP,封账号,高频验证的网站的大规模数据采集

  • 相关阅读:
    HTML标签语义化对照表
    C#自定义分页控件3.0
    并发小工具
    C#方法
    我所知道的一个简单类
    等快递无聊旋转字符串
    委托
    撒列实现关键字过滤,速度可快了
    垃圾回收代
    递归再一次让哥震惊了
  • 原文地址:https://www.cnblogs.com/suncunxu/p/10758987.html
Copyright © 2011-2022 走看看