最近想学习下Python。考虑到一点一点看教程学习过于枯燥,没有时间也没有学习动力。爬虫和Python最常用的功能就是爬虫和数据分析。不如就先从这两样着手做个简单的小项目,爬取一些网站数据,并做一些简单的分析。选定了爬取草榴成人文学的标题列表(不好内容)来作为学术目的。
工具准备 安装Scrapy Scrapy 是一个现行常用的爬虫框架,扩展性强,拥有强大的爬取和分析能力,安装起来也蛮简单。
** pip install scrapy **
当然安装使用起来也有很多的坑会踩,比如说没有安装Twisted、lxml等,这在Python下都不是问题,一个_pip install_搞定。
另外CentOS服务器会碰到运行时找不到__sqlite3模块的错误。靠如下方法搞定:
_sudo yum install sqlite-deve_l
重新编译python3.6:./configure –enable-loadable-sqlite-extensions –with-ssl;make;sudo make install
P.S. 简单的功能,其实爬虫完全可以利用现行的HTTP Request类来写也不复杂。个人只是图省事儿用了Scrapy
安装Pymongo 原本以为数据量很大,就打算直接使用数据库来存储爬取到的数据,而Python常用的数据库为Mongo,使用需要安装Pymongo(后来发现其实只有2000多条数据,直接存文本就可以的)。
pip install Pymongo
这里说一下,数据库我直接使用的是Pymongo官方 提供的实验数据库,有500M空间,可以远程使用.
Python使用Pymongo的文档,可以参考pymongo 文档
使用Scrapy爬取 先执行s_crapy startproject 爬虫项目名_来创建项目,得到如下目录结构
t66y ├── proxy.py ├── scrapy.cfg └── t66y ├── init .py ├── items.py ├── middlewares.py ├── pipelines.py ├── settings.py └── spiders └── init .py
代码 我们在spiders下建立t66y.py,直接上代码了(为避免教坏小朋友,删掉网址):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 import scrapyfrom scrapy.http import Requestfrom t66y.items import T66YItemclass t66yLitSpider (scrapy.Spider) : name = "t66yLit" allowed_domains = ['草榴域名' ] start_urls = ['http://草榴域名/thread0806.php?fid=20&search=&page={}' .format(i) for i in range(1 ,22 )] def parse (self, response) : item = T66YItem() lits = response.xpath('//tr[@class="tr3 t_one tac"]' ) for lit in lits: item['lit_type' ] = lit.xpath('.//*[@class="tal"]/text()[1]' ).extract()[0 ].strip() item['lit_title' ] = lit.xpath('.//*[@class="tal"]//h3/a/text()' ).extract() if len(item['lit_title' ]) == 1 : item['lit_title' ] = item['lit_title' ][0 ].strip() item['lit_url' ] = lit.xpath('.//*[@class="tal"]//h3/a/@href' ).extract()[0 ].strip() item['lit_writer' ] = lit.xpath('.//td[1]//following-sibling::*[2]/a/text()' ).extract()[0 ].strip() item['lit_submit' ] = lit.xpath('.//td[1]//following-sibling::*[2]/a//following-sibling::*[1]/text()' ).extract() if len(item['lit_submit' ]) == 1 : lit_submit = lit.xpath('.//td[1]//following-sibling::*[2]/a//following-sibling::*[1]' ) item['lit_submit' ] = lit_submit.xpath('string(.)' ).extract()[0 ].strip() item['lit_comments' ] = lit.xpath('.//td[1]//following-sibling::*[3]/text()' ).extract() if len(item['lit_comments' ]) == 1 : item['lit_comments' ] = item['lit_comments' ][0 ] item['lit_last_comments' ] = lit.xpath('.//td[1]//following-sibling::*[4]/a/text()' ).extract() if len(item['lit_last_comments' ]) == 1 : item['lit_last_comments' ] = item['lit_last_comments' ][0 ] self.log("[%s],[%s],[%s],[%s],[%s],[%s],[%s]" % (item['lit_type' ],item['lit_title' ],item['lit_url' ],item['lit_writer' ],item['lit_submit' ],item['lit_comments' ],item['lit_last_comments' ])) yield item
T66YItem定义在items.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import scrapyclass T66YItem (scrapy.Item) : lit_type = scrapy.Field() lit_title = scrapy.Field() lit_url = scrapy.Field() lit_writer = scrapy.Field() lit_submit = scrapy.Field() lit_comments = scrapy.Field() lit_last_comments = scrapy.Field() pass
pipeline.py负责抓取后的mongodb存储
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import pymongofrom scrapy.conf import settingsclass T66YPipeline (object) : def __init__ (self) : host = settings['MONGODB_HOST' ] user = settings['MONGODB_USER' ] passwd = settings['MONGODB_PASSWD' ] dbname = settings['MONGODB_DBNAME' ] sheetname = settings['MONGODB_SHEET' ] client = pymongo.MongoClient("mongodb+srv://{0}:{1}@{2}/test?retryWrites=true&w=majority" .format(user,passwd,host)) mydb = client[dbname] self.post = mydb[sheetname] def process_item (self, item, spider) : data = dict(item) self.post.insert(data) return item
若要抓取时同步保存,需要对setting.py进行配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 BOT_NAME = 't66y' SPIDER_MODULES = ['t66y.spiders' ] NEWSPIDER_MODULE = 't66y.spiders' MONGODB_USER = '***' MONGODB_PASSWD = '***' MONGODB_DBNAME = '***' MONGODB_SHEET = '***' MONGODB_HOST = '***.mongodb.net' ROBOTSTXT_OBEY = False DOWNLOAD_DELAY = 5 DEFAULT_REQUEST_HEADERS = { 'Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' , 'Accept-Language' : 'en' , 'User-Agent' :'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36' } ITEM_PIPELINES = { 't66y.pipelines.T66YPipeline' : 300 , }
可以注意到创建工程的时候还有一个middleware.py文件生成,从名字看它应该是一种中间件对吧。其实一般大家用它来更换代理IP(有些网站会查询爬虫的ip,过于频繁的读取会被当成不合规行为,并进行拦截),更换代理IP的代码一般放在此处。当然当碰到网站返回错误要做一些处理的时候,也通常会在这里实现相应代码。好在CL并没有麻烦到需要更换代理IP。
效果 直接看在mongoDB存储的内容。可以看到爬取过程中插入操作增多了,右边是爬取到的数据,文章名称过于暴露就不再显示。
下一章我们介绍:
Jupyter+Pandas+Pyplot进行简单的数据分析。