Python requests+gevent+BeautifulSoup lxml 干点啥-加点速

很久没有写新的内容了,看最近的一篇 都有2/3个半年了 最近又看了一些爬虫文章 还是想深入研究下

目标就是能爬知乎,太可怕了
  • 最近工作中有个需求是抓一些数据 数据量上万 讲真 以前都是玩玩 没实战 所以来这个需求的时候 我内心其实有点激动
装逼模式已开启
  • 然后 我开始装逼了 用request + BeautifulSoup(html) 用这两货实现
    requests请求网络数据加载
    BeautifulSoup(html) 自在解析器 解析网络获取数据

  • 啪啦啪啦啪啦啪啦 没几下代码撸完了 顿时感觉登上人生巅峰
    开始运动 哦 不对 是运行 结果这货第一页(20个详情)数据 用了快4分钟
    要不是中途有些log打印 我都以为他死了

懵逼ing
  • 我一想 这么不行啊 我特么600页的数据 这能玩
    然后我就想 每次数据获取 一整个套路下来
    就是 请求--->IO读取--->解析
    能优化速度的地方 就是 IO读取 解析
    有方向 那就开始 说说解析
    本来用的BeautifulSoup 自带的解析器 文档上说了 速度慢
    既然说了速度慢 肯定有速度快的 我就看了一下 lxml速度快 需要安装C语言库
    解析属于高度计算 对于IO密集型与CPU密集来讲 属于CPU密集型任务 越底层的语言 越有优势 所以这里C语言会很快

  • 然后就开始安装 lxml
    果不其然 报错了 当时在公司做 是Windows 说是缺少一个啥子 具体不记得(反正是微软的 )
    如果Windows安装出相关问题 可以先用pip install wheel安装这个 然后下载lxml相关的whl文件 直接下载下来安装就行
    这里要选择版本 什么的
    相关whl下载地址 进去 ctrl+F搜索就行 注意版本号 和你Py版本 34 35 27 啥的
    http://link.zhihu.com/?target=http%3A//www.lfd.uci.edu/~gohlke/pythonlibs/%23lxml

  • 一顿折腾lxml终于安装OK
    然后 requests+BeautifulSoup(lxml) 在运动 一页50S
    当时我就给吓尿了 效率直接快10倍号码
    真是 ‘搏一搏单车 变摩托’

66666翻天
  • 然后 我又感觉我登上了人生巅峰 电脑挂着 下班回家
    第二天一脸懵逼 说好的数据呢 中途不知道咋的 卡着不动了 一晚上没抓完 本来以为一晚上10个小时差不多能抓完的 结果来这么一出
    然后 想着 我总不能又跑一次 等10个小时吧 没那闲功夫看着啊
    然后 想着能不能再IO等待那里做处理 我想着请求过去了 本地堵塞等着 要是等待的时候 干点别的 比如 开启另外的请求 这样是不是效率很高很多
    然后就查了一下 多线程 多进程
    结果整出来gevent 异步框架 里面用的协程(也是单线程 不过可以跳度切换 任务)
    然后加上这个gevent之后
    卧槽 ----直接每页变成 10S
喜极而泣
  • 最后完成那600页数据的读取 在这个基础还加上了 进程池pool
    200页一个进程 反正最后 3 40分钟 就拿到了12000条数据

夜深了 就是容易 说废话 铺垫做完了 现在 来讲讲这些东西

  • requests 比起自带的urllib2啥的 方便很多 这个没啥说的 可以自己去看看

  • gevent 异步框架 今天也是刚用 用法也简单 等会看代码

  • BeautifulSoup 超级6 叼炸天 去从网页数据中获取你要的数据 前面用Xpath我觉得好用(主要还是最开始用re) 现在这个是首选这里也是这篇博客 主要介绍的 用糗事百科 的数据 来看看咋使用select 和 find

  • 这里先贴两张图 糗事百科 数据获取的50页数据 的情况 find VS select 貌似差不多 没做详细对比 不过我感觉还是find快些吧 毕竟select返回list 大数据量下 还是要测试一波 两个都挺好用的 看习惯


    find方法

    select方法
  • 然后一看也有106秒左右 为什么也不快 因为 没用代理IP(今天去相关网站找的一些 用进去很慢 而且很多不能用 先放着) 然后如果访问太快 直接返回我503 所以 每请求一页 sleep(1) s 也就是说 理论上 如果不停这1S我50页应该是最多66秒左右能跑完 也就是平均一页1S多一点
    就算现在停了 在异步和lxml的处理下 大概也就2S一页 其实算可以啦

  • 再贴一记 打印内容的


    详细获取数据打印

    分析图
  • 全部代码图 一点点 (后面 放github后会更新文章)
  __author__ = 'Daemon1993'

  import gevent
  import requests
  import time
  from bs4 import BeautifulSoup
  from bs4 import SoupStrainer

  SP = 1
  Count=0

  def getHtmlByFind(baseurl, page):
      url = baseurl + str(page)
      r = requests.session()

      html = r.get(url, timeout=5)

#如果状态不正确 这里目的503 暂停时间增大一点
if (html.status_code != 200):
    global SP
    SP += 0.5
    return

#减少内存压力 取出我们需要的那块 不用全部
only_div_tag = SoupStrainer(id="content-left")

# 先拿到这一块
data = BeautifulSoup(html.text, "lxml",parse_only=only_div_tag)

for tag in data.find_all("div", class_="article block untagged mb15"):
    name=tag.find("img").get('alt')
    content=tag.find("div",class_="content").text.strip()
    global Count
    Count+=1
    pass
    # print("\\n 用户:{0} \\n {1}".format(name,content))

#每请求一次 睡眠一下
time.sleep(SP)

  def getHtmlBySelect(baseurl, page):
      url = baseurl + str(page)
      r = requests.session()

html = r.get(url, timeout=5)

if (html.status_code != 200):
    global SP
    SP += 0.5
    return

#减小内存压力
only_div_tag = SoupStrainer(id="content-left")

# 先拿到这一块
data = BeautifulSoup(html.text, "lxml",parse_only=only_div_tag)

for tag in data.select('div[class="article block untagged mb15"]'):
    name=tag.select('img')[0].attrs.get('alt')
    content=tag.select('div[class="content"]')[0].get_text().strip()
    global Count
    Count+=1
    print("\\n 用户:{0} \\n\\n {1}".format(name,content))

#每请求一次 睡眠一下
time.sleep(SP)

def useFind(baseurl):
    start=time.time()
    global  Count
    Count=0
tasks = [gevent.spawn(getHtmlByFind, baseurl, index) for index in range(1, 50)]
gevent.joinall(tasks)

elapsed=time.time()-start
print('getHtmlByFind time {0}  size{1}'.format(elapsed,Count))

def useSelect(baseurl):
start=time.time()
global  Count
Count=0
#gevent.spawn 加入任务方法
tasks = [gevent.spawn(getHtmlBySelect, baseurl, index) for index in range(1, 50)]
#全部加入队列开始 处理 
gevent.joinall(tasks)

elapsed=time.time()-start
print('getHtmlBySelect time {0}  size{1}'.format(elapsed,Count))

  if __name__ == '__main__':
      baseurl = "http://www.qiushibaike.com/8hr/page/"
      #useFind(baseurl)
      useSelect(baseurl)
  • 主要看看 BeautifulSoup 的用法

先分析 网页结构 如何拿到我们想要的 1是每一个 2是有头像地址和名字 3是content内容
如下图 取每个1的 2 3就行


find分析结构图
  • find实现

跟就结构 分析 大题思路
1处是一个列表 ---> find_all("div",class__="className")--List
然后对每个集合中取出 img 和 div[class="content"]的内容 代码如下
for tag in data.find_all("div", class_="article block untagged mb15"):
name = tag.find("img").get('alt')
content = tag.find("div", class_="content").text.strip()

  • select实现

这里要先记住一点 select 每次返回都是list 在你能控制的住的情况下取[0]
同样分析 你会发现其实差不多 只是写法上有些不同 可以仔细看看两者的写法
for tag in data.select('div[class="article block untagged mb15"]'):
name = tag.select('img')[0].attrs.get('alt')
content = tag.select('div[class="content"]')[0].get_text().strip()

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容