Python爬虫的入门与进阶

mark
mark

书籍推荐:

《python核心编程》/《python语言及其应用》->《python cookbook》

《用Python写网络爬虫》

python/爬虫实践文章

https://juejin.im/post/58dce2248d6d8100613a4cfb

https://zhuanlan.zhihu.com/p/21479334

https://zhuanlan.zhihu.com/p/25633789

https://xlzd.me/tag/crawler/

http://dongweiming.github.io/Expert-Python/#1

学习建议

熟悉了python语法之后,写了一两个就入门了。网上有很多爬虫的文章,但是一定要自己动手去写

初级文章读一百篇和读一两篇是一样的,除了浪费时间以外。

另外,初学者没必要一上来就做很大很有成就感的事情,可以先写个简单的,然后不断给自己正向反馈。

比如可以先只是将数据在终端打印出来,然后再渐渐将数据规整化了以后保存到本地的数据库或者文件里面,然后再考虑提高效率,还有一些比较高深的技巧,比如研究分布式呀、断点续爬,怎么控制不同的worker。

mark

思维导图

mark

怎么使用这个思维导图?

先从右上角开始,了解http的内容,然后再学抓取工具。

关于抓取工具

  • Chrome和firebug选其一即可。
  • Tamper Data是一个篡改数据、截停请求的调试器。
  • fiddler 能记录所有客户端的http和https请求,监视、设置断点,修改输入输出的数据。
  • Charles 抓包工具,主要用来抓取手机的包。Web端的抓取策略可能比较复杂和严格,但是在移动端要简单的多。我一般写爬虫就是先看一下有没有开放的API,如果没有的话再看手机端。
    移动端爬虫的一个栗子

关于请求库

个人最推荐requests而完全不推荐按照urllib或者urllib2的方式来写。因为requests帮你考虑的东西更多,比如标准库里往往是默认不支持gzip压缩的,而requests会自动的压缩,而这往往能减少大量的压缩时间。
此外,由于历史原因,标准库的写法冗杂而不优雅,比起高度封装的requests用起来要麻烦的多。

举个栗子:

①urllib2

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
# coding=utf-8
import json
import urllib2
from cookielib import CookieJar

hb_url = 'https://httpbin.org/basic-auth/user/pass'

req = urllib2.Request(hb_url)

password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
password_manager.add_password(None, hb_url, 'user', 'pass')

auth_manager = urllib2.HTTPBasicAuthHandler(password_manager)

cj = CookieJar()
cookie_manager = urllib2.HTTPCookieProcessor(cj)

proxy_handler = urllib2.ProxyHandler({'http': '127.0.0.1'})

opener = urllib2.build_opener(auth_manager, cookie_manager, proxy_handler)

urllib2.install_opener(opener)

handler = urllib2.urlopen(req)

print handler.getcode()
print handler.headers.getheader('content-type')
data = json.load(handler)
print data['authenticated']
# ------
# 200
# 'application/json'
# True

②requests

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

# coding=utf-8
import requests

hb_url = 'https://httpbin.org/basic-auth/user/pass'
proxies = {
'http': 'http://127.0.0.1',
}

r = requests.get(hb_url, auth=('user', 'pass'), proxies=proxies)

print r.status_code
print r.headers['content-type']
print r.json()['authenticated']

关于解析库

  • beautiful soap: 页面处理更友好,代码直观,但是解析比较慢,对于页面的处理比较绕。
  • Xpath+lxml:最推荐,可以直接用一个表达式找到要找的内容,而bs就没这么方便,它要一层一层的去循环。
    学习xml
  • re

关于并发编程

关于任务调度框架

抓取的流程图

mark

发送网络请求->下载好数据后解析html->解析成想要的格式之后存储

celery的流程图

mark

mark

链接:http://pan.baidu.com/s/1skDyoUT 密码:3tsi 就是那个live1.mp4

mark
mark

链接:http://pan.baidu.com/s/1skDyoUT 密码:3tsi 就是那个live2.mp4

AJAX

AJAX出现的较早,在分离这上面做的不是很好,大厂都已经迁移到了Fetch上。
https://github.com/camsong/blog/issues/2

动态网页抓取

关于动态网页的抓取是一件比较困难的事情。有些动态页面可以从接口直接获取数据,但是有一些不行,比如:

  • 用到了现在比较潮流的框架,比如react;
  • 有些需要页面交互才能获取到数据,比如点个按钮
  • 有些是在javascript执行之后生成的。
    这种时候就必须要了解这个过程中是怎么实现渲染的,我们要考虑一个动态页面的抓取的过程。

解决方案

业界动态网页的抓取,常使用selenium + phantomjs,其实就像是打开浏览器,设定一些操作和事件,来模仿一个真实的用户,再通过它提供的接口找到要爬取的元素,拿到它的值。
selenium本来是用来做自动化测试的,还能做鼠标拖动、截屏之类的操作。
phantomjs是一个没有web界面的,可脚本编程的webkit浏览器引擎,可以进行CSS、DOM操作等等。

mark

链接:http://pan.baidu.com/s/1skDyoUT 密码:3tsi 就是那个live3.mp4

几篇celery的文章(一)
几篇celery的文章(二)
几篇celery的文章(三)

mark

很多人会纠结于是用多线程多进程还是asyncio呢,要不要学习twisted呢?其实不需要纠结,先实现功能。

其实主要的性能瓶颈在于要爬取的网站的网络延时、页面渲染的速度还有反爬虫策略。

当然爬虫本身性能可优化的地方也很多,这里有一些建议

  1. 并发或者分布式的方式去爬取。
  2. 使用队列减少数据库的访问。
  3. 按需对数据写操作,从单个执行变成批量执行。(通常是先存在某个地方,比如reddis,然后调一个批量任务定期抓取)
  4. 选择合适的数据库建立正确的索引。如果早期对需求不清楚不确定,用Nosql(比如Mongodb)方便很多,即使数据脏了也可以通过程序处理。
  5. 并发效率并不是线性的,并发数高了对网站和数据库还是有负担。
    ……

mark

对付常用的反爬虫策略

设置IP的访问频率

如果超出一定的频率就会出现验证码。处理验证码可以专门写程序处理,也可以使用开源项目。

*推荐的生成验证码图片的项目 https://github.com/lepture/captcha *

伪造User Agent

一直用一个UA会被开发工程师发现。

建立IP代理池

*获取大量免费代理ip的项目https://github.com/awolfly9/IPProxyTool *

改变refer值

不直接访问,伪造refer

模仿搜索引擎

有可能被打上好人卡~

保存cookie,使用cookie免登陆

关于反反爬虫的项目

推荐的项目:https://github.com/luyishisi/Anti-Anti-Spider

学习典例

爬虫入门:
https://zhuanlan.zhihu.com/p/21479334

知道创宇面试题:
http://www.dongwm.com/archives/pa-chong-lian-xi/

搜狐面试:
https://github.com/dongweiming/mtime

awesome(个人推荐):

https://github.com/BruceDone/awesome-crawler

https://github.com/liinnux/awesome-crawler-cn

https://github.com/facert/awesome-spider

https://github.com/aosabook/500lines/tree/master/crawler/code

scrapy +redis+mongodb进行分布式爬虫

https://github.com/gnemoug/distribute_crawler

技术选型:

  • mongodb:存储爬取的结果(因为它不要求字段的数据结构严格一致化,对脏数据的容错性好)
  • redis:分布式/消息队列/一级缓存(存储中间数据)
  • scrapy:爬虫里最好的一个框架,基于twisted,高度封装。

scrapy+django拓展

https://github.com/scrapy-plugins/scrapy-djangoitem

爬虫情景

对腾讯视频、优酷视频的评论、播放量等的采集

打开网页,弹一个h5或flash的播放器,会请求后端发送视频资源。

  • 页面打开后渲染的第一页就是评论,然后其他页在你翻页或者滚动的时候通过ajax再去加载出来。
  • 刚开始打开页面的时候,底下就没有评论。在后期通过ajax请求过来。相当于视频加载和评论加载(或者其他)分开进行。

** 一般是不可能打开页面后全部评论加载出来的 **