python链家网高并发异步爬虫asyncio+aiohttp+aiomysql异步存入数据
python链家网二手房异步IO爬虫,使用asyncio、aiohttp和aiomysql
很多小伙伴初学python时都会学习到爬虫,刚入门时会使用requests、urllib这些同步的库进行单线程爬虫,速度是比较慢的,后学会用scrapy框架进行爬虫,速度很快,原因是scrapy是基于twisted多线程异步IO框架。
本例使用的asyncio也是一个异步IO框架,在python3.5以后加入了协程的关键字async,能够将协程和生成器区分开来,更加方便使用协程。
经过测试,平均1秒可以爬取30个详情页信息
可以使用asyncio.Semaphore来控制并发数,达到限速的效果


# -*- coding: utf-8 -*-
"""
:author: KK
:url: http://github.com/PythonerKK
:copyright: © 2019 KK <705555262@qq.com.com>
"""
import asyncio
import re
import aiohttp
from pyquery import PyQuery
import aiomysql
from lxml import etree
pool = ''
#sem = asyncio.Semaphore(4) 用来控制并发数,不指定会全速运行
stop = False
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36'
}
MAX_PAGE = 10
TABLE_NAME = 'data' #数据表名
city = 'zh' #城市简写
url = 'https://{}.lianjia.com/ershoufang/pg{}/' #url地址拼接
urls = [] #所有页的url列表
links_detail = set() #爬取中的详情页链接的集合
crawled_links_detail = set() #爬取完成的链接集合,方便去重
async def fetch(url, session):
'''
aiohttp获取网页源码
'''
# async with sem:
try:
async with session.get(url, headers=headers, verify_ssl=False) as resp:
if resp.status in [200, 201]:
data = await resp.text()
return data
except Exception as e:
print(e)
def extract_links(source):
'''
提取出详情页的链接
'''
pq = PyQuery(source)
for link in pq.items("a"):
_url = link.attr("href")
if _url and re.match('https://.*?/\d+.html', _url) and _url.find('{}.lianjia.com'.format(city)):
links_detail.add(_url)
print(links_detail)
def extract_elements(source):
'''
提取出详情页里面的详情内容
'''
try:
dom = etree.HTML(source)
id = dom.xpath('//link[@rel="canonical"]/@href')[0]
title = dom.xpath('//title/text()')[0]
price = dom.xpath('//span[@class="unitPriceValue"]/text()')[0]
information = dict(re.compile('<li><span class="label">(.*?)</span>(.*?)</li>').findall(source))
information.update(title=title, price=price, url=id)
print(information)
asyncio.ensure_future(save_to_database(information, pool=pool))
except Exception as e:
print('解析详情页出错!')
pass
async def save_to_database(information, pool):
'''
使用异步IO方式保存数据到mysql中
注:如果不存在数据表,则创建对应的表
'''
COLstr = '' # 列的字段
ROWstr = '' # 行字段
ColumnStyle = ' VARCHAR(255)'
for key in information.keys():
COLstr = COLstr + ' ' + key + ColumnStyle + ','
ROWstr = (ROWstr + '"%s"' + ',') % (information[key])
# 异步IO方式插入数据库
async with pool.acquire() as conn:
async with conn.cursor() as cur:
try:
await cur.execute("SELECT * FROM %s" % (TABLE_NAME))
await cur.execute("INSERT INTO %s VALUES (%s)"%(TABLE_NAME, ROWstr[:-1]))
print('插入数据成功')
except aiomysql.Error as e:
await cur.execute("CREATE TABLE %s (%s)" % (TABLE_NAME, COLstr[:-1]))
await cur.execute("INSERT INTO %s VALUES (%s)" % (TABLE_NAME, ROWstr[:-1]))
except aiomysql.Error as e:
print('mysql error %d: %s' % (e.args[0], e.args[1]))
async def handle_elements(link, session):
'''
获取详情页的内容并解析
'''
print('开始获取: {}'.format(link))
source = await fetch(link, session)
#添加到已爬取的集合中
crawled_links_detail.add(link)
extract_elements(source)
async def consumer():
'''
消耗未爬取的链接
'''
async with aiohttp.ClientSession() as session:
while not stop:
if len(urls) != 0:
_url = urls.pop()
source = await fetch(_url, session)
print(_url)
extract_links(source)
if len(links_detail) == 0:
print('目前没有待爬取的链接')
await asyncio.sleep(2)
continue
link = links_detail.pop()
if link not in crawled_links_detail:
asyncio.ensure_future(handle_elements(link, session))
async def main(loop):
global pool
pool = await aiomysql.create_pool(host='127.0.0.1', port=3306,
user='root', password='xxxxxx',
db='aiomysql_lianjia', loop=loop, charset='utf8',
autocommit=True)
for i in range(1, MAX_PAGE):
urls.append(url.format(city, str(i)))
print('爬取总页数:{} 任务开始...'.format(str(MAX_PAGE)))
asyncio.ensure_future(consumer())
if __name__ == '__main__':
loop = asyncio.get_event_loop()
asyncio.ensure_future(main(loop))
loop.run_forever()
python链家网高并发异步爬虫asyncio+aiohttp+aiomysql异步存入数据的更多相关文章
- python链家网高并发异步爬虫and异步存入数据
python链家网二手房异步IO爬虫,使用asyncio.aiohttp和aiomysql 很多小伙伴初学python时都会学习到爬虫,刚入门时会使用requests.urllib这些同步的库进行单线 ...
- Pyspider爬虫简单框架——链家网
pyspider 目录 pyspider简单介绍 pyspider的使用 实战 pyspider简单介绍 一个国人编写的强大的网络爬虫系统并带有强大的WebUI.采用Python语言编写,分布式架构, ...
- 使用python抓取并分析数据—链家网(requests+BeautifulSoup)(转)
本篇文章是使用python抓取数据的第一篇,使用requests+BeautifulSoup的方法对页面进行抓取和数据提取.通过使用requests库对链家网二手房列表页进行抓取,通过Beautifu ...
- Python的scrapy之爬取链家网房价信息并保存到本地
因为有在北京租房的打算,于是上网浏览了一下链家网站的房价,想将他们爬取下来,并保存到本地. 先看链家网的源码..房价信息 都保存在 ul 下的li 里面 爬虫结构: 其中封装了一个数据库处理模 ...
- 分享系列--面试JAVA架构师--链家网
本月7日去了一趟链家网面试,虽然没有面上,但仍有不少收获,在此做个简单的分享,当然了主要是分享给自己,让大家见笑了.因为这次是第一次面试JAVA网站架构师相关的职位,还是有些心虚的,毕竟之前大部分时间 ...
- Scrapy实战篇(一)之爬取链家网成交房源数据(上)
今天,我们就以链家网南京地区为例,来学习爬取链家网的成交房源数据. 这里推荐使用火狐浏览器,并且安装firebug和firepath两款插件,你会发现,这两款插件会给我们后续的数据提取带来很大的方便. ...
- TOP100summit:【分享实录】链家网大数据平台体系构建历程
本篇文章内容来自2016年TOP100summit 链家网大数据部资深研发架构师李小龙的案例分享. 编辑:Cynthia 李小龙:链家网大数据部资深研发架构师,负责大数据工具平台化相关的工作.专注于数 ...
- Scrapy实战篇(九)之爬取链家网天津租房数据
以后有可能会在天津租房子,所以想将链家网上面天津的租房数据抓下来,以供分析使用. 思路: 1.以初始链接https://tj.lianjia.com/zufang/rt200600000001/?sh ...
- 链家网爬虫同步VS异步执行时间对比
异步执行时间 import time import asyncio import aiohttp from lxml import etree start_time = time.time() asy ...
随机推荐
- ssm简单整合(注释方法)
1.创建web工程,选择web.xml文件,并导入相关jar包(使用的spring4.0以上版本,) 2.配置web.xml文件,包括spring.xml,springMVC.xml的加载映射,核心操 ...
- MEF 插件式开发之 DotNetCore 中强大的 DI
背景叙述 在前面几篇 MEF 插件式开发 系列博客中,我分别在 DotNet Framework 和 DotNet Core 两种框架下实验了 MEF 的简单实验,由于 DotNet Framewor ...
- (二)在实战中使用Sass和Compass
第三章 无需计算玩转CSS网格布局 3.1 网格布局介绍 3.2 使用网格布局 3.2.1 术语 术语名 定义 是否涉及HTML标签 列 内容度量的垂直单位 否 容器 构成一个网格布局的HTML元素 ...
- CSS元素(文本、图片)水平垂直居中方法
1.text-align:center; 2.margin:0 auto; 3.display:inline-block; + text-align:center; 4.position:relati ...
- JavaScript数组学习总结
数组 数组 1.数组:数组是一组数据(数据类型不限,任意)的有序集合===>我们写代码,一般一个数组只放一种数据类型的数据 2.我们写代码,一般一个数组只放一种类型的数据 3.注意: 大多数 ...
- 性能测试 Apache参数配置与性能调优
Apache性能调优 by:授客 QQ:1033553122 环境: Apache 2.4 1.选择合适的MPM(Multi -Processing Modules, 多处理模块) Unix/Linu ...
- tomcat 取消项目名访问路径
在server.xml 里,<host>...</host>的标签之间添加<Context path="" docBase="projec ...
- js调用android本地java代码
js调用android本地java代码 当在Android上使用WebView控件开发一个Web应用时,可以创建一个通过Javascript调用Android端java代码的接口.也就是可以通过Jav ...
- Nodejs 安装 on centos7
本文演示如何在CentOS7上安装Nodejs. 1 准备工作 1.1 浏览器访问安装包下载地址: https://nodejs.org/dist/ 找到需要安装的版本,以8.11.3版本为例,地址为 ...
- Video.js web视频播放器
免费视频播放器videojs中文教程 Video.js是一款web视频播放器,支持html5和flash两种播放方式.更多关于video.js的介绍,可以访问官方网站介绍,我之前也写过一篇关于vide ...