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

网络爬虫(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”即可。

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


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 requests
html = requests.get('http://tieba.baidu.com/f?ie=utf-8&kw=python')
print (html.text)

当然,有时候我们还需要伪装一下:

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

import requests
import re

url = '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直接提供了该工具:

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

构造贴吧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]

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

一些注意事项由于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如下:

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

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

#-*-coding:utf8-*-
from multiprocessing.dummy import Pool as ThreadPool
from lxml import etree
import requests
import json
import 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()  #关闭文件
    原文作者:李一一⁣⁣⁣⁣
    原文地址: https://blog.csdn.net/qingdujun/article/details/56509373
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞