[Python]实战——百度贴吧爬虫

来源:互联网 发布:用户角色权限java代码 编辑:程序博客网 时间:2024/05/07 19:10

网络爬虫(Web Spiders)是一个自动提取网页的程序,它为搜索引擎从万维网上下载网页,是搜索引擎的重要组成。半年前,我接触了Lucene搜索引擎开发——开始了网络爬虫之旅;当时,采用的是纯JAVA开发环境,对百度某吧几百万帖子进行了全面爬取。那时候我对Python一点都不了解,今天对《Pyhon基础教程:第2版·修订版》以及极客学院相关视频进行了学习,形成了本文。


Key Words:   网络爬虫,  多线程,  requests,  XPath,   lxml


1. 本文相关环境

        开发工具与平台:Python2.7,  Windows7,  PyCharm

        Python第三方包下载平台http://www.lfd.uci.edu/~gohlke/pythonlibs/,该平台可以下载几乎所有Python包,包括本文的requests,lxml,下载之后如何安装(见下文)。另外,推荐一款json格式化工具:HiJson。


2. Windows平台,如何安装requests、lxml包?

        从上述网站上,选择合适自己的版本(Ctrl+F,可搜索),下载完成后:

                ①将后缀“.whl”更改为“.zip”;

                ②解压,将“非-info”文件夹拷贝至“D:\AppInstall\Python27\Lib”即可。

              


3.requests简单介绍

  •         HTTP for humans.
  •         All the cool kids are doing it. Requests is one of the most downloaded Python packages of all time.

以上是官网上的两句原话:①人性化的HTTP;  ②下载量最大的第三方包之一。事实上,requests确实很人性化,比如获取网页源代码如此简单:

GET方法:requests.get(url=, params=, kwargs=)

import requestshtml = requests.get('http://tieba.baidu.com/f?ie=utf-8&kw=python')print (html.text)
当然,有时候我们还需要伪装一下:

User-Agent面纱:审查元素->Network->刷新页面->选择某文件->headers

import requestsimport reurl = 'http://tieba.baidu.com/f?ie=utf-8&kw=python'ua = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}#GET请求数据html = requests.get(url,headers=ua)html.encoding = 'utf-8'#正则匹配title = re.findall('class="j_th_tit ">(.*?)</a>',html.text,re.S)for each in title:    print(each)
GET并不是万能的,有些网页需要我们向其提交数据,才能获得反馈:

POST方法:requests.post(url=, data=, json=, kwargs=)

#构造POST字典node = {    'enter':'true',    'page':'3'}#POST请求数据html = requests.post(url,data=node)

4. XPath教程

  •         XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。
  •         具体查看W3C,http://www.w3school.com.cn/xpath/index.asp

XPath将我们从复杂的正则中解脱了出来,并且Chrome直接提供了该工具:

构造贴吧XPath:借助Chrome XPath着手,形成贴吧相应匹配

#构造XPath,正则每层楼内容content_field = selector.xpath('//div[@class="l_post j_l_post l_post_bright  "]')#抓取data-field里类json数据,并去掉双引号,最后转为字典格式data_field = json.loads(each.xpath('@data-field')[0].replace('"',''))#回复内容content = each.xpath('div[@class="d_post_content_main"]/div/cc/div[@class="d_post_content j_d_post_content  clearfix"]/text()')[0]


一些注意事项由于Python3强制向后不兼容,导致了可能出现以下问题:

  • from lxml import etree,引入失败。解决方案:①换个lxml版本包;②换成Python2.7
  • 如果不使用requests,而使用from urllib import urlopen;urllib.urlopen(tempUrl),出错。解决方案:import urllib.request;urllib.request.urlopen(tempUrl)

5. Python多线程

        这个实现起来尤为简单,主要分为以下几步:

        ①导包:from multiprocessing.dummy import Pool as ThreadPool

        ②多线程,本机为2核CPU:pool = ThreadPool(2)

        ③map Python并发:pool.map(spider,page); pool.close();  pool.join()


6.  百度贴吧爬虫

根据以上介绍,一款贴吧爬虫呼之欲出,这里对上文图中data-field字段,格式化为json如下:


可以根据自己的需要,获取字段中更多的内容~

#-*-coding:utf8-*-from multiprocessing.dummy import Pool as ThreadPoolfrom lxml import etreeimport requestsimport jsonimport sys#强制编码,注意顶部声明reload(sys)sys.setdefaultencoding('utf-8')#控制台显示def showContent(item):    print(u'回帖时间:'+str(item['time'])+'\n')    print(u'回帖内容:'+unicode(item['content'])+'\n')    print(u'回帖人:'+item['user_name']+'\n\n')#保存文件def saveFile(item):    #u'',设定Unicode编码    f.writelines(u'回帖时间:'+str(item['time'])+'\n')    f.writelines(u'回帖内容:'+unicode(item['content'])+'\n')    f.writelines(u'回帖人:'+item['user_name']+'\n\n')#网络爬虫def spider(url):    #抓取网页源码    html = requests.get(url)    selector = etree.HTML(html.text)    #构造XPath,正则每层楼内容    content_field = selector.xpath('//div[@class="l_post j_l_post l_post_bright  "]')    item = {}    for each in content_field:        #抓取data-field里类json数据,并去掉双引号,最后转为字典格式        data_field = json.loads(each.xpath('@data-field')[0].replace('"',''))        #用户名        user_name = data_field['author']['user_name']        #回复内容        content = each.xpath('div[@class="d_post_content_main"]/div/cc/div[@class="d_post_content j_d_post_content  clearfix"]/text()')[0]        #回复时间        time = data_field['content']['date']        #封装item[]        item['user_name'] = user_name        item['content'] = content        item['time'] = time        showContent(item)        saveFile(item)if __name__ == '__main__':    #多线程,2核CPU    pool = ThreadPool(2)    #r'',避免转义,文件以追加形式打开,不存在就新建    f = open(r'D:\content.txt','a')    page = []    for i in range(1,21):        newpage = 'http://tieba.baidu.com/p/4880125218?pn='+str(i)        page.append(newpage)    #map实现Python多线程:map(爬取函数,网址列表)    results = pool.map(spider,page)    pool.close()    pool.join()    f.close()  #关闭文件

[C170102-1]©Turing Ant

0 0
原创粉丝点击