加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 站长学院 > Asp教程 > 正文

Python 爬虫学习笔记之多线程爬虫

发布时间:2016-12-04 01:13:16 所属栏目:Asp教程 来源:站长网
导读:XPath 的安装以及使用 1 . XPath 的介绍 刚学过正则表达式,用的正顺手,现在就把正则表达式替换掉,使用 XPath,有人表示这太坑爹了,早知道刚上来就学习 XPath 多省事

XPath 的安装以及使用

1 . XPath 的介绍

刚学过正则表达式,用的正顺手,现在就把正则表达式替换掉,使用 XPath,有人表示这太坑爹了,早知道刚上来就学习 XPath 多省事 啊。其实我个人认为学习一下正则表达式是大有益处的,之所以换成 XPath ,我个人认为是因为它定位更准确,使用更加便捷。可能有的人对 XPath 和正则表达式的区别不太清楚,举个例子来说吧,用正则表达式提取我们的内容,就好比说一个人想去天安门,地址的描述是左边有一个圆形建筑,右边是一个方形建筑,你去找吧,而使用 XPath 的话,地址的描述就变成了天安门的具体地址。怎么样?相比之下,哪种方式效率更高,找的更准确呢?

2 . XPath 的安装

XPath 包含在 lxml 库中,那么我们到哪里去下载呢? 点击此处 ,进入网页后按住 ctrl+f 搜索 lxml ,然后进行下载,下载完毕之后将文件拓展名改为 .zip ,然后进行解压,将名为 lxml 的文件夹复制粘贴到 Python 的 Lib 目录下,这样就安装完毕了。

3 . XPath 的使用

为了方便演示,我利用 Html 写了个简单的网页,代码如下所示(为了节省时间,方便小伙伴们直接进行测试,可直接复制粘贴我的代码)

lt;!DOCTYPE htmlgt;
lt;html lang="en"gt;
lt;headgt;
  lt;meta charset="UTF-8"gt;
  lt;titlegt;Test Htmllt;/titlegt;
lt;/headgt;
lt;bodygt;
lt;div id="content"gt;
  lt;ul id="like"gt;
    lt;ligt;like onelt;/ligt;
    lt;ligt;like twolt;/ligt;
    lt;ligt;like threelt;/ligt;
  lt;/ulgt;

  lt;ul id="hate"gt;
    lt;ligt;hate onelt;/ligt;
    lt;ligt;hate twolt;/ligt;
    lt;ligt;hate threelt;/ligt;
  lt;/ulgt;

  lt;div id="url"gt;
    lt;a href="http://www.baidu.com"gt;百度一下lt;/agt;
    lt;a href="http://www.hao123.com"gt;好123lt;/agt;
  lt;/divgt;
lt;/divgt;

lt;/bodygt;lt;/htmlgt;

用谷歌浏览器打开这个网页,然后右击,选择检查,会出现如下所示界面

Python 爬虫学习笔记之多线程爬虫

这个时候你鼠标右击任何一行 html 代码,都可以看到一个 Copy,将鼠标放上去,就可以看到 Copy XPath ,先复制下来,怎么用呢?

# coding=utf-8
from lxml import etree

f = open('myHtml.html','r')
html = f.read()
f.close()

selector = etree.HTML(html)
content = selector.xpath('//*[@id="like"]/li/text()')
for each in content:
  print each

看看打印结果

like one
like two
like three

很显然,将我们想要的内容打印下来了,注意我们在 xpath() 中使用了 text() 函数,这个函数就是获取其中的内容,但是如果我们想获取一个属性,该怎么办?比如说我们想得到 html 中的两个链接地址,也就是 href 属性,我们可以这么操作

content = selector.xpath('//*[@id="url"]/a/@href')
for each in content:
  print each

这个时候的打印结果就是

http://www.baidu.com
http://www.hao123.com

看到现在大家大概也就对 xpath() 中的符号有了一定的了解,比如一开始的 // 指的就是根目录,而 / 就是父节点下的子节点,其他的 id 属性也是一步一步从上往下寻找的,由于这是一种树结构,所以也难怪方法的名字为 etree()。

4 . XPath 的特殊用法

lt;!DOCTYPE htmlgt;
lt;html lang="en"gt;
lt;headgt;
  lt;meta charset="UTF-8"gt;
  lt;titlegt;Titlelt;/titlegt;
lt;/headgt;
lt;bodygt;
lt;div id="likeone"gt;like onelt;/divgt;
lt;div id="liketwo"gt;like twolt;/divgt;
lt;div id="likethree"gt;like threelt;/divgt;

lt;/bodygt;
lt;/htmlgt;

面对上面的一个网页,我们应该如何获取到三行的内容的 #63; 嗯哼,很简单,我写三个 XPath 语句不就好了,so easy 。 如果真是这样,那么我们的效率好像是太低了一点,仔细看看这三行 div 的 id 属性,好像前四个字母都是 like, 那就好办了,我们可以使用 starts-with 对这三行进行同时提取,如下所示

content = selector.xpath('//div[starts-with(@id,"like")]/text()')

不过这样有一点麻烦的地方,我们就需要手动的去写 XPath 路径了,当然也可以复制粘贴下来在进行修改,这就是提升复杂度来换取效率的问题了。再来看看标签嵌套标签的提取情况

lt;!DOCTYPE htmlgt;
lt;html lang="en"gt;
lt;headgt;
  lt;meta charset="UTF-8"gt;
  lt;titlegt;Titlelt;/titlegt;
lt;/headgt;
lt;bodygt;

lt;div id="content"gt;
  lt;div id="text"gt;
    lt;pgt;hello
      lt;bgt; world
        lt;font color="#ffe4c4"gt;
          Python
        lt;/fontgt;
      lt;/bgt;
    lt;/pgt;
  lt;/divgt;
lt;/divgt;

lt;/bodygt;
lt;/htmlgt;

像上面这样的一个网页,如果我们想获取到nbsp; hello world Python 语句,该怎么获取呢?很明显这是一种标签嵌套标签的情况,我们按照正常情况进行提取,看看结果如何

content = selector.xpath('//*[@id="text"]/p/text()')
for each in content:
  print each

运行之后,很遗憾的,只打印出了 hello 字样,其他字符丢失了,该怎么办呢?这种情况可以借助于 string(.)如下所示

content = selector.xpath('//*[@id="text"]/p')[0]
info = content.xpath('string(.)')
data = info.replace('n','').replace(' ','')
print data

这样就可以打印出正确内容了,至于第三行为什么存在,你可以将其去掉看看结果,到时候你自然就明白了。

Python 并行化的简单介绍

有人说 Python 中的并行化并不是真正的并行化,但是多线程还是能够显著提高我们代码的执行效率,为我们节省下来一大笔时间,下面我们就针对单线程和多线程进行时间上的比较。

# coding=utf-8
import requests
from multiprocessing.dummy import Pool as ThreadPool
import time


def getsource(url):
  html = requests.get(url)

if __name__ == '__main__':
  urls = []
  for i in range(50, 500, 50):
    newpage = 'http://tieba.baidu.com/f#63;kw=pythonie=utf-8pn=' + str(i)
    urls.append(newpage)

  # 单线程计时
  time1 = time.time()
  for i in urls:
    print i
    getsource(i)
  time2 = time.time()

  print '单线程耗时 : ' + str(time2 - time1) + ' s'

  # 多线程计时
  pool = ThreadPool(4)
  time3 = time.time()
  results = pool.map(getsource, urls)
  pool.close()
  pool.join()
  time4 = time.time()
  print '多线程耗时 : ' + str(time4 - time3) + ' s'

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读