1. 多进程爬虫

  对于数据量较大的爬虫,对数据的处理要求较高时,可以采用python多进程或多线程的机制完成,多进程是指分配多个CPU处理程序,同一时刻只有一个CPU在工作,多线程是指进程内部有多个类似"子进程"同时在协同工作。python中有多种多个模块可完成多进程和多线程的工作,此处此用multiprocessing模块完成多线程爬虫,测试过程中发现,由于站点具有反爬虫机制,当url地址和进程数目较多时,爬虫会报错。

2. 代码内容

#!/usr/bin/python
#_*_ coding:utf _*_ import re
import time
import requests
from multiprocessing import Pool duanzi_list = [] def get_web_html(url):
'''
@params:获取url地址web站点的html数据
'''
headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0"}
try:
req = requests.get(url,headers=headers)
if req.status_code == 200:
response = req.text.encode('utf8')
except Exception as e:
print e
return response def scrap_qiushi_info(url):
'''
@params:url,获取段子数据信息
'''
html = get_web_html(url)
usernames = re.findall(r'<h2>(.*?)</h2>',html,re.S|re.M)
levels = re.findall('<div class="articleGender \w*Icon">(\d+)</div>',html,re.S|re.M)
laugh_counts = re.findall('<span class="stats-vote">.*?<i class="number">(\d+)</i>',html,re.S|re.M)
comment_counts = re.findall('<i class="number">(\d+)</i> 评论',html,re.S|re.M)
contents = re.findall('<div class="content">.*?<span>(.*?)</span>',html,re.S|re.M)
for username,level,laugh_count,comment_count,content in zip(usernames,levels,laugh_counts,comment_counts,contents):
information = {
"username": username.strip(),
"level": level.strip(),
"laugh_count": laugh_count.strip(),
"comment_count": comment_count.strip(),
"content": content.strip()
}
duanzi_list.append(information)
time.sleep(1)
return duanzi_list def normal_scapper(url_lists):
'''
定义调用函数,使用普通的爬虫函数爬取数据
'''
begin_time = time.time()
for url in url_lists:
scrap_qiushi_info(url)
end_time = time.time()
print "普通爬虫一共耗费时长:%f" % (end_time - begin_time) def muti_process_scapper(url_lists,process_num=2):
'''
定义多进程爬虫调用函数,使用mutiprocessing模块爬取web数据
'''
begin_time = time.time()
pool = Pool(processes=process_num)
pool.map(scrap_qiushi_info,url_lists)
end_time = time.time()
print "%d个进程爬虫爬取所耗费时长为:%s" % (process_num,(end_time - begin_time)) def main():
'''
定义main()函数,程序入口,通过列表推倒式获取url地址,调用爬虫函数
'''
url_lists = ['https://www.qiushibaike.com/text/page/{}'.format(i) for i in range(1,11)]
normal_scapper(url_lists)
muti_process_scapper(url_lists,process_num=2) if __name__ == "__main__":
main()

3. 爬取的数据存入到MongoDB数据库

#!/usr/bin/python
#_*_ coding:utf _*_ import re
import time
import json
import requests
import pymongo
from multiprocessing import Pool duanzi_list = [] def get_web_html(url):
'''
@params:获取url地址web站点的html数据
'''
headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0"}
try:
req = requests.get(url,headers=headers)
if req.status_code == 200:
response = req.text.encode('utf8')
except Exception as e:
print e
return response def scrap_qiushi_info(url):
'''
@params:url,获取段子数据信息
'''
html = get_web_html(url)
usernames = re.findall(r'<h2>(.*?)</h2>',html,re.S|re.M)
levels = re.findall('<div class="articleGender \w*Icon">(\d+)</div>',html,re.S|re.M)
laugh_counts = re.findall('<span class="stats-vote">.*?<i class="number">(\d+)</i>',html,re.S|re.M)
comment_counts = re.findall('<i class="number">(\d+)</i> 评论',html,re.S|re.M)
contents = re.findall('<div class="content">.*?<span>(.*?)</span>',html,re.S|re.M)
for username,level,laugh_count,comment_count,content in zip(usernames,levels,laugh_counts,comment_counts,contents):
information = {
"username": username.strip(),
"level": level.strip(),
"laugh_count": laugh_count.strip(),
"comment_count": comment_count.strip(),
"content": content.strip()
}
duanzi_list.append(information)
return duanzi_list def write_into_mongo(datas):
'''
@datas: 需要插入到mongoDB的数据,封装为字典,通过遍历的方式将数据插入到mongoDB中,insert_one()表示一次插入一条数据
'''
client = pymongo.MongoClient('localhost',27017)
duanzi = client['duanzi_db']
duanzi_info = duanzi['duanzi_info']
for data in datas:
duanzi_info.insert_one(data) def query_data_from_mongo():
'''
查询mongoDB中的数据
'''
client = pymongo.MongoClient('localhost',27017)['duanzi_db']['duanzi_info']
for data in client.find():
print data
print "一共查询到%d条数据" % (client.find().count()) def main():
'''
定义main()函数,程序入口,通过列表推倒式获取url地址,调用爬虫函数
'''
url_lists = ['https://www.qiushibaike.com/text/page/{}'.format(i) for i in range(1,11)]
for url in url_lists:
scrap_qiushi_info(url)
time.sleep(1)
write_into_mongo(duanzi_list) if __name__ == "__main__":
main()
#query_data_from_mongo()

4. 插入至MySQL数据库

  将爬虫获取的数据插入到关系性数据库MySQL数据库中作为永久数据存储,首先需要在MySQL数据库中创建库和表,如下:

1. 创建库
MariaDB [(none)]> create database qiushi;
Query OK, 1 row affected (0.00 sec) 2. 使用库
MariaDB [(none)]> use qiushi;
Database changed 3. 创建表格
MariaDB [qiushi]> create table qiushi_info(id int(32) unsigned primary key auto_increment,username varchar(64) not null,level int default 0,laugh_count int default 0,comment_count int default 0,content text default '')engine=InnoDB charset='UTF8';
Query OK, 0 rows affected, 1 warning (0.06 sec) MariaDB [qiushi]> show create table qiushi_info;
+-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| qiushi_info | CREATE TABLE `qiushi_info` (
`id` int(32) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(64) NOT NULL,
`level` int(11) DEFAULT '0',
`laugh_count` int(11) DEFAULT '0',
`comment_count` int(11) DEFAULT '0',
`content` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

写入到MySQL数据库中的代码如下:

#!/usr/bin/python
#_*_ coding:utf _*_
#blog:http://www.cnblogs.com/cloudlab/ import re
import time
import pymysql
import requests duanzi_list = [] def get_web_html(url):
'''
@params:获取url地址web站点的html数据
'''
headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0"}
try:
req = requests.get(url,headers=headers)
if req.status_code == 200:
response = req.text.encode('utf8')
except Exception as e:
print e
return response def scrap_qiushi_info(url):
'''
@params:url,获取段子数据信息
'''
html = get_web_html(url)
usernames = re.findall(r'<h2>(.*?)</h2>',html,re.S|re.M)
levels = re.findall('<div class="articleGender \w*Icon">(\d+)</div>',html,re.S|re.M)
laugh_counts = re.findall('<span class="stats-vote">.*?<i class="number">(\d+)</i>',html,re.S|re.M)
comment_counts = re.findall('<i class="number">(\d+)</i> 评论',html,re.S|re.M)
contents = re.findall('<div class="content">.*?<span>(.*?)</span>',html,re.S|re.M)
for username,level,laugh_count,comment_count,content in zip(usernames,levels,laugh_counts,comment_counts,contents):
information = {
"username": username.strip(),
"level": level.strip(),
"laugh_count": laugh_count.strip(),
"comment_count": comment_count.strip(),
"content": content.strip()
}
duanzi_list.append(information)
return duanzi_list def write_into_mysql(datas):
'''
@params: datas,将爬虫获取的数据写入到MySQL数据库中
'''
try:
conn = pymysql.connect(host='localhost',port=3306,user='root',password='',db='qiushi',charset='utf8')
cursor = conn.cursor(pymysql.cursors.DictCursor)
for data in datas:
data_list = (data['username'],int(data['level']),int(data['laugh_count']),int(data['comment_count']),data['content'])
sql = "INSERT INTO qiushi_info(username,level,laugh_count,comment_count,content) VALUES('%s',%s,%s,%s,'%s')" %(data_list)
cursor.execute(sql)
conn.commit()
except Exception as e:
print e
cursor.close()
conn.close() def main():
'''
定义main()函数,程序入口,通过列表推倒式获取url地址,调用爬虫函数
'''
url_lists = ['https://www.qiushibaike.com/text/page/{}'.format(i) for i in range(1,11)]
for url in url_lists:
scrap_qiushi_info(url)
time.sleep(1)
write_into_mysql(duanzi_list) if __name__ == "__main__":
main()

5. 将爬虫数据写入到CSV文件

  CSV文件是以逗号,形式分割的文本读写方式,能够通过纯文本或者Excel方式读取,是一种常见的数据存储方式,此处将爬取的数据存入到CSV文件内。

将数据存入到CSV文件代码内容如下:

#!/usr/bin/python
#_*_ coding:utf _*_
#blog:http://www.cnblogs.com/cloudlab/ import re
import csv
import time
import requests duanzi_list = [] def get_web_html(url):
'''
@params:获取url地址web站点的html数据
'''
headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0"}
try:
req = requests.get(url,headers=headers)
if req.status_code == 200:
response = req.text.encode('utf8')
except Exception as e:
print e
return response def scrap_qiushi_info(url):
'''
@params:url,获取段子数据信息
'''
html = get_web_html(url)
usernames = re.findall(r'<h2>(.*?)</h2>',html,re.S|re.M)
levels = re.findall('<div class="articleGender \w*Icon">(\d+)</div>',html,re.S|re.M)
laugh_counts = re.findall('<span class="stats-vote">.*?<i class="number">(\d+)</i>',html,re.S|re.M)
comment_counts = re.findall('<i class="number">(\d+)</i> 评论',html,re.S|re.M)
contents = re.findall('<div class="content">.*?<span>(.*?)</span>',html,re.S|re.M)
for username,level,laugh_count,comment_count,content in zip(usernames,levels,laugh_counts,comment_counts,contents):
information = {
"username": username.strip(),
"level": level.strip(),
"laugh_count": laugh_count.strip(),
"comment_count": comment_count.strip(),
"content": content.strip()
}
duanzi_list.append(information)
return duanzi_list def write_into_csv(datas,filename):
'''
@datas: 需要写入csv文件的数据内容,是一个列表
@params:filename,需要写入到目标文件的csv文件名
'''
with file(filename,'w+') as f:
writer = csv.writer(f)
writer.writerow(('username','level','laugh_count','comment_count','content'))
for data in datas:
writer.writerow((data['username'],data['level'],data['laugh_count'],data['comment_count'],data['content'])) def main():
'''
定义main()函数,程序入口,通过列表推倒式获取url地址,调用爬虫函数
'''
url_lists = ['https://www.qiushibaike.com/text/page/{}'.format(i) for i in range(1,11)]
for url in url_lists:
scrap_qiushi_info(url)
time.sleep(1)
write_into_csv(duanzi_list,'/root/duanzi_info.csv') if __name__ == "__main__":
main()

6. 将爬取数据写入到文本文件中

#!/usr/bin/python
#_*_ coding:utf _*_
#blog:http://www.cnblogs.com/cloudlab/ import re
import csv
import time
import requests duanzi_list = [] def get_web_html(url):
'''
@params:获取url地址web站点的html数据
'''
headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0"}
try:
req = requests.get(url,headers=headers)
if req.status_code == 200:
response = req.text.encode('utf8')
except Exception as e:
print e
return response def scrap_qiushi_info(url):
'''
@params:url,获取段子数据信息
'''
html = get_web_html(url)
usernames = re.findall(r'<h2>(.*?)</h2>',html,re.S|re.M)
levels = re.findall('<div class="articleGender \w*Icon">(\d+)</div>',html,re.S|re.M)
laugh_counts = re.findall('<span class="stats-vote">.*?<i class="number">(\d+)</i>',html,re.S|re.M)
comment_counts = re.findall('<i class="number">(\d+)</i> 评论',html,re.S|re.M)
contents = re.findall('<div class="content">.*?<span>(.*?)</span>',html,re.S|re.M)
for username,level,laugh_count,comment_count,content in zip(usernames,levels,laugh_counts,comment_counts,contents):
information = {
"username": username.strip(),
"level": level.strip(),
"laugh_count": laugh_count.strip(),
"comment_count": comment_count.strip(),
"content": content.strip()
}
duanzi_list.append(information)
return duanzi_list def write_into_files(datas,filename):
'''
定义数据存入写文件的函数
@params:datas需要写入的数据
@filename:将数据写入到指定的文件名
'''
print "开始写入文件.."
with file(filename,'w+') as f:
f.write("用户名" + "\t" + "用户等级" + "\t" + "笑话数" + "\t" + "评论数" + "\t" + "段子内容" + "\n")
for data in datas:
f.write(data['username'] + "\t" + \
data['level'] + "\t" + \
data['laugh_count'] + "\t" + \
data['comment_count'] + "\t" + \
data['content'] + "\n" + "\n"
) def main():
'''
定义main()函数,程序入口,通过列表推倒式获取url地址,调用爬虫函数
'''
url_lists = ['https://www.qiushibaike.com/text/page/{}'.format(i) for i in range(1,11)]
for url in url_lists:
scrap_qiushi_info(url)
time.sleep(1)
write_into_files(duanzi_list,'/root/duanzi.txt') if __name__ == "__main__":
main()

Python多线程爬虫与多种数据存储方式实现(Python爬虫实战2)的更多相关文章

  1. ios中常见数据存储方式以及SQLite常用的语句

    在iOS中,根据不同的需求对应的有多种数据存储方式: 1.NSUserdefaults  将数据存储到沙盒中(library),方便易用,但是只能存储系统提供的数据类型(plist),不能存储自定义的 ...

  2. 05.Python网络爬虫之三种数据解析方式

    引入 回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需要进行指 ...

  3. Python爬虫之三种数据解析方式

    一.引入 二.回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需 ...

  4. 05,Python网络爬虫之三种数据解析方式

    回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需要进行指定数据 ...

  5. 《Python网络爬虫之三种数据解析方式》

    引入 回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需要进行指 ...

  6. Python网络爬虫之三种数据解析方式 (xpath, 正则, bs4)

    引入 回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需要进行指 ...

  7. android的数据存储方式

    数据存储在开发中是使用最频繁的,在这里主要介绍Android平台中实现数据存储的5种方式,分别是: 1 使用SharedPreferences存储数据 2 文件存储数据 3 SQLite数据库存储数据 ...

  8. Android的数据存储方式(转)

    数据存储在开发中是使用最频繁的,在这里主要介绍Android平台中实现数据存储的5种方式,分别是: 1 使用SharedPreferences存储数据 2 文件存储数据 3 SQLite数据库存储数据 ...

  9. Android编程中的5种数据存储方式

    Android编程中的5种数据存储方式 作者:牛奶.不加糖 字体:[增加 减小] 类型:转载 时间:2015-12-03我要评论 这篇文章主要介绍了Android编程中的5种数据存储方式,结合实例形式 ...

随机推荐

  1. Python中List和Tuple类型

    a = 'python' print('hello,', a or 'world') b = '' print ('hello,', b or 'world') print('------------ ...

  2. html5版 音乐播放器

    html5版本音乐播放器,支持iOS设备,案例地址:http://www.xttblog.com/?p=1277 功能说明 支持iOS设备,但是iOS不支持自动下一曲,这是iOS本身限制,支持touc ...

  3. AGC010 - A: Addition

    原题链接 题意简述 给出一个个数的数列,每次选出两个奇偶性相同的数合成一个数,问最终能否只剩下一个数. 分析 非常简单的一道题. 两个偶数可以合成一个偶数,两个奇数也能合成一个偶数.所以合并偶数时偶数 ...

  4. 中小研发团队架构实践之微服务MSA

    一.MSA简介 1.1.MSA是什么 微服务架构MSA是Microservice Architecture的简称,它是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相通讯.互相配合, ...

  5. 转载微信公众号 测试那点事:Jmeter乱码解决

    原文地址: http://mp.weixin.qq.com/s/4Li5z_-rT0HPPQx9Iyi5UQ  中文乱码一直都是比较让人棘手的问题,我们在使用Jmeter的过程中,也会遇到中文乱码问题 ...

  6. java:list排序

    第一种方法:就是list中对象(bean文件)实现Comparable接口,代码如下: package com.mapred.entity; public class Bar implements C ...

  7. 2.4 PCI总线的配置

    PCI总线定义了两类配置请求,一个是Type 00h配置请求,另一个是Type 01h配置请求.PCI总线使用这些配置请求访问PCI总线树上的设备配置空间,包括PCI桥和PCI Agent设备的配置空 ...

  8. 《实战Nginx》读书笔记--Nginx配置文件

    先看下一份的Nginx 的配置 #user nobody nobody;#使用的用户和组 worker_processes 4;#工作进程的个数,一般等于CPU核数或者总核数的两倍 #error_lo ...

  9. CAN总线基础知识(二)

    CAN协议和标准规范 1 由ISO标准化的CAN协议 CAN协议已经由ISO标准化,有2个版本,如ISO11898和ISO11519-2,它们之间在数据链路层没什么不同,但是在物理层有些区别. (1) ...

  10. 初试 Windows XP Embedded 系统开发1

    目前 Windows PE(Preinstallation Environment)和 Windows XP Embedded 是可以脱离主机里的硬盘独立运行的 Windows 操作系统,Window ...