第 13 章 Python 并发编程
现在拥有多核 CPU 的服务器随处可见,充分利用语言特性,使用并发方式编程也是 Web 开发者一项必须掌握的日常技能。好的并发程序远比单线程单进程的程序的运行效率高得多。本章我们通过抓取微信公众号文章内容并存入 MongoDB 数据库,来演示 Python 的并发技术。
编写爬虫(Crawler)程序算是不同级别 Python 工程师都可能涉及的工作之一,所谓爬虫就是让程序自动访问目标网站,解析页面,把需要的内容保存下来。写好爬虫其实原则只有一条,就是让你的抓取行为和用户访问网站的真实行为尽量一致。举些例子,用户不会 1 秒钟打开 10 个页面,也不会使用不符合浏览器格式的用户代理(User-Agent,UA),有些页面的 Referfer 和浏览器 Cookie 也很重要。为了保证爬虫持续稳定,甚至于还要模拟用户的正常行为,如发帖、签到、给别人点赞、参与讨论等。这些细节做好了,基本上什么网站都可以抓取成功。
为了让抓取顺利,我们要做好如下 4 件事:
1.使用代理。一般的网站都有一些防爬虫的策略,如限制单位时间内页面的请求次数,基于来源 IP、UA 等请求信息判断用户访问是否正常。单机抓取整个网站内容,要想快速完成显然是不可能的,那么就需要分布式地使用多个服务器来抓取。如果公司没有专门的抓取服务器,可以从网上找一些代理服务器来使用。
2.伪造 UA 字符串。每次请求都使用随机生成的 UA。
3.选择解析 HTML 的方式。BeautifulSoup 是一个可以从 HTML 或 XML 文件中提取数据的 Python 库。我们还需要给它配置一个解析器,解析器提供了相同的、非常人性化的接口,使用非常简便。常见的解析器包含如下几种:
- html.parser。使用 Python 标准库自带的解析器,文档容错能力强,但是速度上没有优势。
- lxml。lxml 是一个 C 语言实现的 libxml2 和 libxslt 的 Python 绑定库,速度比其他的选择快得多,而且文档容错能力强。
- html5lib。容错性最好,它的解析方式和其他解析器相比有所不同,它会以浏览器的方式解析文档。
4.使用 Referfer。使用 Referfer 是一个好习惯,模仿一个从搜索引擎点击进来的请求,更不容易被封禁。
由于 BeautifulSoup 的易用性和 lxml 效率,笔者选择两者的组合来实现页面的解析。先安装它们。
> pip install beautifulsoup4 lxml
需要抓取的内容分三种:
- 抓取多个代理网站上发布的代理地址,把解析的代理地址存进数据库备用。将使用多线程完成。
- 抓取微信工作平台的搜索列表页。我们使用搜狗的微信搜索平台(http://weixin.sogou. com )。搜索支持两种类型,分别是微信公众号和和微信文章,本章将抓取包含 Python 关键词的文章,也就是使用 type=2。将使用协程完成。
- 抓取微信文章内容,微信文章的域名是 http://mp.weixin.qq.com。将分别使用多进程、Future 和 aysncio 三种方式完成。
为了减少复杂度,随机生成 UA 的功能通过第三方库 fake-useragent 实现:
> pip install fake-useragent
生成一个 UA 字符串只需要如下代码即可:
In : from fake_useragent import UserAgent In : ua=UserAgent() In : ua.random Out: u'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome /41.0.2228.0 Safari/537.36' In : ua.random Out: u'Mozilla/5.0 (Macintosh;Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'
我们使用 MongoEngine 管理数据模型。先定义基类:
from mongoengine import connect, StringField, DateTimeField, Document from config import DB_HOST, DB_PORT, DATABASE_NAME connect(DATABASE_NAME, host=DB_HOST, port=DB_PORT) class BaseModel(Document): create_at=DateTimeField() meta={'allow_inheritance':True, 'abstract':True} BaseModel 的 meta 属性将允许其被继承。 config.py 存放配置常量: DB_HOST='localhost' DB_PORT=27017 DATABASE_NAME='chapter13'
为了让例子更简单易懂,本章的例子都使用过程式编程。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论