python代码简洁,拥有高级数据结构,能够以简单高效的方式执行面向对象编程,但是它的运行效率受人诟病,所以python经常作为一种“胶水语言”,把耗时的核心部分使用C/C++等效率更高的语言编写,然后再由python粘和。事实上,在大多数数据任务上,python的运行效率已经可以媲美C/C++.
在大数据深入人心的时代,网络数据采集作为网络、数据库、和机器学习等领域的交汇点,成为满足个性化网络数据需求的最佳实践。网络数据采集技术可以进一步精炼数据,把网络上杂乱无章的的数据聚合成规范的形式,方便分析和挖掘。
工作中经常会遇到各种数据,比如几百页的数据,或者在数据杂乱无章的网站中充满着带有陷阱的表单和坑爹的验证码,甚至需要的数据保存在网页版的PDF和网络图片中。你需要了解常用的数据采集手段和网络表单安全措施。
网络数据采集可以使用多种语言,比如:python, java ,php, C#, Go都可以。Python拥有简洁轻松的语法,开箱可用的模块,强大快乐的社区,总可以快速构建出简单高效的解决方案。
网络数据采集是涉及多个领域的:
Python数据采集的模块有:urllib, BeautifulSoup, lxml, Scrapy, PdfMiner, Requests, Selenium, NLTK, Pillow, unittest,Pysocks等
还有一些知名网站的API,MySQL数据库,OpenRefine数据分析工具,PhanthomJS无头浏览器以及Tor代理服务器等内容。
1 | 如果需要了解python多进程(multiprocessing),并发(concurrency),集群(cluster)等高性能和多核编程,可以移步python高性能、多核编程、设计模式的书籍。 |
进行网络数据采集时,要控制网络数据采集的速度,降低被采集网站服务器的负担。
什么是网络数据采集
网络数据采集也称 网页抓屏(screen scraping),数据挖掘(data mining), 网络收割(Web harvesting),或者网络机器人(bots)。
网络数据采集是通过多种手段收集网络数据的方式,涉及数据库,网络服务器,HTTP协议,HTML语言,网络安全,图像处理,数据科学等。
网络数据采集不光是通过与API交互(或者与浏览器进行交互)的方式,还需要处理js,多媒体和cookie的新式网站。最常用的方法是写一个自动化程序向网络服务器请求数据(通常是HTML表单或其他网页文件),然后对数据进行解析,提取需要的信息。
网络数据挖掘流程:采集数据 -> 数据清洗 ->挖掘模型构建 -> 归类展示(可视化)
数据采集的可视化; 爬取数据 ->存入数据库 ->调用数据库将数据可视化
网络爬虫可以完成传统搜索引擎不能做的事情,搜索引擎不能填写表单,比如爬取大量网站的数据查询出航班价格随时间变化的图表,爬虫可以一次可以成千上百万个网页。
存在各种API(Twitter或者维基百科的API),可以向用户提供服务器中格式完好的数据,而且一个API提供了不同的数据类型,在某些时候API是比爬虫获取数据更加方便。但是在:
- 你收集的数据来自不同的网站,没有一个API能够综合多个网站的数据。
- 你采取的数据非常小众,网站不会为你单独做一个api
- 一些网站没有基础设施或者技术能力去建API
- 即使API存在,有时候还会有请求内容和次数限制,API提供的数据类型或者数据格式也可能无法满足需求
大多数的应用场景都会用到这样毫无阻碍获取数据的手段:市场预测,机器语言翻译,甚至医疗诊断领域,通过对新闻网站、文章以及健康论坛中的数据进行采集和分析,也可以获取很多好处。无论处于哪个领域,网络数据采集都会让你的工作更加高效,提升生产力,甚至开创一个全新的领域。
初见网络爬虫
基本原理:如何利用Python从服务器请求信息,如何对服务器的响应进行基本处理,如何利用自动化手段与网站进行交互。最终你将创建出具有域名切换、信息收集、信息存储功能的爬虫。
爬虫的基本想法:
- 通过域名获取网站HTML数据
- 根据目标信息解析数据
- 存储目标信息
- 如果需求,移动到下一个页面重复这个过程
网络连接
get,post请求的区别
HTTP从网络服务获取信息有4种方式:
- GET: 一般指在浏览器中输入url(不含参数),服务器返回信息的方式
- POST:当你填写表单或者提交信息到网络服务器后端程序时使用。比如:你登录网站时,就是通过用户名和密码(有可能通过加密)发起一个POST请求。
- PUT: 在网站交互的过程中不常用,在API请求有时使用。PUT请求用来更新一个对象或信息。比如:更新一个老用户的邮箱。现在好多API更新信息都使用POST替代PUT,这取决与API请求本身是如何构建的。
- DELETE:用于删除一个对象。比如我们向
http://myapi.com/user/23
发起一个DELETE请求,就会删除ID号是23的用户。DELETE在公用API不常用,不能随便让一个用户删除数据库的信息。
SSL和SSH
++SSH外链++
SSH:安全外壳协议(SSH)是一种在不安全网络上提供安全远程登录及其它安全网络服务的协议。Secure Shell,又可记为SSH
++SSL外链++
++SSL外链2++
OpenSSL 是一个强大的安全套接字层密码库,Apache 使用它加密 HTTPS,OpenSSH 使用它加密SSH,但是,你不应该只将其作为一个库来使用,它还是一个多用途的、跨平台的密码工具。
多多使用知乎,google,百度是个坑
http 和 https 有何区别?如何灵活使用?
关于url中# #! ? &
的作用:
#
代表锚点,可以跳转到页面指定的位置,#
后面的内容称为hashtag, hashtag多用于AJAX请求获取数据。
如果进行url请求,修改#
后面的内容,浏览器不会向服务器重新加载index.html,既不会重新加载,但是会在浏览器中增加一条历史记录。window.location.hash
读取hashtag,这是一个可读可写的变量,用于判断网页状态是否改变,增加一条访问记录。
AJAX = JAVASCRIPT + XML
AJAX是一种用于创建快速动态网页的技术。
?
在url中有两种作用:
- 连接作用,连接网址和参数,比如:
http://www.baidu.com/?userid=walkk&password=123456
- 清楚缓存: index.html?test123123,表示不调用缓存,认为是新地址重新加载。
&
就是上文中的,间隔参数的作用
GET方法向服务器请求数据的过程
- A电脑发送一串0、1的比特值,这些比特构成了一种信息,包括请求头和消息体。请求头包括了A本地路由的MAC地址和服务器B的IP地址,消息体包含了A对B服务器的请求内容。
- A的路由器收到所有0、1比特值,把它理解成一个数据包(package),从A的MAC地址寄到B的IP的地址,A的路由器将数据包加上自己的IP地址作为“发件地址”,然后通过互联网发出去
- A的数据包经过了一些中介服务器,沿着正确的物理/电路路径前进,到达了B的服务器
- B的服务器收取到数据包,解析请求头里面的目标端口(通常是网络应用的80端口,IP地址相当于街道地址,端口相当于房间号),把数据包传到网络服务器对应的应用上。
- 服务器应用从服务器处理器器收到一串数据,
- 这是一个GET请求
- 请求文件Indx.html
- 网络服务器应用找到对应的HTML文件,把它打成数据包,通过本地的路由器回传到B服务器上。
BeautifulSoup
使用urlopen()获取HTML数据,然后把HTML数据传到BeautifulSoup对象,转换成(树型的类似XML结构)下面的结构:
1 | **html** -> <html><head>.....</head><body></body></html> |
1 | from urllib.request import urlopen |
网络数据采集添加 异常处理 (Important)
网络数据采集会遇到:网页数据格式不友好,网站服务器怠机,目标数据的标签找不到等等问题,添加异常处理try….. except防止程序奔溃,死循环,增加健壮性。
html = ulropen("www.jianshu.com")
就像请求数据会出现两种异常:
- 目标网页在服务器上不存在(或获取页面的过程中出错)
- 服务器不存在
第一种异常发 生, 会返回HTTP错误,比如404 Page Not Found, 500 Internal Server Error
,所有类似的异常,urlopen都会返回HTTPError
1 | try: |
第二种情况,服务器不存在(url不存在或者写错了),urlopen会返回一个None对象
1 | if html is None: # 注意是urlopen返回的None对象 |
如果调用Beautiful对象标签,增加一个判断条件判断标签是否存在,不存在返回None对象。但是如果继续访问None对象下面的子标签就会返回一个AttributeError
如何对这两种情形做出检查:
1 | try: |
写爬虫的时候,思考代码总体格局大专栏 python网络数据采集1ong>,既容易捕捉异常,又方便阅读。
为了重用代码:多写getSiteHtml(),和getTitle()这种通用函数(具有周密的异常处理功能,修改函数内容别人就可以调用),进行快速稳定的网络采集。
复杂HTML解析 + 使用爬虫的几种方式
解决复杂HTML页面需要考虑的问题:
- 寻找是否有HTML页面样式更加友好的移动版
- 寻找隐藏在JS中的内容
- URL链接有时候能直接提取出title标题
- 寻求多个数据源看是否有相同数据
在面对埋藏很深或格式不友好的数据,千万不要不经过思考就写代码。
添加异常捕获
1 | from urllib.request import urlopen |
BeautifulSoup
BeautifulSoup有四个对象:
Tag(标签里面有name,attrs)
获取标签name, attrs[]
bsobj.p.name bsobj.p.attrs[]
单独获得某个属性值 :bsobj.a['href'] bsobj.a.get('href')
BeautifulSoup对象(bsobj)
bsobj = BeautifulSoup(html)
NavigableString
(标签中的文字比如<p>
标签中的文字</p>
)p.string
就可以获得标签中的文字
Comment 获得html的注释内容 <!--注释-->
<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>
利用 .string 来输出它的内容,它已经把注释符号去掉了,我们获取其中内容需要做一下判断:if type(soup.a.string)==bs4.element.Comment:
print soup.a.string
具体使用方法
bsobj.h1 bsobj.a bsobj.p
查找的是在所有内容中的第一个符合要求的标签bsobj.find() 和bsobj.findall() 方法
find()和findAll(),都有过滤标签作用,最后返回的一个标签列表,就像<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>
完整的标签
由于返回的是一个列表,要想得到其中内容1.使用for 循环遍历列表2.使用get_text()方法去除html的标签
nameList = bsobj.findAll(“span”,{“class”:{“red”,”blue”}})
for content in nameList:
content.get_text()
1 |
|
find(tag, attributes, recursive, text, limit, keywords)少了limit属性,基本使用方法相同
导航树
++参考外链++
其实就是使用文档结构获取:
tr是table标签的子标签, children
tr,th,td,img,span是table标签的后代标签 descendants
1 | for child in bsobj.findAll("table",{"id":"giftshit"}).children(): |
正则和BeautifulSoup的结合
1 | import re |
使用lambda函数替代正则
Beautiful允许我们把lambda函数作为findAll()的参数,限制条件是:
- 必须把一个标签作为参数
- 返回结果是bool形式
1 | bsobj.findAll(lambda tag: len(tag.attrs == 2)) |
关于python的html解析库:
- BeautifulSoup不用介绍了
- lxml,这个库可以用来解析Html和XML文档,大部分源码用C实现,以非常底层的实现而闻名。虽然学习需要花一些时间,但在处理大多数HTML文档速度都比较快。
- HTML parser 这是Python自带的解析库