知识整理术语表

自整理体系、按字母排序和分条显示讲的内容是完全一样的,只是呈现的方式不同。只看自整理体系即可。

前言

  • 断舍离这个概念其实是日本提出的一种家居整理术,概述一下就是不再接受没用的物品,扔掉家里没用的物品,然后到达一个看起来很有逼格的境界。运用到我们这里面就是,要对信息进行筛选性的处理。
    • 要收敛一下我们的关注边界。我们要收集的不是好的东西,而是对我们有用的东西。这就涉及一个“T”字形的知识结构,是将注意力集中到一个方向上,先通过深度挖掘,在进行拓展的一种知识体系。这种体系是比较适合我们大部分人的,因为很多情况下我们的精力只足以支撑我们用一个点做开端。
    • 评估一下我们的信息渠道。我们现在有很多渠道来获取新的信息,比如看书看电影,微信微博知乎豆瓣。可以说每个渠道都可以为我们提供一些有价值的东西,但是我们需要评估一下这些渠道的性价比,比如微博基本上已经可以定义为一个纯娱乐性的APP了。还有一个就是知乎,知乎这个网站可是说内容质量还是可以的,但是知识过于碎片化,会给人造成刷知乎是在学习的错觉,实际上并没有什么实质的提升,同时也造就了一大批键盘侠。综合来看呢,还是读书适应的人群比较多,最起码你每看完一本书都会对某一件事的某一方面得到系统的认知。
  • 迅速对一个行当有一个了解的方法还有一个是找这个行当里的牛人聊一聊,他们可是集日月之精华的活的数据库。
  • 找、存、理
    • 归类,去重,留精,加可供搜索的标签等等——能够显著提升信息搜索效率。
      • 最初你需要一定的动力去尝试开始做这件事情,而一旦兴趣产生,再加以坚持, 这就已经成为习惯,和你密不可分了。
  • 尽管有些人再不乐意,碎片化的信息输入和提取方式,就是未来的主流趋势。我们必须学会适应这一点,而不是只是吐槽和抱怨。事实上,碎片化的学习自然有其存在即合理的地方。知识的体系化固然有其价值,但是我们在日常工作中,需要的是解决一个个具体的问题。如果遇到每一个问题都要为之建一座体系的高楼,那这辈子其他事情都不用干了。以有涯随无涯,殆已。
  • 不断完善自己的资源搜索库。
    • 查GDP、M2等等数据都可以进统计局、银监会等政府网站。

爬虫知识结构

1. 爬虫基础

爬虫工程师的前景、爬虫工作原理、网络爬虫工作原理详解

  • 从结构化(HTML)和非结构化(流数据)的数据中获取信息
    什么是网络爬虫、如何分析静态网站、如何开发一个完整的爬虫
    动态网站分析和爬取的两种思路
    如何从HTML页面中提取出有效的数据,以及对如何将数据合理地存储成各类文件以实现持久化。
    一个爬虫所应该具有的全部功能组件以及编码实现
    分布式爬虫,功能和基础爬虫一致,在单机爬虫的基础上进行分布式改进,帮助大家从根本上了解分布式爬虫,消除分布式爬虫的神秘感。
    、动态网站的抓取、协议分析
    爬虫的设计及实现流程
    熟悉抓包分析请求并模拟
    正则表达式、Path、css选择器、Xpath
    熟练使用selenium、lxml、bs4,对xml、html的文本进行抓取解析清洗
    完整地介绍了爬虫程序的每一个知识模块
    网络爬虫
    组成
    什么是
    初识
    爬虫(网页)抓取原理及技术
    基本议题和框架
    遇到爬虫问题的时候的各种解决方法

    1.1. 为什么要学

    为什么、好处、重要性、作用、意义、优势、不足、历史、现状、趋势、大背景。
    不断解决遇到的疑惑。
    科技如何给大家带来实效
    数据的存储对公司有什么影响
    如何存储数据⇒高效利用 方便对接其他部门和业务
    如何使用淘宝网上所有绿色产品(如空气净化器)的销量数据来做潜在市场评估
    如何一直高效率、持续不断地从日新月异的网站中获取信息
    互联网的运作和结构
    爬虫程序是收集信息的基础。
  • 学习网络爬虫的原因
  • 网络爬虫带来的价值
  • 飞速发展的大数据时代。
    市场营销:丰富的数据信息让我们有能力更好地了解消费者、顾客和竞争对手。电商网站评论收集可以及时知悉顾客对于产品的看法,通过微博数据收集可以及时洞察潜在消费者的购买意向和需求。
    企业管理人员:通过对手网站信息收集可以及时知晓对手的实时动态,真正做到运筹帷幄之中,决胜千里之外。
    打开数据信息收集大门的钥匙。
    有志于在数据分析方面有所突破。
    使用Python编写网络爬虫程序获取互联网上的大数据是当前的热门专题。
    技术创新驱动变革的潮流。
    数据量爆发式增长的互联网时代。
    大数据分析的火热。
    大数据成为业界与学术界最火热的话题之一。
    数据已经成为每个公司极为重要的资产。
    互联网大量的公开数据为个人和公司提供了以往想象不到的可以获取的数据量。
    网络爬虫技术是大数据分析的第一环。有助于获取有用的公开数据集。
    理解了信息的获取、存储和整理,才有可能系统地收集和应用不同源头和千变万化的网站信息。
    DT的核心是从信息的源头去理解和分析,以做出能打动对方的行动决策方案。
    由谷歌搜索到现在的大数据时代,爬虫技术的重要性和广泛性一直很突出。
    爬取目标网站的资料、分析和建立应用。 获取数据自动、实时、及时、省时。
    电商市场的重要性日益凸显。了解对手的产品特点、价格以及销量情况,及时跟进产品开发进度和营销策略,从而知己知彼,赢得竞争。过去,两个痛点——无法自动化和无法实时获取。产品研发部门会手动访问一个个电商产品页面,人工复制并粘贴到Excel表格中,制作竞品分析报告。但是这种重复性的手动工作不仅浪费宝贵的时间,一不留神复制少了一个数字还会导致数据错误;对手产品的销量则是由某一家咨询公司提供报告,每周一次,但是报告缺乏实时性,难以针对快速多变的市场及时调整价格和营销策略。
    学会一项新的技术
    第一方企业(也就是拥有这些数据的企业)做出更好的决策
    第三方企业也可从中受益
    数据共享
    Python:热门的开源软件(这意味着有人源源不断地开发更新且更强大的包给你用)
    Python:简单、简洁、易学、有效、可扩展性的计算机语言。 最受欢迎的程序语言之一。 强大而丰富的库。
    C语言:底层,学习成本大。

    1.2. 类型

    有哪些
  • 聚焦
  • 增量式

    1.3. 技能

    技能总览
    实现原理
    实现技术
    可以做什么
    开发技术
  • 三大库
  • 中间件(Middleware)、中间件的变化、中间件延伸
  • 提升速度、迅速技巧、倍速
  • 抓包与中间人
  • 定向爬取技术
    部署与计划运行
    攻防战
    Android原生App
    基于逆向分析小程序的
    常见搜索算法
    JSONAPl和AJAX

    1.4. 应用场景

    一些附加值更高的“事”,如人工智能、统计建模等。
    机器学习和统计算法分析
    在营销领域可以帮助企业做好4P(Product:产品创新,Place:智能选址,Price:动态价格,Promotion:数据驱动的营销活动)
    在金融领域,数据驱动的征信等应用会带来越来越大的价值。
    公开数据的应用价值
    所有网络数据
    社交媒体的每一条发帖。社交媒体在用户生态圈的自我交互下产生大量文本、图片和视频数据。
    团购网站的价格及点评。电商商产品的描述、价格
    招聘网站的招聘信息
    搜索引擎从数据库中提取搜索结果

    1.5. 流程图

    具体步骤及各步骤之间的关系。
    获【取】网页、解【析】网页(提取数据)、【存】储数据、整【理】。
  • 获取网页:给一个网址发送请求,该网址会返回整个网页的数据。类似于在浏览器中键入网址并按回车键,然后可以看到网站的整个页面。
  • 解析网页:从整个网页的数据中提取想要的数据。类似于在浏览器中看到网站的整个页面,但是你想找的是产品的价格,价格就是你想要的数据。
  • 存储数据:把数据存储下来。
    三个流程的技术实现:
  • 获取网页
    获取网页的基础技术:request、urllib和selenium(模拟浏览器)。
    获取网页的进阶技术:多进程多线程抓取、登录抓取、突破IP封禁和服务器抓取。
    并发编程(多线程(池)、多进程(池)、futures)
    异步编程(asyncio)
  • 解析网页
    解析网页的基础技术:re正则表达式、BeautifulSoup和lxml。
    解析网页的进阶技术:解决中文乱码。
  • 存储数据
    存储数据的基础技术:存入txt文件和存入csv文件。
    存储数据的进阶技术:存入MySQL数据库和存入MongoDB数据库。
    发起请求——通过HTTP库向⽬目标站点发起请求,即发送一个Request,请求可以包含额外的headers等信息,等待服务器器响应。
    获取响应内容 ——如果服务器器能正常响应,会得到一个Response,Response的内容便便是所要获取的⻚页⾯面内容,类型可能有HTML,Json字符串串,二进制数据(如图⽚片视频)等类型。
    解析内容 ——得到的内容可能是HTML,可以⽤用正则表达式、⽹网⻚页解析库进⾏解析。可能是Json,可以直接转为Json对象解析,可能是二进制数据,可以做保存或者进一步的处理理。
    保存数据 ——保存形式多样,可以存为文本,也可以保存⾄至数据库,或者保存特定格式的文件。

    2. 获取网页

    2.1. 法律和道德、注意事项

    网络爬虫是否合法
    法律问题
    道德协议
    在充满爬虫的世界里做一个好公民
    用户爬虫的那些事儿
    是否合法
    基本议题
    成规模的爬虫一般都会使用集群,一般的小网站服务器规模可能不如爬虫集群的规模大。所以很多时候我们最好对要爬的网站限制一下频率。否则这些爬虫就相当于DoS攻击集群了!一般的网站都会有robots.txt可以参考。
    爬虫有哪些潜在的法律纠纷、公司的爬虫合不合法 。
    建立共利的互联网环境,不能把爬虫作为窃取数据的工具。
    爬虫必须在合情、合法、合理的情况下获取和应用。
    尊重数据供应者的知识产权和正常运作才能产生长久共利的环境。
    保障对方平台的正常运作是每个程序员都应当做到的
    法律:
    互联网世界已经通过自身的协议建立起一定的道德规范(Robots协议)。该协议是国际互联网界通行的道德规范,虽然没有写入法律,但是每一个爬虫都应该遵守这项协议。
    法律部分还在建立和完善中。
    如果抓取的数据属于个人使用或科研范畴,基本不存在问题。当你爬取网站数据时,无论是否仅供个人使用,都应该遵守Robots协议。
    而如果数据属于商业盈利范畴,就要就事而论,有可能属于违法行为,也有可能不违法。
    大部分网站不欢迎使用程序进行登录,因为需要登录才能查看的数据不属于公开数据。最好不要使用此程序获取非公开数据或批量注册,若出现了问题,可能需负法律责任。
    建议使用API。
    Robots协议
    Robots协议(爬虫协议)的全称是“网络爬虫排除标准”(Robots Exclusion Protocol),网站通过Robots协议告诉搜索引擎哪些页面可以抓取,哪些页面不能抓取。
    https://www.taobao.com/robots.txt。
    Allow开头的URL是允许robot访问的。例如,Allow:/article允许百度爬虫引擎访问/article.htm、/article/12345.com等。
    Disallow不允许百度爬虫引擎访问的。例如,Disallow:/product/不允许百度爬虫引擎访问/product/12345.com等。
    Disallow:/禁止百度爬虫访问除了Allow规定页面外的其他所有页面。
    taobao的robots.txt对不同的搜索引擎所允许爬行范围不同。/product项对应淘宝内部的产品信息。当在搜索框中搜索“淘宝iphone7”的时候,Google可搜到淘宝中的产品,而百度不能。
    过于快速或者频密的网络爬虫都会对服务器产生巨大的压力。→调集资源限制爬虫,保护用户的流量和减少有价值数据的流失。
    反爬方维权:网站封锁你IP,法律行动。
    将请求的速度限定在一个合理的范围之内。
    每年的三月份会迎来一个爬虫高峰期。因为有大量的大学生五月份交论文,在写论文的时候会选择爬取数据,也就是3月份爬取数据,4月份分析数据,5月份交论文。
    2007年,爱帮网利用垂直搜索技术获取了大众点评网上的商户简介和消费者点评,并且直接大量使用,大众点评网多次要求爱帮网停止使用这些内容,而爱帮网以自己是使用垂直搜索获得的数据为由,拒绝停止抓取大众点评网上的内容,并且质疑大众点评网对这些内容所享有的著作权。为此,双方开打了两场官司。2011年1月,北京海淀法院做出判决:爱帮网侵犯大众点评网著作权成立,应当停止侵权并赔偿大众点评网经济损失和诉讼必要支出。
    2013年10月,百度诉360违反Robots协议。百度方面认为,360违反了Robots协议,擅自抓取、复制百度网站内容并生成快照向用户提供。2014年8月7日,北京市第一中级人民法院做出一审判决,法院认为被告奇虎360的行为违反了《反不正当竞争法》相关规定,应赔偿原告百度公司70万元。
    虽然说大众点评上的点评数据、百度知道的问答由用户创建而非企业,但是搭建平台需要投入运营、技术和人力成本,所以平台拥有对数据的所有权、使用权和分发权。【网站的知识产权】
    以上两起败诉告诉我们,在爬取网站的时候需要限制自己的爬虫,遵守Robots协议和约束网络爬虫程序的速度。如果违反了这些规定,很可能会吃官司,并且败诉的概率相当高。

    2.2. 网页特点

    静态网页:纯粹HTML格式的网页通常被称为静态网页。其在浏览器中展示的内容都在HTML源代码中。早期的网站一般都是由静态网页制作的。容易爬。
    动态网页:使用JavaScript、AJAX等技术展现的网页。很多内容并不会出现在HTML源代码中。主流网站一般都会使用。不容易爬。
    如何获取网页
  • 如何使用API获取数据【API是官方提供的数据获取通道,因此数据的获取是没有争议的。如果一个网站提供API获取数据,那么最好使用API获取,既简单又方便。】
  • 如何安装Requests库?如何使用Requests库获取响应内容(整个网页的源代码)
  • 基于深度和广度的爬虫。取深度加大到第3层,看看最短在多少秒之内能够完成前3层的爬虫。【深度优先的递归爬虫,广度优先的多线程爬虫】
  • 静态网页是啥
  • 动态网页是啥
  • 动态网页的实例
  • 什么是动态抓取?两种动态网页抓取技术获取动态网页的数据
    • 通过浏览器审查元素解析真实网页地址【AJAX动态解析地址】
    • 使用selenium模拟浏览器的方法

      2.2.1. 获取动态网页的真实地址

      Chrome浏览器的检查(审查元素)功能:浏览器右键⇒检查⇒Network⇒XHR或JS选项
      Network:显示浏览器从网页服务器中得到的所有文件。一般这些数据以json文件格式获取。
      在Network选项卡下,找到真正的评论文件。
      单击Preview标签即可查看数据。可以按 ctrl+F 进行查找。顶部search也可以。
      Elements会出现相应的code所在的地方。

      2.3. 抓包分析工具

      Fiddler
      什么是
      与爬虫的关系
      基本原理与基本界面
      捕获会话功能
      QuickExec命令行
      断点功能
      会话查找功能
      的其他功能

      2.4. API

      网站API分析
      使用
      秘钥获取
      数据获取

      2.5. 常用库

      Urllib库
  • 什么是
  • 快速使用
  • URLError异常处理
    requests
    BeautifulSoup4
    CSVFeedSpider
    强大的Requests库能够让你轻易地发送HTTP请求,这个库功能完善,而且操作非常简单

    2.6. requests

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    import requests
    r = requests.get('http://www.santostang.com/')
    # ========【r的方法】========
    # r response响应对象,存储了服务器响应的内容,以从中获取需要的信息
    # r.encoding 服务器内容使用的文本编码。
    # r.status_code 响应状态码。检测请求是否正确响应。
    # r.text 字符串方式的响应体。会自动根据响应头部的字符编码进行解码。
    # r.content 字节方式的响应体。会自动解码gzip和deflate编码的响应数据。gzip文件用这个。
    # r.json() Requests中内置的JSON解码器。
    # r.url r对应的请求的页面网址
    # ========【requests.get的参数设置】========
    ## URL参数、请求头、发送POST请求、设置超时
    ## ----------【params】:dict ----------
    ### get传递url参数。http://httpbin.org/get?key1=value1&key2=value2
    key_dict = {'key1': 'value1', 'key2': 'value2'}
    r = requests.get('http://httpbin.org/get', params=key_dict)
    ## ----------【headers】:dict ----------
    ### 有的网站不带请求头会返回错误的数据。带请求头使程序更像人的手动行为
    headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36',
    'Host': 'www.santostang.com'
    }
    r = requests.get('http://www.santostang.com/', headers=headers)
    ## ----------【data】: dict ----------
    ### 用于提交表单。data在发出请求的时候会自动编码为表单形式。
    key_dict = {'key1': 'value1', 'key2': 'value2'}
    r = requests.post('http://httpbin.org/post', data=key_dict)
    ## ----------【timeout】: 单位为秒 ----------
    ### 如果服务器在timeout秒内没有应答,就返回异常。一般会把这个值设置为20秒。
    link = "http://www.santostang.com/"
    r = requests.get(link, timeout= 0.001)
    ## 返回的异常为:
    ## ConnectTimeout: HTTPConnectionPool(host='www.santostang.com', port=80): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<requests.packages.urllib3.connection.HTTPConnection object at 0x00000000077806D8>, 'Connection to www.santostang.com timed out. (connect timeout=0.001)'))
    ## 异常值的意思是,时间限制在0.001秒内,连接到地址为www.santostang.com的时间已到。
    # https://github.com/Santostang/PythonScraping/blob/master/第一版/Cha 3 -静态网页抓取/Cha 3 -静态网页抓取.ipynb

    2.7. urllib

    2.7.1. 核心代码

    urllib2.urlopen(<>).read()
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    # 核心代码
    import urllib
    import urllib2
    ## 请求1
    response = urllib2.urlopen(<>)
    ## 请求2
    values = {}
    values['username'] = "XX"
    values['password'] = "XXXX"
    # 此三行等价于 values = {"username":"XX","password":"XXXX"}
    data = urllib.urlencode(values)
    request = urllib2.Request(url,data)
    response = urllib2.urlopen(request)
    # 读取
    text = response.read()

    2.7.2. eg.1 直接GET

    1
    2
    3
    import urllib2
    response = urllib2.urlopen("http://www.baidu.com")
    print response.read()

    2.7.3. eg.2 带参数的GET

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import urllib
    import urllib2

    values={}
    values['username'] = "XX"
    values['password']="XXXX"
    data = urllib.urlencode(values)
    url = "http://passport.csdn.net/account/login"
    geturl = url + "?"+data
    request = urllib2.Request(geturl)
    response = urllib2.urlopen(request)
    print response.read()

    2.7.4. eg.3 POST

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import urllib
    import urllib2

    values = {"username":"XX","password":"XXXX"}
    data = urllib.urlencode(values)
    url = "<post网址>"
    request = urllib2.Request(url,data)
    response = urllib2.urlopen(request)
    print response.read()

    2.7.5. 等效写法

    1
    2
    3
    4
    # response = urllib2.urlopen("http://www.baidu.com")
    request = urllib2.Request("http://www.baidu.com")
    response = urllib2.urlopen(request)
    # request对象,推荐写法,通过构建一个request,服务器响应请求得到应答,逻辑上清晰明确

    2.7.6. 类方法解析

    1
    2
    3
    4
    5
    urlopen(url, data, timeout)
    url,必选。
    data,可选。默认为空None。访问URL时要传送的数据。
    timeout,可选。默认为 socket._GLOBAL_DEFAULT_TIMEOUT。设置超时时间。
    urlopen方法之后,返回一个response对象。

    2.7.7. response

    1
    2
    print response
    <addinfourl at 139728495260376 whose fp = <socket._fileobject object at 0x7f1513fb3ad0>

    2.7.8. 设置代理

    proxy_handler = urllib2.ProxyHandler({"http" : 'http://some-proxy.com:8080'})
    设置代理 ProxyHandler 参数为http字典
    opener = urllib2.build_opener(proxy_handler)
    打开代理 build_opener 参数为ProxyHandler
    urllib2.install_opener(opener)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    import urllib2
    enable_proxy = True
    proxy_handler = urllib2.ProxyHandler({"http" : 'http://some-proxy.com:8080'})
    proxy_handler_null = urllib2.ProxyHandler({})
    if enable_proxy:
    opener = urllib2.build_opener(proxy_handler)
    else:
    opener = urllib2.build_opener(proxy_handler_null)
    urllib2.install_opener(opener)
    urllib2 默认会使用环境变量 http_proxy 来设置 HTTP Proxy。
    有些网站会检测某一时间段内某个IP 的访问次数,如果访问次数过多,网站会禁止访问。
    这时可以设置一些代理服务器来工作,每隔一段时间换一个代理。

    2.7.9. 设置headers

    request = urllib2.Request(url, data, headers)
    1
    2
    3
    4
    5
    headers = { 'User-Agent' : 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'  , 
    'Referer':'http://www.zhihu.com/articles' }
    # 有些防盗链,服务器会识别headers中的referer是不是它自己,如果不是,服务器就不响应
    user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
    headers = { 'User-Agent' : user_agent }

    2.8. Selenium

    Selenium模拟浏览器
    Selenium和PhantomJS
    Selenium和PhantomJS的配合使用
    Selenium选择元素的方法有很多。
    xpath和css_selector是比较好的方法,一方面比较清晰,另一方面相对其他方法定位元素比较准确。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    查找单个元素:
    find_element_by_class_name:class选择
    <p class="content">Site content goes here.</p>⇒driver.find_element_by_class_name('content')。
    find_element_by_css_selector:class选择
    <div class='bdy-inner'>test</div>⇒driver.find_element_by_css_selector ('div.bdy-inner')。
    find_element_by_id:id选择
    <div id='bdy-inner'>test</div>⇒driver.find_element_by_id('bdy-inner')。
    find_element_by_link_text:链接地址选择
    <a href="continue.html">Continue</a>⇒driver.find_element_by_link_text('Continue')。
    find_element_by_name:name选择
    如<input name="username"type="text" />⇒driver.find_element_by_name('username')。
    find_element_by_partial_link_text:链接的部分地址选择
    <a href="continue.html">Continue</a>⇒driver.find_element_by_partial_link_text('Conti')。
    find_element_by_tag_name:名称选择
    <h1>Welcome</h1>⇒driver.find_element_by_tag_name('h1')。
    find_element_by_xpath:通过xpath选择
    <form id="loginForm"> ⇒driver.find_element_by_xpath("//form[@id='loginForm']")。
    查找多个元素时,[element]后加上s:
    find_elements_by_class_name
    find_elements_by_css_selector
    find_elements_by_link_text
    find_elements_by_name
    find_elements_by_partial_link_text
    find_elements_by_tag_name
    find_elements_by_xpath
    除了Selenium的click操作元素方法,常见的操作元素方法:
    ● Clear清除元素的内容。
    ● send_keys模拟按键输入。
    ● Click单击元素。
    ● Submit提交表单。
    comment = driver.find_element_by_css_selector(‘div.bdy-inner’)
    content = comment.find_element_by_tag_name(‘p’)
    Selenium的高级操作:
    1
    2
    3
    4
    5
    6
    7
    fp = webdriver.FirefoxProfile()
    # 1. 限制CSS的页面
    fp.set_preference("permissions.default.stylesheet",2)
    # 2. 限制图片的显示。极大地提高网络爬虫的效率。图片文件相对于文字、CSS、JavaScript等文件都比较大,加载需要较长时间。
    fp.set_preference("permissions.default.image",2)
    # 3. 控制JavaScript的运行。大多数网页都会利用JavaScript异步加载很多内容,如果这些内容不是需要的,其加载会浪费时间。
    fp.set_preference("javascript.enabled", False)
    全部限制对于加载速度的提升效果最好。如果能够限制,那么最好限制多种加载,这样的效果最好。
    具体的加载速度提升还得看相应的网页,若网页的图片比较多,则限制图片的加载肯定效果很好。
    参考链接:selenium
    Selenium官方文档:http://selenium-python.readthedocs.io/index.html。
    Selenium要在整个网页加载出来后才开始爬取内容,速度往往较慢。
    Selenium可以实现的功能:
    操作元素对浏览器中的网页进行各种操作,包括登录。
    模拟鼠标单击、双击、拖拽
    获得网页中各个元素的大小
    模拟键盘
    浏览器渲染引擎。直接用浏览器在显示网页时解析HTML、应用CSS样式并执行JavaScript的语句。Selenium使用浏览器渲染,数据已经渲染到了HTML代码中。用chrome定位标签即可。
    用脚本控制浏览器操作。Python的Selenium库模拟浏览器完成抓取。
    Selenium:用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,浏览器自动按照脚本代码做出单击、输入、打开、验证等操作,就像真正的用户在操作一样。
    用Selenium控制浏览器加载的内容,可加快Selenium的爬取速度。此类常用的方法有:
    (1)控制CSS的加载。
    (2)控制图片文件的显示。
    (3)控制JavaScript的运行。
    (1)控制CSS。因为抓取过程中仅仅抓取页面的内容,CSS样式文件是用来控制页面的外观和元素放置位置的,对内容并没有影响,所以我们可以限制网页加载CSS,从而减少抓取时间。
    支持多个浏览器的调用:IE(7、8、9、10、11)、Firefox、Safari、Google Chrome、Opera等。最常用的是Firefox。

    2.9. 爬虫与反爬

    ==术语==
    网络爬虫:使用任何技术手段自动批量获取网站信息的一种方式。
    反爬虫: 使用任何技术手段阻止批量获取网站信息的一种方式。
    出书的人和经验丰富的实战工程师区别大概就在于此。
    与爬虫的斗争
    问题
    为什么会被
    方式有哪些、技术突破、如何“反反爬虫”
    反爬虫(反爬虫会增加获取数据的难度。限制封锁。)与反反爬(初级的反反爬虫方法只能初步帮助我们顺利地完成爬虫程序)
  • 如登录后才可以查看【处理登录表单:使用Python登录表单。Selenium爬取网站】
  • 登录时设置验证码【处理验证码:通过程序识别图片中的文字(人工或者OCR)】
  • 如何保存cookies
  • 中文编码问题。为啥可以解决编码问题。为什么、怎么回事
    1
    2
    3
    4
    import sys
    sys.getdefaultencoding
    sys.getdefaultencoding()
    s.encoding('utf-8')
  • IP封锁与更换。【多服务器或Tor爬虫。如何让爬虫程序运行在“云”上,也能够让你随意改变自己的IP地址,进而走出爬虫被封IP的困境。】
  • 如何解决Python中文乱码的问题【什么是字符编码,Python的字符编码是什么】
    参考链接
    就像攻击武器与防御武器一样,双方总是在不断升级。爬虫和反爬是典型的攻防双方的互相升级。但这种升级不像军事,军事是无尽头的,但是爬虫和反爬是有尽头的。

    2.9.1. 爬虫的尽头

    就是浏览器,一旦使用浏览器,程序完全可以模拟真实用户发出请求,
    消耗资源,因为需要新开一个进程,解析DOM,运行客户端JavaScript代码。(chrome的node api在github开源仅仅两天,就拿到8k个star)

    2.9.2. 反爬的尽头

    就是像Google这种超级厉害的验证码,毕竟验证码的根本目的就是识别人类和机器的。

    2.9.3. 网站为什么要“反爬虫”

    第一,网络爬虫浪费网站的流量,也就是浪费钱。爬虫对于一个网站来说并不算是真正用户的流量,而且往往能够不知疲倦地爬取网站,更有甚者,使用分布式的多台机器爬虫,造成网站浏览量增高,浪费网站流量。
    第二,数据是每家公司非常宝贵的资源。在大数据时代,数据的价值越来越突出,很多公司都把它作为自己的战略资源。由于数据都是公开在互联网上的,如果竞争对手能够轻易获取数据,并使用这些数据采取针对性的策略,长此以往,就会导致公司竞争力的下降。
    因此,有实力的大公司便开始利用技术进行反爬虫,如淘宝、京东、携程等。反爬虫是指使用任何技术手段阻止别人批量获取自己网站信息的一种方式。
    再次特地声明,大家在获取数据时一定要有节制、有节操地爬虫。本书中的爬虫也仅用于学习、研究用途,请不要用于非法用途。任何由此引发的法律纠纷请自行负责。

    2.9.4. 爬虫与反爬一览

    反爬|应对
  • -|–
    频率限制|随机sleep
    登陆限制|加上cookie
    header|header池
    JS|js反爬
    验证码|机器学习
    ip限制|代理池和高匿代理等好用的东西
    内容反爬|OCR
  • 反爬技术与反爬问题、网络异常
  • 负责爬虫技术攻坚,丰富爬虫反爬手段、反爬策略的设计及优化,快速解决
  • 设计爬虫策略和防屏蔽规则(常见的反爬手段及其应对措施=熟知当前各类反爬手段,对反爬机制有研究可破解(有能力解决复杂的反爬限制),有应对这些反爬手段的实际经验)
  • 登录爬取问题和验证码问题 解决办法和分析实例
    • JavaScript反爬
    • 验证码识别技术、复杂图片验证码、滑动块识验码、账号限制、ip限制
    • 优化爬虫路由调度策略
    • 对网站的cookie时效性处理有经验
  • 当在PC网页端爬取遇到困难时,爬取方式可以向手机网页端转变。

    2.9.5. 常见的反爬措施

    2.9.5.1. 浏览器伪装技术

    什么是
    准备工作
    Headers属性
    登录
    验证码
    表单交互
    需要登录的爬虫
    注册、登录及创建项目

    2.9.5.2. Cookie的使用

    2.9.5.3. 访问频率

    很好理解,如果访问太频繁网站可能针对你的ip封锁一段时间,这和防DDoS的原理一样。对于爬虫来说,碰到这样的限制一下任务的频率就可以了,可以尽量让爬虫想人类一样访问网页(比如随机sleep一段时间,如果每隔3s访问一次网站很显然不是正常人的行为)。

    2.9.5.4. 登录限制

    也比较常见。不过公开信息的网站一般不会有这个限制,这样让用户也麻烦了。其实反爬措施都或多或少的影响真实用户,反爬越严格,误杀用户的可能性也越高。对爬虫来说,登录同样可以通过模拟登录的方式解决,加个cookie就行了(话又说回来,网络的原理很重要)。

    2.9.5.5. 通过Header封杀

    一般浏览器访问网站会有header,比如Safari或者Chrome等等,还有操作系统信息。如果使用程序访问并不会有这样的header。破解也很简单,访问的时候加上header就行。

    2.9.5.6. JavaScript脚本动态获取网站数据

    有一些网站(尤其是单页面网站)的内容并不是通过服务器直接返回的,而是服务器只返回一个客户端JavaScript程序,然后JavaScript获取内容。更高级的是,JavaScript在本地计算一个token,然后拿这个token来进行AJAX获取内容。而本地的JavaScript又是经过代码混淆和加密的,这样我们做爬虫的通过看源代码几乎不可能模拟出来这个请求(主要是token不可能破解),但是我们可以从另一个角度:headless的浏览器,也就是我们直接运行这个客户端程序,这可以100%地模拟真实用户!

    2.9.5.7. 验证码

    这几乎是终极武器了,验证码是专门用来区分人和计算机的手段。对于反爬方来说,这种方式对真实用户和搜索引擎(其实可以通过记录搜索引擎爬虫的ip来区别对待,可以解决)的危害比较大,相信读者都有输入验证码的痛苦经历。但这种方法也并不是无敌的!通过现在很火的机器学习可以轻松的识别大部分的验证码!Google的reCAPTCHA是一种非常高级的验证码,但是听过通过模拟浏览器也是可以破解的。有的网站需要验证码验证拿到一个token,token长得很像一个时间戳,本地自己生成一个时间戳发现也是能用的!于是就这样绕过了验证码。

    2.9.5.8. ip限制

    网站可能将识别的ip永久封杀,这种方式需要的人力比较大,而且误伤用户的代价也很高。但是破解办法却非常简单。目前代理池几乎是搞爬虫的标配了,甚至还有很多高匿代理等好用的东西。所以这基本上只能杀杀小爬虫。

    2.9.5.9. 服务器采集

    代理服务器的设置
    为什么使用服务器采集
    使用动态IP拨号服务器
    使用Tor代理服务器

    2.9.5.10. 网站内容反爬

    有一些网站将网站内容用只有人类可以接收的形式来呈现(其实反爬就是区别对待人类和机器嘛)。比如将内容用图片的形式显示。但是近几年来人类和机器的差别越来越小,图片可以用OCR准确率非常高地去识别。
    网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动的抓取万维网信息的程序或者脚本。
    爬虫,即网络爬虫,大家可以理解为在网络上爬行的一直蜘蛛,互联网就比作一张大网,而爬虫便是在这张网上爬来爬去的蜘蛛咯,如果它遇到资源,那么它就会抓取下来。想抓取什么?这个由你来控制它咯。
    比如它在抓取一个网页,在这个网中他发现了一条道路,其实就是指向网页的超链接,那么它就可以爬到另一张网上来获取数据。这样,整个连在一起的大网对这之蜘蛛来说触手可及,分分钟爬下来不是事儿。
    用户看到的网页实质是由 HTML 代码构成的,爬虫爬来的便是这些内容,通过分析和过滤这些 HTML 代码,实现对图片、文字等资源的获取。
    爬虫爬取数据时必须要有一个目标的URL才可以获取数据,因此,它是爬虫获取数据的基本依据,准确理解它的含义对爬虫学习有很大帮助。
    怎样扒网页呢?其实就是根据URL来获取它的网页信息,虽然我们在浏览器中看到的是一幅幅优美的画面,但是其实是由浏览器解释才呈现出来的,实质它是一段HTML代码,加 JS、CSS,如果把网页比作一个人,那么HTML便是他的骨架,JS便是他的肌肉,CSS便是它的衣服。所以最重要的部分是存在于HTML中的,下面我们就写个例子来扒一个网页下来。

    2.10. 编码

    什么是字符编码
    Python的字符编码
  • 文本、数字、bit、字节:计算机只能处理数字,文本转换为数字才能处理,
  • 字节:计算机中8个bit作为一个字节,一个字节能表示的最大数字就是255
  • ASCII: 计算机是美国人发明的,所以一个字节就可以标识所有单个字符,ASCII(一个字节)编码就成为美国人的标准编码
  • GB2312: 中文不止255个汉字,ASCII处理中文明显不够,所以中国制定了GB2312编码,用两个字节表示一个汉字。GB2312将ASCII也包含进去了。
  • Unicode:同理,日文,韩文,越来越多的国家为了解决这个问题就都发展了一套编码,标准越来越多,如果出现多种语言混合显示就一定会出现乱码
    • 于是unicode出现了,它将所有语言包含进去了。
  • “utf-8:可变长的编码。英文:1字节,汉字3字节,特别生僻的变成4-6字节。
    比较:
  • 如果内容全是英文,unicode编码比ASCII编码需要多一倍的存储空间,传输也会变慢。
  • 传输大量的英文,utf8作用就很明显。
    示例:
  • ASCII和unicode编码:
    • 字母A:ASCII编码十进制是65,二进制 0100 0001,unicode:00000000 0100 0001(编码只需要在二进制前面补0)
    • 汉字”中” 已近超出ASCII编码的范围,用unicode编码是20013二进制是01001110 00101101
      解决:
  • 读取文件,进行操作时转换为unicode编码进行处理
  • 保存文件时,转换为utf-8编码。以便于传输
  • 读文件的库会转换为unicode
    默认:
  • python2 默认编码格式为ASCII,
  • Python3 默认编码为 utf-8
    ython2 默认编码格式为 ASCII,Python3 默认编码为 utf-8

    2.11. 爬虫进阶

    怎么处理图片验证码
    反爬破解策略
    消息队列
    任务调度
    代理的使用
  • 用户代理池
  • IP代理池
  • 同时使用用户代理池与IP代理池的方法

    2.12. 异常处理

    为什么我抓到的和浏览器看到的不一样?怎样解决JavaScript渲染的问题
    分析Ajax请求、Selenium/WebDriver、PyV8、Ghost.py 、Splash

    3. 数据解析、清洗和组织

    直接处理、正则表达式、XPath、Json解析、BeautifulSoup、PyQuery
    难度:正则表达式>BeautifulSoup、lxml(可能在寻找正则表达式上耗费时间、BeautifulSoup的find方法很容易学)
    速度:BeautifulSoup≈lxml(BeautifulSoup已经支持lxml解析,因此速度和lxml差不多)
    XMLFeedSpider
    BeautifulSoup
    lxml
    JSON
    高性能HTML内容解析
    解析真实地址抓取
    解析数据
    如何解析网页上的数据。3种方法各有千秋,各自的优缺点
  • 解析JSON数据
  • BeautifulSoup解析网页
  • 正则表达式
  • BeautifulSoup(find方法)
  • XPath、lxml

BeautifulSoup
Urllib中使用XPath表达式
PhantomJS 、浏览器伪装
超时设置

3.1. bs4

使用BeautifulSoup解析网页
BeautifulSoup是一个工具箱。通过【解析文档】来提取数据。

  • 可以从HTML或XML文件中提取数据。
  • 可以提供一些简单的、Python式的函数用来处理导航、搜索、修改分析树等。
    简单,不需要多少代码就可以写出一个完整的应用程序。非常强大。
    支持Python标准库中的HTML解析器,还支持一些第三方的解析器。
    BeautifulSoup 4主要特性、适合做什么、怎样使用
    使用BeautifulSoup获取博客标题
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import requests
    from bs4 import BeautifulSoup
    link = "http://www.santostang.com/"
    headers = {'User-Agent' : 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}
    r = requests.get(link, headers= headers)
    soup = BeautifulSoup(r.text,"html.parser") # 将网页响应体的字符串转化为soup对象
    # <h1>元素,class为' post-title',提取<a>元素中的文字,strip()的功能是把字符串左右的空格去掉。find只是用来找到第一条结果。
    first_title = soup.find("h1", class_="post-title").a.text.strip()
    print ("第一篇文章的标题是:", first_title)
    title_list = soup.find_all("h1", class_="post-title")
    for i in range(len(title_list)):
    title = title_list[i].a.text.strip()
    print ('第 %s 篇文章的标题是:%s' %(i+1, title))
    找所有结果,用find_all。find_all返回列表。
    BeautifulSoup的其他功能
    soup.prettify() 代码美化
    首先,需要把:
    1
    soup = BeautifulSoup(html, "html.parser")
    代码转化成BeautifulSoup对象。
    BeautifulSoup对象是一个复杂的【树】形结构,它的每一个【节点】都是一个【Python对象】。
    提取对象的3种方法:

    遍历文档树
    搜索文档树
    CSS选择器
    1.遍历文档树
    先爬树干,然后小树干,最后树枝。

    1
    2
    3
    4
    5
    6
    soup.header.h3:获取取<h3>标签。如结果为:<h3 id="name">大数据@唐松Santos</h3>)。
    soup.header.div.contents:列出某个标签的所有子节点。只能获取第一代子标签。
    soup.header.div.contents[1]:索引为1的子标签。
    soup.header.div.children:获得所有子标签。只能获取第一代子标签。
    soup.header.div.descendants:获得所有子子孙孙标签
    soup.header.div.a.parent:获得父节点的内容:
    遍历文档树的方法其实使用得比较少。
    2.搜索文档树
    最常用的是搜索文档树。
    最常用的是find()和find_all()。
    find()和find_all()方法还可以和re正则结合起来使用
    1
    2
    3
    4
    5
    for tag in soup.find_all(re.compile("^h")):  # 找出所有以h开头的标签,这表示<header>和<h3>的标签都会被找到
    print(tag.name)
    # 输出的结果是:
    # header
    # h3
    如果传入正则表达式作为参数,Beautiful Soup就会通过正则表达式的match()来匹配内容。
  1. CSS选择器
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    通过tag标签逐层查找:soup.select("header h3")⇒得到的结果是:[<h3 id="name">大数据@唐松Santos</h3>]
    通过某个tag标签下的直接子标签遍历,:
    soup.select("header > h3") ⇒[<h3 id="name">大数据@唐松Santos</h3>]
    soup.select("div > a") ⇒ <div>下所有的< a>标签
    [<a href="http://www.santostang.com/feed/" rel="nofollow" target="_blank"title="RSS"><i aria-hidden="true" class="fa fa-rss"></i></a>, <a href="http://weibo.com/santostang" rel="nofollow" target="_blank" title="Weibo"><i aria-hidden="true" class="fa fa-weibo"></i></a>, …]
    soup.select('a[href^="http://www.santostang.com/"]'):找所有链接以http://www.santostang.com/开始的<a>标签
    得到的结果是:
    [<a href="http://www.santostang.com/feed/" rel="nofollow" target="_blank"title="RSS"><i aria-hidden="true" class="fa fa-rss"></i></a>,
    <a href="http://www.santostang.com/">首页</a>,
    <a href="http://www.santostang.com/about-me/">关于我</a>,
    <a href="http://www.santostang.com/post-search/">文章搜索</a>,
    <a href="http://www.santostang.com/wp-login.php">登录</a>]
  2. 3 使用lxml解析网页
    一些比较流行的解析库
    Xpath语法(如lxml),同样是效率比较高的解析方法。lxml使用C语言编写,解析速度比不使用lxml解析器的BeautifulSoup快一些。
  3. 3.2 使用lxml获取博客标题
    使用lxml提取网页源代码数据的3种方法
    XPath选择器
    CSS选择器
    BeautifulSoup的find()方法
    和BeautifulSoup相比,lxml还多了一种XPath选择器方法。
    XPath是一门在XML文档中查找信息的语言。
    XPath使用路径表达式来选取XML文档中的节点或节点集,也可以用在HTML获取数据中。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import requests
    from lxml import etree
    link = "http://www.santostang.com/"
    headers = {'User-Agent' : 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}
    r = requests.get(link, headers= headers)
    html = etree.HTML(r.text) # 解析为lxml的格式
    title_list = html.xpath('//h1[@class="post-title"]/a/text()') # 用XPath读取里面的内容
    print (title_list)
    //:无论在文档中什么位置
    //h1:所有<h1>元素
    //h1[@class="post-title"]:<h1>中class为"post-title"的元素
    /a表示选取<h1>子元素的<a>元素
    /text()表示提取<a>元素中的所有文本。
    chrome审查,右键,选取元素,Copy→Copy XPath
  4. 3.3 XPath的选取方法
    XPath使用路径表达式可以在网页源代码中选取节点,它是沿着路径来选取的,如表5-3所示。
    XPath路径表达式及其描述 https://res.weread.qq.com/wrepub/epub_928559_47
    下面是一个XML文档,我们将用XPath提取其中的一些数据。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <? xml version="1.0" encoding="ISO-8859-1"? >
    <bookstore>
    <book>
    <title lang="en">Harry Potter</title>
    <author>J K. Rowling</author>
    <year>2005</year>
    <price>29.99</price>
    </book>
    </bookstore>
    XPath的一些路径表达式及其结果:https://res.weread.qq.com/wrepub/epub_928559_48
    https://github.com/Santostang/PythonScraping/blob/master/%E7%AC%AC%E4%B8%80%E7%89%88/Cha%205%20-%E8%A7%A3%E6%9E%90%E7%BD%91%E9%A1%B5/Cha%205%20-%E8%A7%A3%E6%9E%90%E7%BD%91%E9%A1%B5.ipynb
  5. 5 BeautifulSoup爬虫实践:房屋价格数据
    目的:获取安居客网站上北京二手房的数据。获取前10页二手房源的名称、价格、几房几厅、大小、建造年份、联系人、地址、标签。
    网址:https://beijing.anjuke.com/sale/。
  6. 5.1 网站分析
  7. 5.2 项目实践
    通过以上分析已经能够获得各个数据所在的地址,接下来用requests加上BeautifulSoup获取安居客北京二手房结果的第一页数据,代码如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    import requests
    from bs4 import BeautifulSoup
    import time
    headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36'}
    for i in range(1,11):
    link = 'https://beijing.anjuke.com/sale/p' + str(i)
    r = requests.get(link, headers = headers)
    print ('现在爬取的是第', i, '页')
    soup = BeautifulSoup(r.text, 'lxml')
    house_list = soup.find_all('li', class_="list-item")
    for house in house_list:
    name = house.find('div', class_ ='house-title').a.text.strip()
    price = house.find('span', class_='price-det').text.strip()
    price_area = house.find('span', class_='unit-price').text.strip()
    no_room = house.find('div', class_='details-item').span.text
    area = house.find('div', class_='details-item').contents[3].text
    floor = house.find('div', class_='details-item').contents[5].text
    year = house.find('div', class_='details-item').contents[7].text
    broker = house.find('span', class_='brokername').text
    broker = broker[1:]
    address = house.find('span', class_='comm-address').text.strip()
    address = address.replace('\xa0\xa0\n ',' ')
    tag_list = house.find_all('span', class_='item-tags')
    tags = [i.text for i in tag_list]
    print (name, price, price_area, no_room, area, floor, year, broker, address, tags)
    time.sleep(5)
    进阶:获取其中的各项数据,如小区名称、房屋类型、房屋朝向、参考首付等。
    https://github.com/Santostang/PythonScraping/blob/master/%E7%AC%AC%E4%B8%80%E7%89%88/Cha%205%20-%E8%A7%A3%E6%9E%90%E7%BD%91%E9%A1%B5/Cha%205%20_%E7%AB%A0%E6%9C%AB%E5%AE%9E%E6%88%98.ipynb

    3.2. Xpath

    xpath语法
    表达式|说明|

–|–|
article|选取所有article元素的所有子节点|
/article|选取根元素article|
article/a|选取所有属于article的子元素的a元素|
//div|选取所有div元素(不管出现在文档里的任何地方)|
article//div|选取所有属于article元素的后代的div元素,不管它出现在article之下的任何位置|
/div/|选取属于div元素的所有子节点|
//
|选取所有元素|
//div[@*]|选取所有带属性的div 元素|
//@class|选取所有名为class的属性|
//div/a 丨//div/p|选取所有div元素的a和p元素|
//span丨//ul|选取文档中的span和ul元素|
article/div/p丨//span|选取所有属于article元素的div元素的p元素以及文档中所有的 span元素
xpath语法-谓语:
表达式|说明|
–|–|
/article/div[1]|选取属于article子元素的第一个div元素|
/article/div[last()]|选取属于article子元素的最后一个div元素|
/article/div[last()-1]|选取属于article子元素的倒数第二个div元素|
//div[@color]|选取所有拥有color属性的div元素|
//div[@color=’red’]|选取所有color属性值为red的div元素|
xpath的使用
会右键查看就能获取网页上任何内容

  1. xpath简介
  2. xpath术语与语法
  3. xpath抓取误区:javasrcipt生成html与html源文件的区别
  4. xpath抓取实例
    为什么要使用xpath?
    xpath使用路径表达式在xml和html中进行导航
    xpath包含有一个标准函数库
    xpath是一个w3c的标准
    xpath速度要远远超beautifulsoup。
    xpath节点关系
    父节点、上一层节点
    子节点
    兄弟节点、同胞节点
    先辈节点、父节点、爷爷节点
    后代节点、儿子、孙子
    xpath抓取误区
    firebugs插件
    取某一个网页上元素的xpath地址
    如:http://blog.jobbole.com/110287/
    在标题处右键使用firebugs查看元素。
    然后在

    2016 腾讯软件开发面试题(部分)

    右键查看xpath

    3.3. 解析器对比分析

    主要的解析器及其优缺点
    https://res.weread.qq.com/wrepub/epub_928559_44
    https://res.weread.qq.com/wrepub/epub_928559_49
    使用lxml的解析器将会解析得更快。

    4. 数据存储

    数据存储
    方式
  • TXT
  • CSV
  • Excel
  • JSON
  • MySQL
  • MongoDB及其优化建议
    如何存储数据
  • 存TXT。【写入和读取都非常方便,可以很快速地打开文件查看。用来存储测试用的数据。文件大时打开很慢。数据修改麻烦】
  • 存CSV。【同上】
  • 存MySQL。【数据量比较大、要与别人交换或别人也要访问时】
  • 存MongoDB。【同上。JSON格式数据而不用进行解析】
    文本——纯文本、Json、Xml等。
    二进制文件——如图片、视频、⾳频等直接保存成特定格式即可。
    关系型数据库——如MySQL、Oracle、SQL Server等具有结构化表结构形式存储。
    非关系型数据库——如MongoDB、Redis等Key-Value形式存储。

    4.1. 数据库

    创建、连接和查询
    数据导入
    Python3操作
    与标准Python客户端建立数据库接口
    数据库设计
  • oracle、Cassandra
  • 熟悉关系型(mysql/postgresql)、nosql(mongodb/hbase/elasticsearch/HBase/HIVE)、缓存sql(redis/memcached)
  • 调优和海量存储经验优先;能进行简单优化 有大数据开发经验优先 熟悉hadoop、spark、storm
  • 至少精通大数据量的一种关系型开发
  • 三种数据库的存储方式、SQLite、MySQL和MongoDB三种数据库的操作方式,实现爬取数据存储的多样化
    MySQL
    MongoDB
    Redis
    SQLite
    Excel表格自动合并
    ‘’’⽹页文本’’’——如HTML文档、Json格式文本等。
    ‘’’图⽚’’’——获取到的是二进制文件,保存为图片格式。
    ‘’’视频’’’——同为二进制文件,保存为视频格式即可。
    ‘’’其他’’’——只要是能请求到的,都能获取。

    5. 高性能爬取策略

    基础爬虫
    简单分布式爬虫
    Scrapy爬虫
    Scrapy分布式爬虫
    深度优先的递归
    广度优先
    定向爬取
    爬虫的浏览器伪装技术
    HTTP协议请求
    DebugLog
    异常处理神器——URLError
    Cookiejar精析
    并发和并行,同步和异步、异步加载技术与爬虫方法、多协程、多线程、多进程
    如何提升爬虫的速度效率(速度实现成倍提升)。比较。
    二叉树的遍历问题
    深度优先(递归实现)
    顺着一条路,走到最深处。然后回头。垂直方向
    广度优先(队列实现)
    分层遍历:遍历完儿子辈。然后遍历孙子辈。水平方向
    深度优先算法
1
2
3
4
5
6
7
def depth_tree(tree_node):
if tree_node is not None:
print (tree_node._data)
if tree_node._left is not None:
return depth_tree(tree_node.left)
if tree_node._right is not None:
return depth_tree(tree_node._right)

广度优先算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def level_queue(root):
#利用队列实现树的广度优先遍历
if root is None:
return
my_queue = []
node = root
my_queue.append(node)
while my_queue:
node = my_queue.pop(0)
print (node.elem)
if node.lchild is not None:
my_queue.append(node.lchild)
if node.rchild is not None:
my_queue.append(node.rchild)

5.1. 性能

标准性能模型
解决性能问题
系统性能
示例1:非常简单的管道
示例2:测量吞吐量和延时的扩展
超时设置
容错处理
定时爬取
自动化爬取的重要性
定向爬取的相关步骤与策略
动态渲染页面的爬取、JavaScript与AJAX数据爬取
简单的矩形区域抓取方式
高级区域抓取方式
创建自定义监控命令
使用ApacheSpark流计算偏移量

6. Scrapy分布式爬虫

好(较为成熟)的爬虫方案:多X程、分布式、将爬虫部署在服务器上把自己的个人计算机解放出来
如何通过Redis实现了一个分布式爬虫,让其在不同服务器之间通信。
分布式爬虫的好处是什么?

  • 队列的分配是依靠master的,当你获取数据的某一台slave奴隶服务器因为各种原因停止爬虫了,也不会让整个爬虫程序停下来。

  • 分布式爬虫既可成倍提升爬虫效率,又可保证爬虫的稳定性。

  • (1)服务器之间有通信,每个服务器的待爬网页无需手动分配。

  • (2)数据集中存储到某一个服务器或数据库中。统一管理能够实现从不同服务器爬虫的队列管理到数据存储的优化。
    Scrapy框架的安装
    Scrapy框架基本使用
    Scrapy命令行详解
    Scrapy中选择器的用法
    Scrapy中Spiders的用法
    Scrapy中Item Pipeline的用法
    Scrapy中Download Middleware的用法
    Scrapy爬取知乎用户信息实战
    Scrapy+Cookies池抓取新浪微博
    Scrapy+Tushare爬取微博股票数据
    命令行创建scrapy项目
    cd desktop
    scrapy startproject ArticleSpider
    scrapy目录结构
    scrapy借鉴了django的项目思想
    scrapy.cfg:配置文件。
    setings.py:设置
    SPIDER_MODULES = [‘ArticleSpider.spiders’] #存放spider的路径
    NEWSPIDER_MODULE = ‘ArticleSpider.spiders’
    pipelines.py: 数据存储相关
    middilewares.py: 自己定义的middlewares 定义方法,处理响应的IO操作
    init.py:项目的初始化文件。
    items.py:定义我们所要爬取的信息的相关属性。Item对象是种类似于表单,用来保存获取到的数据
    创建spider
    cd ArticleSpider
    scrapy genspider jobbole blog.jobbole.com
    自动生成

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    -*- coding: utf-8 -*-
    import scrapy
    class JobboleSpider(scrapy.Spider):
    name = "jobbole"
    allowed_domains = ["blog.jobbole.com"]
    # start_urls是一个带爬的列表,
    #spider会为我们把请求下载网页做到,直接到parse阶段
    start_urls = ['http://blog.jobbole.com/']
    def parse(self, response):
    pass

    在命令行启动Spider
    scrapy crawl jobbole
    创建调试工具类
    在项目根目录里创建main.py作为调试工具文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    # _*_ coding: utf-8 _*_
    #
    __author__ = 'mtianyan'
    __date__ = '2017/3/28 12:06'
    #
    import sys
    import os
    from scrapy.cmdline import execute
    #
    # 将系统当前目录设置为项目根目录
    # os.path.abspath(__file__)为当前文件所在绝对路径
    # os.path.dirname为文件所在目录
    # H:\CodePath\spider\ArticleSpider\main.py
    # H:\CodePath\spider\ArticleSpider
    sys.path.append(os.path.dirname(os.path.abspath(__file__)))
    # 执行命令,相当于在控制台cmd输入改名了
    execute(["scrapy", "crawl" , "jobbole"])

    设置不遵守reboots协议
    settings.py的
    ROBOTSTXT_OBEY = False
    ⭕在jobble.py打上断点
    def parse(self, response):
    pass
    返回的htmlresponse对象:
    body:网页内容
    _DEFAULT_ENCODING= ‘ascii’
    encoding= ‘utf-8’
    scrapy已经为我们做到了将网页下载下来。而且编码也进行了转换.
    import scrapy
    class JobboleSpider(scrapy.Spider):
    name = “jobbole”
    allowed_domains = [“blog.jobbole.com”]
    start_urls = [‘http://blog.jobbole.com/110287/']
    def parse(self, response):

    re_selector = response.xpath("/html/body/div[3]/div[3]/div[1]/div[1]/h1")
    # print(re_selector)
    pass

    调试debug可以看到
    re_selector =(selectorlist)[]
    可以看到返回的是一个空列表,
    列表是为了如果我们当前的xpath路径下还有层级目录时可以进行选取
    空说明没取到值:

    //*[@id=”post-110287”]/div[1]/h1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    import scrapy
    class JobboleSpider(scrapy.Spider):
    name = "jobbole"
    allowed_domains = ["blog.jobbole.com"]
    start_urls = ['http://blog.jobbole.com/110287/']
    def parse(self, response):
    re_selector = response.xpath('//*[@id="post-110287"]/div[1]/h1')
    # print(re_selector)
    pass

    6.1. 概述

    分布式系统概述
    初识Scrapy Scrapy是一个Twisted应用
    喜欢Scrapy的更多理由
    Scrapy不是什么
    框架介绍、架构概述、核心架构
    目录结构
    Scrapy设置
    常用的Scrapy组件详解
    Scrapy工作流
    Scrapy引擎——一种直观方式
    Scrapy高级应用
    理解Scrapy性能

    6.2. 部署到Scrapinghub

    搜索引擎核心
    爬行策略
    网页更新策略
    身份识别
    什么是Cookie
    常用工具命令
    Spider类参数传递
    避免被禁止
    UR2lM——基本抓取流程
    抽取更多的URL
    创建手机应用
    访问item
    配置与管理
    基本设置
    进阶设置
    信号
    管道秘诀
    使用RESTAPl
    使用Twisted专用客户端建立服务接口
    为CPU密集型、阻塞或遗留功能建立接口
    使用telnet获得组件利用率
    基准系统
    故障排除流程

    6.3. 代码

    items的编写
    pipelines的编写
    settings的编写
    Items的编写
    Spider的编写

    6.4. 使用Scrapy填充数据库

    Scrapy的中文输出
    Scrapy的中文存储
    Scrapy与MongoDB
    Scrapy与Redis

    6.5. Scrapyd

    分布式爬虫与Scrapy
    Scrapyd部署分布式爬虫
    Scrapyd与实时分析进行分布式爬取

    6.6. Scrapy项目

    用Scrapy进行爬虫项目管理
    Scrapy爬虫多开技能
    从Scrapy到移动应用
    财经新闻数据
    博客
    Redis分布式爬虫实践
    认识框架
    框架安装难点解决技巧
    常见指令
    使用
    You-get源码分析
    与Urllib的整合
    多线程
    分布式
    https://github.com/LUCY78765580/Python-web-scraping
    https://github.com/qiyeboy/SpiderBook
    分布式爬虫的架构解析
    分布式爬虫实现原理
    分布式爬虫之Docker基础
    分布式爬虫之Redis基础
    分布式爬虫构建实战
    Scrapy分布式原理及Scrapy-Redis源码解析
    Scrapy分布式架构搭建抓取知乎
    Scrapy分布式的部署详解
    小白爬虫第一弹之抓取妹子图
    小白爬虫第二弹之健壮的小爬虫
    小白爬虫第三弹之去重去重
    小白爬虫第四弹之爬虫快跑(多进程+多线程)
    小白进阶之Scrapy第一篇
    小白进阶之Scrapy第二篇(登录篇)
    小白进阶之Scrapy分布式的前篇–让redis和MongoDB安全点
    小白进阶之Scrapy第三篇(基于Scrapy-Redis的分布式以及cookies池)
    小白进阶之Scrapy第四篇(图片下载管道篇)
    小白进阶之Scrapy第五篇(Scrapy-Splash配合CrawlSpider;瞎几把整的)
    利用新接口抓取微信公众号的所有文章
    小白进阶之Scrapy第六篇Scrapy-Redis详解
    https://www.jianshu.com/p/cd4054bbc757
    https://cloud.tencent.com/developer/article/1114535
    爬虫只运行在一台机器上时,受计算能力和网络带宽的影响,即使使用了异步和多线程技术,在待爬数据量较大时,需要耗费的时间会比较长,爬取效率也非常有限。
    而多台主机协同爬取,效率会成倍增加。此即为分布式爬取,在网络中的多台计算机上同时运行爬虫程序,共同完成一个大型爬取任务。
    Scrapy本身并不是一个为分布式爬取而设计的框架,但第三方库scrapy-redis为其拓展了分布式爬取的功能,两者结合便是一个分布式Scrapy爬虫框架。
    在分布式爬虫框架中,需要使用某种通信机制协调各个爬虫的工作,让每一个爬虫明确自己的任务,其中包括:
    (1)当前的爬取任务,即下载+提取数据(分配任务)。
    (2)当前爬取任务是否已经被其他爬虫执行过(任务去重)。
    (3)如何存储爬取到的数据(数据存储)。
    scrapy-redis利用Redis数据库作为多个爬虫的数据共享实现以上功能。
    网站的树结构(url分层设计)
    网站url树结构分层设计:
    bogbole.com
    blog.bogbole.com
    python.bogbole.com
    python.bogbole.com/123
    去重问题与策略
    环路链接问题
    从首页到下面节点。
    但是下面的链接节点又会有链接指向首页。
    有些已经爬过
    将访问过的url保存到数据库中
    将url保存到set中。只需要O(1)的代价就可以查询到url

    1000000002byte50个字符/1024/1024/1024 = 9G
    url经过md5等方法哈希后保存到set中,将url压缩到固定长度而且不重复
    用bitmap方法,将访问过的url通过hash函数映射到某一位
    bloomfilter方法对bitmap进行改进,多重hash函数降低冲突(scrapy去重,分布式scrapy-redis)
    基于Hadoop的分布式网络爬虫系统的设计与实现

    7. 数据分析

    7.1. 可视化

    地图
    轨迹

    7.2. NumPy

    一维数组
    多维数组
    数组的运算

    7.3. pandas

    数据清洗
    数据分组、分割、合并和变形
    缺失值、异常值和重复值处理
    时序数据处理
    数据类型转换

    8. 框架

    爬虫架构设计
    爬虫框架
    什么是
    常见的

  • CrawlSpider与链接提取器、CrawlSpider实例

  • Crawley

  • Portia

  • newspaper

  • Python-goose

  • PySpider
    手机应用框架
    PySpider框架基本使用及抓取TripAdvisor实战
    PySpider架构概述及用法详解
    PyQuery详解
    Selenium详解

    9. 项目实施

    熟练掌握一种开源爬虫工具,有研发爬虫框架经验者优先;scrapy、webmagic、nutch、heritrix、Requests、Selenium、Appium、PhantomS

  • 著名爬虫框架Scrapy的运用、

  • 通过Redis和Scrapy的结合实现分布式爬虫

  • 整个的实现过程以及注意事项

  • PySpider(基本功能)
    熟悉HttpClient、HtmlParser、Jsoup、Lucene、Nutch中的一种或多种开源技术
    研究各种网页特点和规律
    项目描述
    功能分析
    实现思路
    网站分析
    编写实战
    调试与运行
    项目实施
    优化方案
    代码优化
    效率优化
    网页分析算法
    数据来源分析
    工作流程
    通过热力图分析为用户提供出行建议
    从数据到产品
    产品设计
    产品交付
    数据获取渠道
    发现数据的价值
    pyecharts业服务
    从价值探索到交付落地
    创新的不确定性
    房产的标题是如何影响价格的
    通过 2 个爬虫免试获得 2 个业界知名公司 offer

  • 具备一个爬虫开发工程师需要的全部技能
  • 理论性、经验性的内容为主,远远无法达到一个系统的标准
  • 完整的爬虫开发需要学习的知识的体系
  • 在过去的工作中完成过上百个抓取任务
  • 参与和维护着使用 Celery、Twisted 等技术完成每天上亿次抓取量的抓取服务
  • 3个写爬虫实现功能的视频
  • 17年4月在知乎开过一场叫做 爬虫从入门到进阶 的知乎Live,目前已经有3.3k+人参加,评分4.9分(满分5分)

    9.1. 框架搭建

    架构设计、系统规划、建立、开发、研发、维护(完善)与管理、日常监控、优化、建模、调研
    爬虫系统的架构设
  • 精通信息抓取抽取技术和整合技术、抽取算法保证抽取、去重、分类、解析、增量融合入库等流程之后的数据结果;内容提取
    • 网页去重 、大规模爬取中的去重问题 、海量数据的去重方式以及各种去重方式的优劣比较
  • 网页信息调度、采集抓取提取、维护、验证、抓取规划、解析、清洗、入库以及汇总、清洗、整理、整合及合并、有数据分析能力。研发和优化工作
  • 分布式网络爬虫、高并发、高可用爬虫平台架构的设计和优化
  • 爬虫系统与数据分析系统数据接口设计和开发
  • 高性能爬虫系统的后台监控、报警模块的开发
  • 爬虫引擎核心功能
  • 能快速部署新的爬虫应用
    • 多线程、多进程、协程相关知识及编程经验 、网路编程以及Web认证机制
    • 分布式、
    • 抓取调度,多样化抓取,页面解析和结构化抽取,海量数据存储和读取、实时高并发海量数据爬取
  • 核心算法的策略优化:充分利用资源,避免限制;
    • 模板提高扩展性、效率和质量、持续优化系统提高系统的稳定性、监控抓取数据的完整性
    • 调权调度、分析预测、质量判断、封禁与反封禁研究
  • 备份

    9.2. 扩展技能

    熟悉搜索引擎、有搜索开发经验加分、优化搜索、匹配、抓取等关键程序的性能及效率
    有网站开发经历加分、web挖掘能力
    挖掘算法优化
    数据分类及分布统计,文本分类、统计分析
    特征挖掘。具有数据挖掘、自然语言处理、信息检索
    个性化相关的机器学习算法、精通主流分词算法、分类、提取摘要、大规模网页聚类、索引等相关开发经验者优先。
    有客户端及相关安全领域经验者优先

    9.3. 后起

    网页外挂机器人开发及维护
    进行技术分享与培训
    网页数据的自动化爬取脚本
    数据爬取平台相关工具平台的架构设计与产品开发
    参与数据层建设,专注于基础数据采集平台建设
    爬取10w量级的数据
    统计分析、可视化展示,发掘数据价值 【彩色直方图、折线图】
    Django展示数据图
    多平台信息的抓取和分析

    9.4. 加分项目

    垂直领域数据 社交、新闻媒体、论坛类、商业大数据、金融证券行业
    网络数据源
  • 网站(页):电商网站、定期爬取指定网站(如亚马逊、ebay平台)的数据、有大型B2C、C2C电商网站
  • APP
    1,项目的目标。【爬取知乎Live的所有实时语音分享以及知乎Live的听众。知乎Live的URL地址为https://www.zhihu.com/lives】

2.列举出各项目所采用的技术。
3.初始Url
4.项目步骤

  • 一个简单的Python网络爬虫
  • 维基百科
    • 维基百科是一个网络百科全书,在一般情况下允许用户编辑任何条目。当前维基百科由非营利组织维基媒体基金会负责营运。维基百科一词是由网站核心技术Wiki和具有百科全书之意的encyclopedia共同创造出来的新混合词Wikipedia。
  • 大众点评
  • (1)通过大众点评的搜索结果获取餐厅的基本信息和地址。
  • (2)进入每家店铺的网页,获取大众点评餐厅的详细信息和评价。
  • 百度地图API
    • http://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-placeapi
    • 获取中国所有城市的公园数据,并且获取每一个公园具体的评分、描述等详情,最终将数据存储到MySQL数据库中。
    • 拥有丰富的餐馆、房地产等数据,是一款网络地图搜索服务。可查地理位置,最近位置。街道、商场、楼盘、餐馆、学校、银行、公园等。百度地图提供了丰富的API供开发者调用,我们可以免费地获取各类地点的具体信息。
    • 免费API:新浪微博、豆瓣电影、饿了么、豆瓣音乐、Facebook、Twitter。
    • 收费API:百度API Store、聚合数据
  • 知乎
    • 知乎是中文互联网一个非常大的知识社交平台。在知乎上,用户可以通过问答等交流方式获取知识。区别于百度知道等问答网站,知乎的回答往往非常深入,都是回答者精心写的,知乎上聚集了中国互联网科技、商业、文化等领域里最具创造力的人群,将高质量的内容通过人的节点形成规模的生产和分享,构建高价值人际关系网络。
  • 爬取了博客文章评论

    10. 实际爬虫

    Requests+正则表达式
    分析Ajax请求
    使用Selenium模拟浏览器
    使用Redis+Flask
    房产
    基于位置信息的Ⅰ
    猫眼电影
    今日头条街拍美图
    淘宝商品美食信息
    维护动态代理池
    维护动态Cookies池
    使用代理处理反爬抓取微信文章
    图片
    链接
    糗事百科
    微信
    博客类
    图片类
    模拟登录
    抢票软件的实现
    PEXELS图片
    糗事百科网的用户地址信息
    豆瓣音乐TOP250的数据
    豆瓣电影TOP250的数据
    豆瓣网图书TOP250的数据
    维基百科
    餐厅点评
    知乎Live
    百度地图API
    畅销书籍
    TOP250电影数据
    房屋价格数据
    虎扑论坛
    酷狗TOP500的数据
    知乎网Python精华话题
    简书网热门专题信息
    简书网专题收录文章
    简书网推荐信息
    简书网热评文章
    简书网用户动态信息
    简书网7日热门信息
    拉勾网招聘信息
    起点中文网小说信息
    《斗破苍穹》全文小说
    新浪微博好友圈信息
    QQ空间好友说说
    转转网二手市场商品信息
    淘宝商品信息
    北京地区短租房信息
    糗事百科网的段子信息
    电商网站(商品)数据——大型爬虫(Selenium)
    BOSS直聘爬虫
    Keep热门
    果壳网自动登录
    大麦网演出
    小说网
    博客
    猜数游戏半自动爬虫开发
    股票行情(用Scrapy)
    深圳短租数据(Selenium)
    用API爬取天气预报数据
    知乎(asyncio)
    新浪微博
    京东
    淘宝
    出版社信息
    京东图书
    当当网
    新闻
    豆瓣网登陆爬虫与验证码自动识别
    模拟登录
    腾讯动漫(JS动态触发+id随机生成反爬破解实战)
    微信爬虫
    腾讯视频评论爬虫思路介绍
    腾讯视频评论爬虫实战
    糗事百科
    抓包分析实战
    tt商品图片爬虫实战
    tt商品大型爬虫项目与自动写入数据库实战)
    作业讲解:博文信息的爬取
    腾讯微信和视频
    百度信息自动搜索
    自动POST

    10.0.1. 简单的爬虫

    【用到的库】requests + bs4
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # https://github.com/Santostang/PythonScraping/blob/master/第一版/Cha 2 - 编写你的第一个网络爬虫/Cha 2 _章末实战.ipynb
    #!/usr/bin/python
    # coding: utf-8
    import requests
    from bs4 import BeautifulSoup #从bs4这个库中导入BeautifulSoup
    # 第一步:获取页面
    link = "http://www.santostang.com/"
    headers = {'User-Agent' : 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}
    r = requests.get(link, headers= headers) # requests的headers伪装成浏览器访问。r是requests的Response回复对象。
    # 第二步:提取需要的数据
    soup = BeautifulSoup(r.text, "html.parser") # 使用BeautifulSoup解析这段网页。把HTML代码转化为soup对象。r.text是获取的网页内容代码
    title = soup.find("h1", class_="post-title").a.text.strip() # 提取第一篇文章的标题
    print (title)
    # 第三步:存储数据
    with open('title_test.txt', "a+") as f:
    f.write(title)

    10.0.2. 爬取豆瓣电影TOP250

    【用到的库】requests + bs4
    获取豆瓣电影TOP250的所有电影的名称
    网页地址为:https://movie.douban.com/top250
    第一页有25个电影
    获取所有的250页电影
    总共10页的内容
    第二页:https://movie.douban.com/top250? start=25
    第三页:https://movie.douban.com/top250? start=50
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    import requests
    from bs4 import BeautifulSoup
    def get_movies():
    headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36',
    'Host': 'movie.douban.com'
    }
    movie_list = []
    for i in range(0,10):
    link = 'https://movie.douban.com/top250?start=' + str(i * 25)
    r = requests.get(link, headers=headers, timeout= 10)
    print (str(i+1),"页响应状态码:", r.status_code)

    soup = BeautifulSoup(r.text, "lxml")
    div_list = soup.find_all('div', class_='hd')
    for each in div_list:
    movie = each.a.span.text.strip()
    movie_list.append(movie)
    return movie_list

    movies = get_movies()
    print (movies)
    # 原文有误
    # 用 ]: 便于在 ipynb 中查找下一项
    参考链接:豆瓣电影(https://github.com/Santostang/PythonScraping/blob/master/第一版/Cha 3 -静态网页抓取/Cha 3 _章末实战.ipy)
    进阶问题:获取TOP 250电影的英文名、港台名、导演、主演、上映年份、电影分类以及评分。

    10.0.3. 爬取动态网页

    【用到的库】requests + json
    AJAX加载的动态网页,有两种爬取方法:
    (1)通过浏览器审查元素解析地址。
    (2)通过Selenium模拟浏览器抓取。
    两个特别重要的变量,即offset和limit。
    limit:每一页评论数量的最大值
    offset:本页的第一条评论是总的第几条
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    import requests
    import json
    def single_page_comment(link):
    headers = {'User-Agent' : 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}
    r = requests.get(link, headers= headers)
    # 获取 json 的 string
    json_string = r.text
    json_string = json_string[json_string.find('{'):-2]
    json_data = json.loads(json_string) # 使用json.loads()把字符串格式的响应体数据转化为json数据
    comment_list = json_data['results']['parents'] # json数据的结构提取
    for eachone in comment_list:
    message = eachone['content']
    print (message)
    for page in range(1,4):
    link1 = "https://api-zero.livere.com/v1/comments/list?callback=jQuery112407875296433383039_1506267778283&limit=10&offset="
    link2 = "&repSeq=3871836&requestPath=%2Fv1%2Fcomments%2Flist&consumerSeq=1020&livereSeq=28583&smartloginSeq=5154&_=1506267778285"
    page_str = str(page)
    link = link1 + page_str + link2
    print (link)
    single_page_comment(link)
    参考链接:
    https://github.com/Santostang/PythonScraping/blob/master/第一版/Cha 4 -动态网页抓取/Cha 4 -动态网页抓取.ipynb

    10.0.4. 通过Selenium模拟浏览器抓取

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    from selenium import webdriver
    driver = webdriver.Firefox()
    driver.get("https://www.dianping.com/search/category/7/10/p1")
    # 如果运行之后,发现程序报错:
    # selenium.common.exceptions.WebDriverException: Message: 'geckodriver' executable needs to be in PATH.
    # 可以到https://github.com/mozilla/geckodriver/releases下载最新版的geckodriver,解压后可以放在Python安装目录(可能是Script子文件夹)下(可能需并放在环境变量的PATH中)。
    from selenium import webdriver
    from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
    caps = webdriver.DesiredCapabilities().FIREFOX
    caps["marionette"] = False

    path = r'D:\\Program Files\\Mozilla Firefox\\firefox.exe'
    binary = FirefoxBinary(path) # Firefox程序的地址
    driver = webdriver.Firefox(firefox_binary=binary, capabilities=caps)
    driver.get("http://www.santostang.com/2017/03/02/hello-world/")
    import time
    try:
    load_more = driver.find_element_by_css_selector('div.tie-load-more') # 更多或下一页
    load_more.click() # 模拟单击
    except:
    pass
    comments = driver.find_elements_by_css_selector('div.bdy- inner')
    time.sleep(5)
    user = driver.find_element_by_name("username") #找到用户名输入框
    user.clear #清除用户名输入框内容
    user.send_keys("1234567") #在框中输入用户名
    pwd = driver.find_element_by_name("password") #找到密码输入框
    pwd.clear #清除密码输入框内容
    pwd.send_keys("******") #在框中输入密码
    driver.find_element_by_id("loginBtn").click() #单击登录

    10.0.5. 深圳短租

    目的:获取Airbnb深圳前20页的短租房源的名称、价格、评价数量、房屋类型、床数量和房客数量。监控和了解竞争对手的房屋名称和价格,让自己的房子有竞争力。
    网址:https://zh.airbnb.com/s/Shenzhen--China?page=1

4.4.1 网站分析
一个房子的所有数据。地址为:div.infoContainer_v72lrv。
价格数据,地址为:div.priceContainer_4ml1ll
评价数据,地址为:span.text_5mbkop-o_O-size_micro_16wifzf-o_O-inline_g86r3e
房屋名称数据,地址为:div.listingNameContainer_kq7ac0-o_O-ellipsized_1iurgbx
房间类型、床数量和房客数量,地址为:span.detailWithoutWrap_j1kt73
4.4.2 项目实践
用Selenium获取Airbnb第一页的数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from selenium import webdriver
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
import time
caps = webdriver.DesiredCapabilities().FIREFOX
caps["marionette"] = True
binary = FirefoxBinary(r'C:\Program Files\Firefox Developer Edition\firefox.exe')
# 把上述地址改成你电脑中Firefox程序的地址
# 如果没改,会出现selenium.common.exceptions.SessionNotCreatedException: Message: Unable to find a matching set of capabilities
#用 selenium 的 driver 来启动 firefox
driver = webdriver.Firefox(firefox_binary=binary, capabilities=caps)
#在虚拟浏览器中打开 Airbnb 页面。使用Selenium打开该页面
driver.get("https://zh.airbnb.com/s/Shenzhen--China?page=1")
time.sleep(20)
#找到页面中所有的出租房。用Selenium的css selector获取所有房屋的div数据
rent_list = driver.find_elements_by_css_selector('div._1788tsr0')
#对于每一个出租房
for eachhouse in rent_list:
#找到评论数量
try:
comment = eachhouse.find_element_by_css_selector('span._gb7fydm')
comment = comment.text
except:
comment = 0
#找到价格
price = eachhouse.find_element_by_css_selector('span._hylizj6')
price = price.text[4:]
#找到名称
name = eachhouse.find_element_by_css_selector('div._ew0cqip')
name = name.text
#找到房屋类型,大小
details = eachhouse.find_elements_by_css_selector('div._saba1yg small div span')
details = details[0].text
house_type = details.split(" · ")[0]
bed_number = details.split(" · ")[1]
print (comment, price, name, house_type, bed_number)

进阶:将Selenium的控制CSS加载、控制图片加载和控制JavaScript加载加入本实践项目的代码中,从而提升爬虫的速度。
https://github.com/Santostang/PythonScraping/blob/master/%E7%AC%AC%E4%B8%80%E7%89%88/Cha%204%20-%E5%8A%A8%E6%80%81%E7%BD%91%E9%A1%B5%E6%8A%93%E5%8F%96/Cha%204%20_%E7%AB%A0%E6%9C%AB%E5%AE%9E%E6%88%98.ipynb

11. 相关参考

11.1. allitebooks

Web Scraping with Python(有2版)
Website Scraping with Python -
Learning Scrapy
Webbots, Spiders, and Screen Scrapers
Getting Started with Beautiful Soup

11.2. 其他

Web Scraping with Python Collecting More Data from the Modern Web- 城通网盘 ||似乎与Ryan Mitchell的是同一本
Learning Selenium Testing Tools with Python
Python Requests Essentials
Web Scraping with Python, 2nd Edition
Practical Web Scraping for Data Science
Python Web Scraping Cookbook - 2018
Spider Webb’s Angels
Python Web Scraping
Python数据抓取技术与实战 仅京东

11.3. 中文书籍

  • Python网络爬虫从入门到实践,唐松
  1. Python爬虫入门一之综述
  2. Python爬虫入门二之爬虫基础了解
  3. Python爬虫入门三之Urllib库的基本使用
  4. Python爬虫入门四之Urllib库的高级用法
  5. Python爬虫入门五之URLError异常处理
  6. Python爬虫入门六之Cookie的使用
  7. Python爬虫入门七之正则表达式

    11.8.2. 二、爬虫实战

  8. Python爬虫实战一之爬取糗事百科段子
  9. Python爬虫实战二之爬取百度贴吧帖子
  10. Python爬虫实战三之实现山东大学无线网络掉线自动重连
  11. Python爬虫实战四之抓取淘宝MM照片
  12. Python爬虫实战五之模拟登录淘宝并获取所有订单
  13. Python爬虫实战六之抓取爱问知识人问题并保存至数据库
  14. Python爬虫实战七之计算大学本学期绩点
  15. Python爬虫实战八之利用Selenium抓取淘宝匿名旺旺

    11.8.3. 三、爬虫利器

  16. Python爬虫利器一之Requests库的用法
  17. Python爬虫利器二之Beautiful Soup的用法
  18. Python爬虫利器三之Xpath语法与lxml库的用法
  19. Python爬虫利器四之PhantomJS的用法
  20. Python爬虫利器五之Selenium的用法
  21. Python爬虫利器六之PyQuery的用法

    11.8.4. 四、爬虫进阶

  22. Python爬虫进阶一之爬虫框架概述
  23. Python爬虫进阶二之PySpider框架安装配置
  24. Python爬虫进阶三之爬虫框架Scrapy安装配置
  25. Python爬虫进阶四之PySpider的用法
  26. Python爬虫进阶五之多线程的用法
  27. Python爬虫进阶六之多进程的用法
  28. Python爬虫进阶七之设置ADSL拨号服务器代理

    12. 附录

    必备软件的安装与故障排除

    12.1. 平台

    搭建平台、开发环境
    Linux、Windows、Mac

    12.2. 软件安装及环境配置

    Anaconda: https://www.continuum.io/downloads
    Jupyter
    默认端口:8888
    为什么推荐大家使用Jupyter学习和编写Python脚本呢?
    Jupyter:交互式编程和展示功能。
    分段执行,编写和测试时边看边写,加快调试速度。
    能够把运行和输出的结果保存下来,下次打开这个Notebook时也可以看到之前运行的结果。
    还可以添加各种元素,比如图片、视频、链接等,同时还支持Markdown,可以充当PPT使用。
    Alt + Enter jupyter快捷键
    MongoDB环境配置
    Robomongo:MongoDB数据库的可视化管理工具。
    MySQL环境配置
    Python、Python多版本共存配置
    PyCharm
    Redis、修改Redis配置
    Redis Desktop Manager:Redis的可视化管理工具。

13. 术语表

Anaconda:Python开发集成环境。南美洲的巨蟒。自带Python、pip和Jupyter。
第三方库:可理解为供用户调用的代码组合。在安装某个库之后,可以直接调用其中的功能,使得我们不用一个代码一个代码地实现某个功能。
代码缩进:代码要按照结构以Tab键或者4个空格进行缩进严格缩进
DT(Data Technology,数据技术)
命令提示符。输入一些命令后,可执行对系统的管理。 Windows的cmd,开始按钮→cmd。Mac的terminal。应用程序→terminal。
爬虫:
pip:Python安装各种第三方库(package)的工具。
Python:蟒蛇
数据交换:网站与用户的沟通本质。
print
Python不需要在使用之前声明需要使用的变量和类别。
字符串(string):单引号(’)或双引号(”)
连接字符串: +
数字(Number):数字用来存储数值
整数(int)
浮点数(float):由整数和小数部分组成。
列表(list):能够包含任意种类的数据类型和任意数量。
创建列表非常容易,只要把不同的变量放入方括号中,并用逗号分隔即可,例如list0 = [“a”,2,”c”,4]
增删查改、索引、切片
字典(Dictionaries):一种可变容器模型。
键(key)和值(value)。key必须唯一,但是值不用。值也可以取任何数据类型。
遍历
条件语句:满足条件的时候才执行某部分代码。条件为布尔值,也就是只有True和False两个值。
当if判断条件成立时才执行后面的语句;当条件不成立的时候,执行else后面的语句
如果需要判断的有多种条件,就需要用到elif
无序:字典
有序:列表、元组
对象有两种,即可更改(mutable)与不可更改(immutable)对象。在Python中,strings、tuples和numbers是不可更改对象,而list、dict等是可更改对象。
循环语句:多次执行一个代码片段。
循环分为for循环和while循环。
for循环:在一个给定的顺序下重复执行。
while循环:不断重复执行,只要能满足一定条件。
函数
代码庞大复杂时,使得代码易读,可重复使用,并且容易调整顺序。
函数的参数与返回值
面向过程编程:根据业务逻辑从上到下写代码,最容易被初学者接受。
函数式编程:把某些功能封装到函数中,需要用时可以直接调用,不用重复撰写。函数式的编程方法节省了大量时间。只需要写清楚输入和输出变量并执行函数即可。
面向对象编程:把函数进行分类和封装后放入对象中,使得开发更快、更强。首先要创建封装对象,然后还要通过对象调用被封装的内容。在某些应用场景下,面向对象编程能够显示出更大的优势。
如果各个函数之间独立且无共用的数据,就选用函数式编程;如果各个函数之间有一定的关联性,选用面向对象编程比较好。
特性与行为,属性和方法
面向对象的两大特性:封装和继承。
封装:把内容封装好,再调用封装好的内容。使用构造方法将内容封装到对象中,然后通过对象直接或self间接获取被封装的内容。
继承:以普通的类为基础建立专门的类对象。子继承了父的某些特性。将多个类共有的方法提取到父类中,子类继承父类中的方法即可,不必一一实现每个方法。
【状态码】
200,请求成功
4xx,客户端错误
5xx,服务器错误
【请求头】
Headers:提供了关于请求、响应或其他发送实体的信息。
如果没有指定请求头或请求的请求头和实际网页不一致,就可能无法返回正确的结果。
Chrome浏览器的检查。单击需要请求的网页,在Headers中可以看到Requests Headers的详细信息。
请求头的信息为:
GET / HTTP/1.1
Host: www.santostang.com
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36
Accept:
text/html, application/xhtml+xml, application/xml; q=0.9, image/webp, /; q=0.8 Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US, en; q=0.8, zh-CN; q=0.6, zh; q=0.4, zh-TW; q=0.2
GET请求,密码会显示在URL中,非常不安全。
POST请求,
【动态网页】
AJAX(Asynchronous Javascript And XML,异步JavaScript和XML),一种异步更新技术。
单击“更多”,url地址没有任何改变,有新内容加载出来。
数据不会出现在网页源代码中。但是有JavaScript代码。
最后呈现出来的数据是通过JavaScript加载的。
通过在后台与服务器进行少量数据交换就可以使网页实现异步更新。
在不重新加载整个网页的情况下对网页的某部分进行更新。
减少了网页重复内容的下载
节省了流量
更小、更快、更友好
传统的网页必须重载整个网页页面
动态网页的例子
http://www.santostang.com/2018/07/04/hello-world/
页面下面的评论用JavaScript加载。评论数据没法在在网页源代码找到。
注释:#

Hexo

0.1. 说明

记录本站所采用的主题的改动历史。学习和记录hexo的相关配置和操作。

0.2. 小记

主博客用的是Yelee主题,修改了UI,使其比较符合自己的口味。子博客用的是landscape主题,修改了bannar、浮悬导航及部分其他UI,增加了目录和到顶部按钮。抽离出自定义子博客模块。自此,每个新子博客用一条命令,三五个动作就可以部署成功了,扩展性大幅度增强。

Read More

SQL

1. 刷题

UPDATE salary
SET sex = char(ASCII(SEX)^ASCII(‘m’)^ASCII(‘f’))

SELECT *
FROM cinema
WHERE id %2 = 1 and description != ‘boring’ SQL里判断相等用的是一个等号
ORDER BY rating DESC 默认的排序为升序

https://leetcode.com/problems/classes-more-than-5-students/submissions/
SELECT
class
FROM
courses
GROUP BY
class
HAVING
COUNT(DISTINCT student)>=5;

https://leetcode.com/problems/duplicate-emails/

SELECT
Email
FROM
Person
GROUP BY
Email
HAVING
COUNT(*) > 1

https://leetcode.com/problems/combine-two-tables/
SELECT FirstName, LastName, City, State
FROM Person LEFT JOIN Address USING(PersonId)

https://leetcode.com/problems/employees-earning-more-than-their-managers/
SELECT E1.Name AS Employee
FROM Employee AS E1, Employee AS E2
WHERE E1.ManagerId = E2.Id AND E1.Salary > E2.Salary

https://leetcode.com/problems/customers-who-never-order/description/
连接和子查询两种方法(子查询更快leetcode上)
到底是哪个ID,不同表中同一名称的列代表了不同的内容

SELECT Name AS Customers
FROM Customers
WHERE Id NOT IN (SELECT CustomerId FROM Orders)

SELECT C1.Name AS Customers
FROM Customers C1 LEFT JOIN Orders O1 ON C1.Id=O1.CustomerId
WHERE O1.CustomerId IS NULL

2. 概述

2.1. 模式

模式定义了数据如何存储、存储什么样的数据以及数据如何分解等信息,数据库和表都有模式。

2.2. 主键

主键的值不允许修改,也不允许复用(不能将已经删除的主键值赋给新数据行的主键)。

2.3. SQL

SQL(Structured Query Language),标准 SQL 由 ANSI 标准委员会管理,从而称为 ANSI SQL。各个 DBMS 都有自己的实现,如 PL/SQL、Transact-SQL 等。

2.4. 大小写

SQL 语句不区分大小写,但是数据库表名、列名和值是否区分依赖于具体的 DBMS 以及配置。

SQL 支持以下三种注释:

3. 语法

3.1. 注释

1
2
3
4
SELECT *
FROM mytable; -- 注释
/* 注释1
注释2 */

3.2. 创建数据库与使用数据库

1
2
CREATE DATABASE test;
USE test;

3.3. 创建表

1
2
3
4
5
6
7
8
9
10
11
CREATE TABLE mytable (
# int 类型,不为空,自增
id INT NOT NULL AUTO_INCREMENT,
# int 类型,不可为空,默认值为 1,不为空
col1 INT NOT NULL DEFAULT 1,
# 变长字符串类型,最长为 45 个字符,可以为空
col2 VARCHAR(45) NULL,
# 日期类型,可为空
col3 DATE NULL,
# 设置主键为 id
PRIMARY KEY (`id`));

3.4. 创建新子表

1
2
CREATE TABLE newtable AS
SELECT * FROM mytable;

3.5. 增加列

1
2
ALTER TABLE mytable
ADD col CHAR(20);

3.6. 删除行

1
2
3
DELETE FROM mytable
WHERE id = 1;
-- 使用更新和删除操作时一定要用 WHERE 子句,不然会把整张表的数据都破坏。可以先用 SELECT 语句进行测试,防止错误删除。

3.7. 删除列

1
2
ALTER TABLE mytable
DROP COLUMN col;

3.8. 删除表

1
DROP TABLE mytable;

3.9. 清空表

– TRUNCATE TABLE 可以清空表,也就是删除所有行。

1
TRUNCATE TABLE mytable;

3.10. 增加行

1
2
INSERT INTO mytable(col1, col2)
VALUES(val1, val2);

3.11. 跨表增加行

1
2
3
INSERT INTO mytable1(col1, col2)
SELECT col1, col2
FROM mytable2;

3.12. 改

1
2
3
UPDATE mytable
SET col = val
WHERE id = 1;

3.13. DISTINCT

相同值只会出现一次。它作用于所有列,也就是说所有列的值都相同才算相同。

1
2
3
SELECT DISTINCT col1, col2
FROM mytable;
LIMIT

3.14. LIMIT

限制返回的行数。可以有两个参数,第一个参数为起始行,从 0 开始;第二个参数为返回的总行数。

返回前 5 行:

1
2
3
4
5
6
7
8
SELECT *
FROM mytable
LIMIT 5;
-- 返回前5行
LIMIT 0, 5;
-- 返回前5行
LIMIT 2, 3;
-- 返回第 3 ~ 5 行

3.15. ORDER BY排序

ASC :升序(默认)
DESC :降序
可以按多个列进行排序,并且为每个列指定不同的排序方式:

1
2
3
SELECT *
FROM mytable
ORDER BY col1 DESC, col2 ASC;

3.16. WHERE过滤

不进行过滤的数据非常大,导致通过网络传输了多余的数据,从而浪费了网络带宽。因此尽量使用 SQL 语句来过滤不必要的数据,而不是传输所有的数据到客户端中然后由客户端进行过滤。

1
2
3
SELECT *
FROM mytable
WHERE col IS NULL;

下表显示了 WHERE 子句可用的操作符

操作符 说明
= 等于
< 小于

大于
<> != 不等于
<= !> 小于等于
= !< 大于等于
BETWEEN 在两个值之间
IS NULL 为 NULL 值
应该注意到,NULL 与 0、空字符串都不同。

AND 和 OR 用于连接多个过滤条件。优先处理 AND,当一个过滤表达式涉及到多个 AND 和 OR 时,可以使用 () 来决定优先级,使得优先级关系更清晰。

IN 操作符用于匹配一组值,其后也可以接一个 SELECT 子句,从而匹配子查询得到的一组值。

NOT 操作符用于否定一个条件。

3.17. 通配符

通配符也是用在过滤语句中,但它只能用于文本字段。

% 匹配 >=0 个任意字符;

_ 匹配 ==1 个任意字符;

[ ] 可以匹配集合内的字符,例如 [ab] 将匹配字符 a 或者 b。用脱字符 ^ 可以对其进行否定,也就是不匹配集合内的字符。

使用 Like 来进行通配符匹配。

1
2
3
SELECT *
FROM mytable
WHERE col LIKE '[^AB]%'; -- 不以 A 和 B 开头的任意文本

不要滥用通配符,通配符位于开头处匹配会非常慢。

3.18. 计算字段

在数据库服务器上完成数据的转换和格式化的工作往往比客户端上快得多,并且转换和格式化后的数据量更少的话可以减少网络通信量。

计算字段通常需要使用 AS 来取别名,否则输出的时候字段名为计算表达式。

1
2
SELECT col1 * col2 AS alias
FROM mytable;
1
2
3
4
SELECT CONCAT(TRIM(col1), '(', TRIM(col2), ')') AS concat_col
FROM mytable;
-- CONCAT() 用于连接两个字段。
-- TRIM() 可以去除首尾空格。许多数据库会使用空格把值填充为列宽,因此连接的结果会出现一些不必要的空格。

3.19. 函数

各个 DBMS 的函数都是不相同的,因此不可移植,以下主要是 MySQL 的函数。

汇总
函 数 说 明
AVG() 返回某列的平均值
COUNT() 返回某列的行数
MAX() 返回某列的最大值
MIN() 返回某列的最小值
SUM() 返回某列值之和
AVG() 会忽略 NULL 行。

使用 DISTINCT 可以汇总不同的值。

1
2
SELECT AVG(DISTINCT col1) AS avg_col
FROM mytable;

文本处理
函数 说明
LEFT() 左边的字符
RIGHT() 右边的字符
LOWER() 转换为小写字符
UPPER() 转换为大写字符
LTRIM() 去除左边的空格
RTRIM() 去除右边的空格
LENGTH() 长度
SOUNDEX() 转换为语音值
其中, SOUNDEX() 可以将一个字符串转换为描述其语音表示的字母数字模式。

1
2
3
SELECT *
FROM mytable
WHERE SOUNDEX(col1) = SOUNDEX('apple')

日期和时间处理
日期格式:YYYY-MM-DD
时间格式:HH:MM:SS
函 数 说 明
ADDDATE() 增加一个日期(天、周等)
ADDTIME() 增加一个时间(时、分等)
CURDATE() 返回当前日期
CURTIME() 返回当前时间
DATE() 返回日期时间的日期部分
DATEDIFF() 计算两个日期之差
DATE_ADD() 高度灵活的日期运算函数
DATE_FORMAT() 返回一个格式化的日期或时间串
DAY() 返回一个日期的天数部分
DAYOFWEEK() 对于一个日期,返回对应的星期几
HOUR() 返回一个时间的小时部分
MINUTE() 返回一个时间的分钟部分
MONTH() 返回一个日期的月份部分
NOW() 返回当前日期和时间
SECOND() 返回一个时间的秒部分
TIME() 返回一个日期时间的时间部分
YEAR() 返回一个日期的年份部分
mysql> SELECT NOW();
2018-4-14 20:25:11
数值处理
函数 说明
SIN() 正弦
COS() 余弦
TAN() 正切
ABS() 绝对值
SQRT() 平方根
MOD() 余数
EXP() 指数
PI() 圆周率
RAND() 随机数

3.20. 分组GROUP BY

把具有相同的数据值的行放在同一组中。

可以对同一分组数据使用汇总函数进行处理,例如求分组数据的平均值等。

指定的分组字段除了能按该字段进行分组,也会自动按该字段进行排序。

1
2
3
SELECT col, COUNT(*) AS num
FROM mytable
GROUP BY col;

GROUP BY 自动按分组字段进行排序,ORDER BY 也可以按汇总字段来进行排序。

1
2
3
4
SELECT col, COUNT(*) AS num
FROM mytable
GROUP BY col
ORDER BY num;

WHERE 过滤行,HAVING 过滤分组,行过滤应当先于分组过滤。

1
2
3
4
5
SELECT col, COUNT(*) AS num
FROM mytable
WHERE col > 2
GROUP BY col
HAVING num >= 2;

分组规定:

GROUP BY 子句出现在 WHERE 子句之后,ORDER BY 子句之前;
除了汇总字段外,SELECT 语句中的每一字段都必须在 GROUP BY 子句中给出;
NULL 的行会单独分为一组;
大多数 SQL 实现不支持 GROUP BY 列具有可变长度的数据类型。

3.21. 子查询

子查询中只能返回一个字段的数据。

可以将子查询的结果作为 WHRER 语句的过滤条件:

1
2
3
4
SELECT *
FROM mytable1
WHERE col1 IN (SELECT col2
FROM mytable2);

下面的语句可以检索出客户的订单数量,子查询语句会对第一个查询检索出的每个客户执行一次:

1
2
3
4
5
6
SELECT cust_name, (SELECT COUNT(*)
FROM Orders
WHERE Orders.cust_id = Customers.cust_id)
AS orders_num
FROM Customers
ORDER BY cust_name;

3.22. 连接

连接用于连接多个表,使用 JOIN 关键字,并且条件语句使用 ON 而不是 WHERE。

连接可以替换子查询,并且比子查询的效率一般会更快。

可以用 AS 给列名、计算字段和表名取别名,给表名取别名是为了简化 SQL 语句以及连接相同表。

内连接
内连接又称等值连接,使用 INNER JOIN 关键字。

1
2
3
SELECT A.value, B.value
FROM tablea AS A INNER JOIN tableb AS B
ON A.key = B.key;

可以不明确使用 INNER JOIN,而使用普通查询并在 WHERE 中将两个表中要连接的列用等值方法连接起来。

1
2
3
SELECT A.value, B.value
FROM tablea AS A, tableb AS B
WHERE A.key = B.key;

自连接
自连接可以看成内连接的一种,只是连接的表是自身而已。

一张员工表,包含员工姓名和员工所属部门,要找出与 Jim 处在同一部门的所有员工姓名。

子查询版本

1
2
3
4
5
6
SELECT name
FROM employee
WHERE department = (
SELECT department
FROM employee
WHERE name = "Jim");

自连接版本

1
2
3
4
SELECT e1.name
FROM employee AS e1 INNER JOIN employee AS e2
ON e1.department = e2.department
AND e2.name = "Jim";

自然连接
自然连接是把同名列通过等值测试连接起来的,同名列可以有多个。

内连接和自然连接的区别:内连接提供连接的列,而自然连接自动连接所有同名列。

1
2
SELECT A.value, B.value
FROM tablea AS A NATURAL JOIN tableb AS B;

外连接
外连接保留了没有关联的那些行。分为左外连接,右外连接以及全外连接,左外连接就是保留左表没有关联的行。

检索所有顾客的订单信息,包括还没有订单信息的顾客。

1
2
3
SELECT Customers.cust_id, Orders.order_num
FROM Customers LEFT OUTER JOIN Orders
ON Customers.cust_id = Orders.cust_id;

customers 表:

cust_id cust_name
1 a
2 b
3 c
orders 表:

order_id cust_id
1 1
2 1
3 3
4 3
结果:

cust_id cust_name order_id
1 a 1
1 a 2
3 c 3
3 c 4
2 b Null

3.23. 组合查询

使用 UNION 来组合两个查询,如果第一个查询返回 M 行,第二个查询返回 N 行,那么组合查询的结果一般为 M+N 行。

每个查询必须包含相同的列、表达式和聚集函数。

默认会去除相同行,如果需要保留相同行,使用 UNION ALL。

只能包含一个 ORDER BY 子句,并且必须位于语句的最后。

1
2
3
4
5
6
7
SELECT col
FROM mytable
WHERE col = 1
UNION
SELECT col
FROM mytable
WHERE col =2;

3.24. 视图

视图是虚拟的表,本身不包含数据,也就不能对其进行索引操作。

对视图的操作和对普通表的操作一样。

视图具有如下好处:

简化复杂的 SQL 操作,比如复杂的连接;
只使用实际表的一部分数据;
通过只给用户访问视图的权限,保证数据的安全性;
更改数据格式和表示。

1
2
3
4
CREATE VIEW myview AS
SELECT Concat(col1, col2) AS concat_col, col3*col4 AS compute_col
FROM mytable
WHERE col5 = val;

3.25. 存储过程

存储过程可以看成是对一系列 SQL 操作的批处理。

使用存储过程的好处:

代码封装,保证了一定的安全性;
代码复用;
由于是预先编译,因此具有很高的性能。
命令行中创建存储过程需要自定义分隔符,因为命令行是以 ; 为结束符,而存储过程中也包含了分号,因此会错误把这部分分号当成是结束符,造成语法错误。

包含 in、out 和 inout 三种参数。

给变量赋值都需要用 select into 语句。

每次只能给一个变量赋值,不支持集合的操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
delimiter //

create procedure myprocedure( out ret int )
begin
declare y int;
select sum(col1)
from mytable
into y;
select y*y into ret;
end //

delimiter ;
call myprocedure(@ret);
select @ret;

3.26. 游标

在存储过程中使用游标可以对一个结果集进行移动遍历。

游标主要用于交互式应用,其中用户需要对数据集中的任意行进行浏览和修改。

使用游标的四个步骤:

声明游标,这个过程没有实际检索出数据;
打开游标;
取出数据;
关闭游标;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
delimiter //
create procedure myprocedure(out ret int)
begin
declare done boolean default 0;

declare mycursor cursor for
select col1 from mytable;
# 定义了一个 continue handler,当 sqlstate '02000' 这个条件出现时,会执行 set done = 1
declare continue handler for sqlstate '02000' set done = 1;

open mycursor;

repeat
fetch mycursor into ret;
select ret;
until done end repeat;

close mycursor;
end //
delimiter ;

3.27. 触发器

触发器会在某个表执行以下语句时而自动执行:DELETE、INSERT、UPDATE。

触发器必须指定在语句执行之前还是之后自动执行,之前执行使用 BEFORE 关键字,之后执行使用 AFTER 关键字。BEFORE 用于数据验证和净化,AFTER 用于审计跟踪,将修改记录到另外一张表中。

INSERT 触发器包含一个名为 NEW 的虚拟表。

1
2
3
4
CREATE TRIGGER mytrigger AFTER INSERT ON mytable
FOR EACH ROW SELECT NEW.col into @result;

SELECT @result; -- 获取结果

DELETE 触发器包含一个名为 OLD 的虚拟表,并且是只读的。

UPDATE 触发器包含一个名为 NEW 和一个名为 OLD 的虚拟表,其中 NEW 是可以被修改的,而 OLD 是只读的。

MySQL 不允许在触发器中使用 CALL 语句,也就是不能调用存储过程。

3.28. 事务管理

基本术语:

事务(transaction)指一组 SQL 语句;
回退(rollback)指撤销指定 SQL 语句的过程;
提交(commit)指将未存储的 SQL 语句结果写入数据库表;
保留点(savepoint)指事务处理中设置的临时占位符(placeholder),你可以对它发布回退(与回退整个事务处理不同)。
不能回退 SELECT 语句,回退 SELECT 语句也没意义;也不能回退 CREATE 和 DROP 语句。

MySQL 的事务提交默认是隐式提交,每执行一条语句就把这条语句当成一个事务然后进行提交。当出现 START TRANSACTION 语句时,会关闭隐式提交;当 COMMIT 或 ROLLBACK 语句执行后,事务会自动关闭,重新恢复隐式提交。

设置 autocommit 为 0 可以取消自动提交;autocommit 标记是针对每个连接而不是针对服务器的。

如果没有设置保留点,ROLLBACK 会回退到 START TRANSACTION 语句处;如果设置了保留点,并且在 ROLLBACK 中指定该保留点,则会回退到该保留点。

1
2
3
4
5
6
7
START TRANSACTION
// ...
SAVEPOINT delete1
// ...
ROLLBACK TO delete1
// ...
COMMIT

3.29. 字符集

基本术语:

字符集为字母和符号的集合;
编码为某个字符集成员的内部表示;
校对字符指定如何比较,主要用于排序和分组。
除了给表指定字符集和校对外,也可以给列指定:

1
2
3
CREATE TABLE mytable
(col VARCHAR(10) CHARACTER SET latin COLLATE latin1_general_ci )
DEFAULT CHARACTER SET hebrew COLLATE hebrew_general_ci;

可以在排序、分组时指定校对:

1
2
3
SELECT *
FROM mytable
ORDER BY col COLLATE latin1_general_ci;

3.30. 权限管理

MySQL 的账户信息保存在 mysql 这个数据库中。

1
2
USE mysql;
SELECT user FROM user;

3.30.1. 创建账户

新创建的账户没有任何权限。

1
CREATE USER myuser IDENTIFIED BY 'mypassword';

3.30.2. 修改账户名

1
RENAME USER myuser TO newuser;

3.30.3. 删除账户

1
DROP USER myuser;

3.30.4. 查看权限

1
SHOW GRANTS FOR myuser;

3.30.5. 授予权限

账户用 username@host 的形式定义,username@% 使用的是默认主机名。

1
GRANT SELECT, INSERT ON mydatabase.* TO myuser;

3.30.6. 删除权限

GRANT 和 REVOKE 可在几个层次上控制访问权限:

整个服务器,使用 GRANT ALL 和 REVOKE ALL;
整个数据库,使用 ON database.
特定的表,使用 ON database.table;
特定的列;
特定的存储过程。
REVOKE SELECT, INSERT ON mydatabase.
FROM myuser;

3.30.7. 更改密码

必须使用 Password() 函数进行加密。

1
SET PASSWROD FOR myuser = Password('new_password');

4. 牛客

常见的sql优化技巧,不正确的是?_乐信笔试题|c5c977fbc9e0453486e244c5a88a8678
关于SQL优化,哪些是正确的?_唯品会笔试题|be873ae5acd448b18a5045677c87c84c

写出下面2个PHP操作Mysql函数的作用及区别。_微博笔试题|db95632130dc414e9af675444b04ce87

现有Mysql数据库,写Spring + Hibernate_|7633c7c52a8447fda1d76e83d77070aa
mysql数据库,game_order表表结构如下,下面哪些|7d2af51194e14e708c71c855f5f28a36
Linux下MySQL数据库安装方式分为[$##$]、[$#_搜狐畅游笔试题|0b2b724678fc408f959e5469a05517d2
PHP只能跟MySQL数据库进行联合编程说法是否正确()
|33b69ee0d53d4bda8cb28ab8129e117d
在配置APP连接MySQL数据库的时候,字符串“搜狐畅游笔试题|38b46989ee664be2a91fe0464da47c1d
MySQL数据库提供了四种级别的事务隔离,其中默认的隔离级别_搜狐畅游笔试题|4bd14ee6743841e29d5c899a00ccdf93
PHP只能跟MySQL数据库进行联合编程说法是否正确()
|7856c6be6c8c41b4826bcc6ea70ce334
MySQL数据库中可使用()语句增加新用户并限制用户访问数据|827ef567d596425e98ff86cf28ad4b9b
MySQL数据库查询操作中可使用()子句指定查询结果的排序规
|98c2182584e0499db2dd2c3e0e7241fd
如下哪些日志可以记录到MySQL数据库的所有更新操作_搜狐畅游笔试题|a2ce8dcfcc57434bb16b4e9e0ad75701
假设MySQL数据库_搜狗笔试题|aeff9b71bc4f45b3987a82fab508e852

Mysql查询时,只有满足联接条件的记录才包含在查询结果,这第四范式笔试题|6a383d264d1c42029b7d3ffd3fc7bdcd
Mysql查询时,只有满足联接条件的记录才包含在查询结果,这摩拜笔试题|ec152f2aa7ce485cb1e9772dfef2b307
在SQL查询时,如果需要去掉查询结果中的重复组,应使用___
|0ff9a20f04a4458eb108af559782bd78
在SQL查询时,使用WHERE子句指出的
|2af4e50a36894d9f8e4ffadfb5ecbd6a
PDO通过执行SQL查询与数据库进行交互,可以分为多种不同的|86cdf39c251149c3ba207219391e76c8
在SQL查询中使用WHERE子句指出的是()。
|9a65de6327df4a4288acc151d4e01a2b
SQL查询语句中where、group by、having 摩拜笔试题|cd7d70aea97b450593f1263defe18a92
哪种不是SQL查询的联接算法_招商银行信用卡中心笔试题|d7e33038eea04c88bd34ff6d49a4f108
在SQL查询时,如果需要去掉查询结果中的重复组,应使用( )
|d93cdbf234094c619a9259f776817dd5

Mysql sql注入中使用延时注入时常用的语句是()|04139bac8c024c0a970add8504e5e028
Mysql sql注入中使用延时注入时常用的语句是()_小米笔试题|1f9d81d3747a43af9ff952584bce3010
分类列举sql注入常用判断方法?
|c3593d010fa745c88c84a830bfbe7cd8

使用sql语句查询class列不是NULL的记录,WHERE_快手笔试题|a3140cd056dd4262a539f73396e28765
写出以下sql语句。网易笔试题|a9889965d6fd40aebe8f1865b965f072
写出符合条件的sql语句。_腾讯笔试题|bcd7133020df49eeab0c656718a876d7
在SQL语句中,与表达式"仓库号 NOT_搜狐畅游笔试题|254487b011c64320abeced5d56239201
已知表T1中有2行数据,T2中有3行数据,执行SQL语句,&_摩拜笔试题|2a35d7a4d6b24d43a3b32a27ef92418c
SQL语句执行的顺序是_网易笔试题|2bee77aff9c94b2dae43e493cf3df319
下述SQL语句中,起修改表中数据作用的命令动词是()
|2e2ddd5123794a8aa27a18f64484dd88
对于满足SQL92标准的SQL语句:SELECT foo,c_招商银行信用卡中心笔试题|2f0a9189f17847a5af6f17dd7ab62b59
下面关于SQL语句”SELECT * F_搜狐畅游笔试题|487036093b2248138a1bd57c4e56682c
 SQL语句性能分析的关键字是什么?腾讯笔试题|5d5b782a1a484af4ac3ab07e437d468f
ADO.net访问SQL server数据库时,在SQL语句
|5f2c5766357c4d48988d319288f74dc7
在SQL语句中,用“%”表示任何一个字符 ,这种说法正确吗(|6243c96f1d034d8cb12033e1b8aab0f9
下列哪一个Transact-SQL语句能够实现收回user2
|6300f4878d83446db352c9fb46641841
SQL语句中,删除一个表的命令是()。猿辅导笔试题|6b1b19602fbe423b82b59d87c7cdfd79
SQL语句中,可以查看到学生信息表中,学生姓名的SQL语句为_小米笔试题|6fdd1a3594824233aaee3e2909ac5dfb
对于满足SQL92标准的SQL语句:SELECT foo,c_腾讯笔试题|7abd397a22054bbb99e2b3982ff81d01
下列SQL语句中,修改表结构的是()
|7f5a506326c944ef95f6b9b62bd44708
对于SQL语句select * from t where a_网易笔试题|a9755786616e4049aa3d3041f3a99c41
下列SQL语句可以将查询结果降序排列的是|b07884418c3448fd8e91b097eca8a259
为何SQL语句需要使用大写字母?
|b6b2ce1ae18c48a99047e61a70592a67
用SQL语句建立表时将属性定义为主关键字,应使用短语( )第四范式笔试题|ba8e4dfd1d3f4b1bbc0bd74f727195ad
SQL语句中与Having子句同时使用的语句是?()_顺丰科技笔试题|d35fee69aefa4ff6af06fe4a74706db7
下列两条SQL语句的检索结果为何不同?_华为笔试题|d3980009a1094d2a88fc4270820a665b
使用Transact-SQL语句拒绝user4查询视图MyV
|ddcbfe05f1d0477c9a56d7124759c2f0

以下hive sql语法正确的是网易笔试题|185a862dc74e42d49f6937e3cd4fef42
关于isql语法分析器的常用参数,下面说法正确的有:(&nb
|7895f6e3d3d94dd09b606f2db01ba615
以下hive sql语法正确的是_网易笔试题|f4476d751a4c41e6ba27730163641faa
增加数据库一列的SQL语法是什么?_人人网笔试题|91f0508367e34d318bcca2786823dccf

SQL语言具有的功能是 ( )|047aec571bea474896313c3e7689848e
在SQL语言中授权的操作是通过___语句实现的。
|0b73d04ce6e6491d848a950ee6539eec
在SQL语言的SELECT语句中,能实现选择操作的是:|1301822371f94a818a44012ad07775cf
SQL语言是()的语言,易学习。
|18414cc2a1cf4207a43c14980b4468e0
SQL语言中,用于授权的语句是()。 <div>|18d8039d8cd84276b7121129d13a3f76
在SQL语言中,子查询是</span>
|217ddfe703754efb909d747bbc378151
SQL语言的功能包括()、()、()、()。|58d3e034df4748fdbdd99672a65e0a28
在SQL语言的SELECT查询中,需要去掉查询结果中的重复记
|6b5dc36d8553441382647b2683262ff3
SQL语言的关键字包括SELECT、INSERT、UPDAT_百度笔试题|6d7c074de2644e118845dacebd95a042
在SQL语言的Select语句中实现选择运算的子句是( )。|6fa9dbb6f740449e8d7334a8680d782a
标准SQL语言集数据查询、数据操作、数据定义和数据控制功能于
|7697bc2262e444aabf3dce7ab4e0ecf7
SQL语言具有( )的功能。|a3c2b0afb9134f06bfc62b4c8e3118ec
SQL语言集数据查询、数据操纵、数据定义和数据控制功能于一体
|a6ceec080b7948359a0375efa7ea879e
标准SQL语言集数据查询、数据操作、数据定义和数据控制功能于|a8522e7b766c445596ebfb72bf31836a
SQL语言允许使用通配符进行字符串匹配的操作,其中&lsqu_摩拜笔试题|aca0f342bb9e46c7ae576e90f94db787
SQL语言中删除一个表的指令是_快手笔试题|b15436e05f354461af026c66f209a2a6
SQL语言共分为三大类(亦有说法分为四大类),那么不属于数据_顺丰科技笔试题|b2ff34be83de4dc4a81f3902c25ef9f5
在SQL语言的SELECT语句中,对应关系代数中“投影”运算
|b962888aa0644610bd05c3366aec5ee7
在数据库的SQL语言开发中,下述关于Union和Union&_唯品会笔试题|bd4453be5de94445916bae4aa8965666
SQL语言集数据查询、数据操纵、数据定义和数据控制功能于一体_腾讯笔试题|ccecce1c5f1a48b99302dfc58b2c4c66
在SQL语言中,子查询是(  &nbsp_摩拜笔试题|e849c014eeb5449fb4c45578ec3cd2ab
 SQL语言中删除一个表的指令是()_腾讯笔试题|efb2f754ab9a4601a7dd9fb184809983

使用SQLServer数据库系统时如何减少事务的死锁招商银行信用卡中心笔试题|9f9ca757f11d489ebe4af3847f507135
1 [问答]简单介绍SQLite数据库。
|91a9a0a75013423788e1acd8a25c7490

mysql主从复制?_|85b17fb014eb46ffb653465681af1775

现有Mysql数据库,写Spring + Hibernate_|7633c7c52a8447fda1d76e83d77070aa
Linux下MySQL数据库安装方式分为[$##$]、[$#搜狐畅游笔试题|0b2b724678fc408f959e5469a05517d2
PHP只能跟MySQL数据库进行联合编程说法是否正确()
|33b69ee0d53d4bda8cb28ab8129e117d
在配置APP连接MySQL数据库的时候,字符串“搜狐畅游笔试题|38b46989ee664be2a91fe0464da47c1d
MySQL数据库提供了四种级别的事务隔离,其中默认的隔离级别_搜狐畅游笔试题|4bd14ee6743841e29d5c899a00ccdf93
PHP只能跟MySQL数据库进行联合编程说法是否正确()
|7856c6be6c8c41b4826bcc6ea70ce334
MySQL数据库中可使用()语句增加新用户并限制用户访问数据|827ef567d596425e98ff86cf28ad4b9b
MySQL数据库查询操作中可使用()子句指定查询结果的排序规
|98c2182584e0499db2dd2c3e0e7241fd
如下哪些日志可以记录到MySQL数据库的所有更新操作搜狐畅游笔试题|a2ce8dcfcc57434bb16b4e9e0ad75701
假设MySQL数据库_搜狗笔试题|aeff9b71bc4f45b3987a82fab508e852
mysql数据库,game_order表表结构如下,下面哪些
|7d2af51194e14e708c71c855f5f28a36

git

沙盒:https://learngitbranching.js.org/?NODEMO

  • undo、reset 修正错误,不记入步数。
  • objective 打开任务对话框
  • levels 选择关卡
  • show solution 查看本关答案
    todo
  • 命令有哪些?对应的关卡是?
  • 各个命令接的参数是什么
  • 分支、head、星号、节点各有什么变化
  • 哪些命令能移动分支
  • 哪些命令能移动节点
  • 移动整个分支还是部分节点
  • 谁从哪移到哪
  • 哪些命令能创建分支
  • 哪些命令会创建commit
  • 哪些命令会移动星号
  • 哪些命令会改变HEAD默认位置
    尚不熟练的关卡:

    Read More

GitHub

github学习笔记。

  1. 专注于完成现有的功能比完成新的开始更有价值。(一个善终强于无数个善始)

  2. 不要直接提交给主分支。 有太多的分支,先集中解决其中一两个。

  3. 修故障,开新分支。添加新功能,开新分支。

  4. 好的经验法则,每个5~10分支提交一次。

  5. 提交信息:在做什么(向人展示你的工作),为什么做,为啥要采用你的提交。(description and detailed description)

  6. WYSIWYG:所见即所得。WY死机。

    Read More