python实现web页面数据抓取代码

web数据抓取是一个经常在python的讨论中出现的主题。有很多方法可以用来进行web数据抓取,然而其中好像并没有一个最好的办法。有一些如scrapy这样十分成熟的框架,更多的则是像mechanize这样的轻量级库。DIY自己的解决方案同样十分流行:你可以使用requests、beautifulsoup或者pyquery来实现。

codego.net中介绍的方法如此多样的原因在于,数据“抓取”实际上包括很多问题:你不需要使用相同的工具从成千上万的页面中抓取数据,同时使一些Web工作流自动化(例如填一些表单然后取回数据)。

我喜欢DIY的原因在于其灵活性,但是却不适合用来做大量数据的抓取,因为需要请求同步,所以大量的请求意味着你不得不等待很长时间。

在本文中,我将会为你展示一个基于新的异步库(aiohttp)的请求的代替品。我使用它写了一些速度的确很快的小数据抓取器,下面我将会为你演示是如何做到的。

asyncio的基本概念

asyncio是在python3.4中被引进的异步IO库。你也可以通过python3.3的pypi来安装它。它相当的复杂,而且我不会介绍太多的细节。相反,我将会解释你需要知道些什么,以利用它来写异步的代码。

协同程序和事件循环。

协同程序像是方法,但是它们可以在代码中的特定点暂停和继续。当在等待一个IO(比如一个HTTP请求),同时执行另一个请求的时候,可以用来暂停一个协同程序。我们使用关键字yield from来设定一个状态,表明我们需要一个协同程序的返回值。而事件循环则被用来安排协同程序的执行。

关于asyncio还有很多很多,但是以上是我们到目前为止需要知道的。可能你还有些不清楚,那么让我们来看codego.net上面的一些代码吧。

aiohttp 是一个利用asyncio的库,它的API看起来很像请求的API。到目前为止,相关文档还不健全。但是这里有一些非常有用的例子。我们将会演示它的基本用法。

我们会定义一个协同程序用来获取页面,并打印出来。我们使用 asyncio.coroutine将一个方法装饰成一个协同程序。aiohttp.request是一个协同程序,所以它是一个可读方法,我们需要使用yield from来调用它们。除了这些,下面的代码看起来相当直观:

@asyncio.coroutine def print_page(url): response = yield from aiohttp.request('GET', url) body = yield from response.read_and_close(decode=True) print(body)

我们可以使用yield from从另一个协同程序中调用一个协同程序。为了从同步代码中调用一个协同程序,我们需要一个事件循环。我们可以通过asyncio.get_event_loop()得到一个标准的事件循环,之后使用它的run_until_complete()方法来运行协同程序。所以,为了使之前的协同程序运行,我们只需要做下面的步骤:

loop = asyncio.get_event_loop() loop.run_until_complete(print_page('http://example.com'))

一个有用的方法是asyncio.wait,通过它可以获取一个协同程序的列表,同时返回一个将它们全包括在内的单独的协同程序,所以我们可以这样写:

loop.run_until_complete(asyncio.wait([print_page('http://example.com/foo'),

print_page('http://example.com/bar')]))

另一个是asyncio.as_completed,通过它可以获取一个协同程序的列表,同时返回一个按完成顺序生成协同程序的迭代器,因此当你用它迭代时,会尽快得到每个可用的结果。

数据抓取

现在我们知道了如何做异步HTTP请求,因此我们可以来写一个数据抓取器了。我们仅仅还需要一些工具来读取html页面,我使用了beautifulsoup来做这个事情,其余的像 pyquery或lxml也可以实现。

我们会写一个小数据抓取器来从海盗湾抓取一些linux distributions的torrent 链路(海盗湾(英语:The Pirate Bay,缩写:TPB)是一个专门存储、分类及搜索Bittorrent种子文件的网站,并自称“世界最大的BitTorrent tracker(BT种子服务器)”,提供的BT种子除了有自由版权的收集外,也有不少被著作人声称拥有版权的音频、视频、应用软件与电子游戏等,为网络分享与下载的重要网站之一–译者注来自维基百科)

首先,需要一个辅助协同程序来获取请求:

@asyncio.coroutine def get(*args, **kwargs): response = yield from aiohttp.request('GET', *args, **kwargs) return (yield from response.read_and_close(decode=True))

解析部分。本文并非介绍beautifulsoup的,所以这部分我会简写:我们获取了这个页面的第一个磁链。

def first_magnet(page): soup = bs4.BeautifulSoup(page) a = soup.find('a', title='Download this torrent using magnet') return a['href']

在这个协同程序中,url的结果通过种子的数量进行排序,所以排名第一的结果实际上是种子最多的:

6 @asyncio.coroutine def print_magnet(query): url = 'http://thepiratebay.se/search/{}/0/7/0'.format(query) page = yield from get(url, compress=True) magnet = first_magnet(page) print('{}: {}'.format(query, magnet))

用下面的代码来调用以上所有的方法。

distros = ['archlinux', 'ubuntu', 'debian'] loop = asyncio.get_event_loop() f = asyncio.wait([print_magnet(d) for d in distros]) loop.run_until_complete(f)

现在我们来到了这个部分。你有了一个异步工作的小抓取器。这意味着多个页面可以同时被下载,所以这个例子要比使用请求的相同代码快3倍。现在你应该可以用相同的方法写出你自己的抓取器了。

你一旦熟悉了这一切,我建议你看一看asyncio的文档和aiohttp的范例,这些都能告诉你 asyncio拥有怎样的潜力。

这种方法(事实上是所有手动的方法)的一个局限在于,没有一个独立的库可以用来处理表单。机械化的方法拥有很多辅助工具,这使得提交表单变得十分简单,但是如果你不使用它们,你将不得不自己去处理这些事情。这可能会导致一些bug的出现,所以同时我可能会写一个这样的库(不过目前为止无需为此担心)。

额外的建议:不要对服务器要求太多

同时做3个请求很酷,但是同时做5000个就不那么好玩了。如果你打算同时做太多的请求,链接有可能会断掉。你甚至有可能会被禁止链接网络。

为了避免这些,你可以使用semaphore。这是一个可以被用来限制同时工作的协同程序数量的同步工具。我们只需要在建立循环之前创建一个semaphore ,同时把我们希望允许的同时请求的数量作为参数传给它既可:

sem = asyncio.Semaphore(5)

然后,我们只需要将下面

page = yield from get(url, compress=True)

替换成被semaphore 保护的同样的东西。

with (yield from sem): page = yield from get(url, compress=True)

这就可以保证同时最多有5个请求会被处理。

tqdm是一个用来生成进度条的优秀的库。这个协同程序就像asyncio.wait一样工作,不过会显示一个代表完成度的进度条。

@asyncio.coroutine def wait_with_progress(coros): for f in tqdm.tqdm(asyncio.as_completed(coros), total=len(coros)): yield from f

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/30184705/viewspace-1482867/,如需转载,请注明出处,否则将追究法律责任。

用python爬取网页数据代码_python实现web页面数据抓取代码相关推荐

  1. python爬取b站评论_Python爬虫框架:scrapy抓取B站博人传评论数据

    1. B站博人传评论数据爬取简介 今天想了半天不知道抓啥,去B站看跳舞的小姐姐,忽然看到了评论,那就抓取一下B站的评论数据,视频动画那么多,也不知道抓取哪个,选了一个博人传跟火影相关的,抓取看看.网址 ...

  2. python 爬取网页 通知消息_python简单爬取页面信息及实现打开、关闭浏览器

    声明:本文仅是为了学习而举例说明python的强大,禁止用于不良目的! 1.python可以打开浏览器并浏览网页,并且保存网页内容到本地硬盘 实现代码如下: import urllib import ...

  3. python爬取京东商品代码_Python简单爬取京东商品列表

    #!/usr/bin/python3 # -*- coding: UTF-8 -*- import urllib.request import urllib.error import re impor ...

  4. python爬取并下载代码_python 爬取并批量下载网易云歌单源代码

    #!/usr/bin/env python#!--*--coding:utf-8 --*-- #![url=home.php?mod=space&uid=238618]@Time[/url]  ...

  5. python爬取腾讯新闻_Python 实现腾讯新闻抓取

    原博文 2012-08-14 09:56 − 思路: 1.抓取腾讯新闻列表页面: http://news.qq.com/ 2.提取详细页面的url:http://news.qq.com/a/20120 ...

  6. Python 爬取网页HTML代码

    #/usr/bin/env python #-*- coding:utf-8 -*-import urllib2 import sys import chardetreq = urllib2.Requ ...

  7. python爬取网页停止工作_python人员api停止工作

    我有一个python(2.7.10)代码,它基于位于https://developers.google.com/people/quickstart/python的"快速入门"示例, ...

  8. python爬取网页代码-python爬虫爬取网页所有数据详细教程

    Python爬虫可通过查找一个或多个域的所有 URL 从 Web 收集数据.Python 有几个流行的网络爬虫库和框架.大家熟知的就是python爬取网页数据,对于没有编程技术的普通人来说,怎么才能快 ...

  9. python爬取网页公开数据_如何用Python爬取网页数据

    使用Python爬取网页数据的方法: 一.利用webbrowser.open()打开一个网站:>>> import webbrowser >>> webbrowse ...

  10. 编程python爬取网页数据教程_实例讲解Python爬取网页数据

    一.利用webbrowser.open()打开一个网站: >>> import webbrowser >>> webbrowser.open('http://i.f ...

最新文章

  1. 对python3中pathlib库的Path类的使用详解
  2. 【请求后台接口】30秒完成Angular10精简版HttpClient请求服务搭建
  3. 如何在Python中调用Windows的cmd命令?
  4. 在linux下给grep命令添加颜色
  5. 解决使用Navicat等工具进行连接登录mysql的1130错误,无法使用Ip远程连接的问题(mysql为8.0版本)
  6. 反编译sencha toucha打包的apk文件,修改应用名称支持中文以及去除应用标题栏
  7. 使用JMS实现请求/应答程序
  8. ef 单表一对多集合查询_FILTER函数你用过吗?一对多查询与自动筛选,用它都能轻松搞定...
  9. github中删除已建仓库(二)
  10. 圆心角 圆弧上点坐标_数控加工中心CNC的G02/G03圆弧指令的I、J、与R的区别
  11. CSS3 linear-gradient实现三角形
  12. Redis定时任务,
  13. SQL语法集锦一:SQL语句实现表的横向聚合
  14. 使用new和delete
  15. Structure from Motion Using OpenCV
  16. 湖南大学计算机与通信学院李燕,基于SVM的面部表情分析
  17. 用frp开源工具,实现内网穿透(详细教程)
  18. 【软件定义汽车】【场景篇】AR-HUD
  19. 怎么在html中使logo,如何用CSS3设计腾讯QQ LOGO?
  20. Eclipse怎么设置字体呢

热门文章

  1. 第三章 原位正三和弦的连接
  2. 网站在移动端访问时偶尔不能加载页面,http访问被劫持
  3. 360隐私保护器直指腾讯QQ 360真的发飙了,百度旁观!
  4. 计算机应用中双绞线细铜线几根,《计算机应用基础_在线作业_E100.doc
  5. php花曲线,ps钢笔工具怎么画曲线
  6. 台式计算机和笔记本电脑的相同点,与笔记本电脑相比,台式机有哪些优势?
  7. java String类型的处理
  8. 保利威视后台设置播放域名黑白名单
  9. 小鑫の日常系列故事(五)——卡片游戏
  10. ECMAScript历史