热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python链家网高并发异步爬虫asyncio+aiohttp+aiomysql异步存入数据

python链家网二手房异步IO爬虫,使用asyncio、aiohttp和aiomysql很多小伙伴初学python时都会学习到爬虫,刚入门时会使用re

python链家网二手房异步IO爬虫,使用asyncio、aiohttp和aiomysql

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

1579698-20190305120650251-1695379729.png
1579698-20190305120658440-746826969.png

# -*- coding: utf-8 -*-
""":author: KK:url: http://github.com/PythonerKK:copyright: © 2019 KK <705555262&#64;qq.com.com>
"""
import asyncio
import re
import aiohttp
from pyquery import PyQuery
import aiomysql
from lxml import etreepool &#61; &#39;&#39;
#sem &#61; asyncio.Semaphore(4) 用来控制并发数&#xff0c;不指定会全速运行
stop &#61; False
headers &#61; {&#39;User-Agent&#39;: &#39;Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36&#39;
}
MAX_PAGE &#61; 10
TABLE_NAME &#61; &#39;data&#39; #数据表名
city &#61; &#39;zh&#39; #城市简写
url &#61; &#39;https://{}.lianjia.com/ershoufang/pg{}/&#39; #url地址拼接
urls &#61; [] #所有页的url列表
links_detail &#61; set() #爬取中的详情页链接的集合
crawled_links_detail &#61; set() #爬取完成的链接集合&#xff0c;方便去重async def fetch(url, session):&#39;&#39;&#39;aiohttp获取网页源码&#39;&#39;&#39;# async with sem:try:async with session.get(url, headers&#61;headers, verify_ssl&#61;False) as resp:if resp.status in [200, 201]:data &#61; await resp.text()return dataexcept Exception as e:print(e)def extract_links(source):&#39;&#39;&#39;提取出详情页的链接&#39;&#39;&#39;pq &#61; PyQuery(source)for link in pq.items("a"):_url &#61; link.attr("href")if _url and re.match(&#39;https://.*?/\d&#43;.html&#39;, _url) and _url.find(&#39;{}.lianjia.com&#39;.format(city)):links_detail.add(_url)print(links_detail)def extract_elements(source):&#39;&#39;&#39;提取出详情页里面的详情内容&#39;&#39;&#39;try:dom &#61; etree.HTML(source)id &#61; dom.xpath(&#39;//link[&#64;rel&#61;"canonical"]/&#64;href&#39;)[0]title &#61; dom.xpath(&#39;//title/text()&#39;)[0]price &#61; dom.xpath(&#39;//span[&#64;class&#61;"unitPriceValue"]/text()&#39;)[0]information &#61; dict(re.compile(&#39;

  • (.*?)(.*?)
  • &#39;).findall(source))information.update(title&#61;title, price&#61;price, url&#61;id)print(information)asyncio.ensure_future(save_to_database(information, pool&#61;pool))except Exception as e:print(&#39;解析详情页出错&#xff01;&#39;)passasync def save_to_database(information, pool):&#39;&#39;&#39;使用异步IO方式保存数据到mysql中注&#xff1a;如果不存在数据表&#xff0c;则创建对应的表&#39;&#39;&#39;COLstr &#61; &#39;&#39; # 列的字段ROWstr &#61; &#39;&#39; # 行字段ColumnStyle &#61; &#39; VARCHAR(255)&#39;for key in information.keys():COLstr &#61; COLstr &#43; &#39; &#39; &#43; key &#43; ColumnStyle &#43; &#39;,&#39;ROWstr &#61; (ROWstr &#43; &#39;"%s"&#39; &#43; &#39;,&#39;) % (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(&#39;插入数据成功&#39;)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(&#39;mysql error %d: %s&#39; % (e.args[0], e.args[1]))async def handle_elements(link, session):&#39;&#39;&#39;获取详情页的内容并解析&#39;&#39;&#39;print(&#39;开始获取: {}&#39;.format(link))source &#61; await fetch(link, session)#添加到已爬取的集合中crawled_links_detail.add(link)extract_elements(source)async def consumer():&#39;&#39;&#39;消耗未爬取的链接&#39;&#39;&#39;async with aiohttp.ClientSession() as session:while not stop:if len(urls) !&#61; 0:_url &#61; urls.pop()source &#61; await fetch(_url, session)print(_url)extract_links(source)if len(links_detail) &#61;&#61; 0:print(&#39;目前没有待爬取的链接&#39;)await asyncio.sleep(2)continuelink &#61; links_detail.pop()if link not in crawled_links_detail:asyncio.ensure_future(handle_elements(link, session))async def main(loop):global poolpool &#61; await aiomysql.create_pool(host&#61;&#39;127.0.0.1&#39;, port&#61;3306,user&#61;&#39;root&#39;, password&#61;&#39;xxxxxx&#39;,db&#61;&#39;aiomysql_lianjia&#39;, loop&#61;loop, charset&#61;&#39;utf8&#39;,autocommit&#61;True)for i in range(1, MAX_PAGE):urls.append(url.format(city, str(i)))print(&#39;爬取总页数&#xff1a;{} 任务开始...&#39;.format(str(MAX_PAGE)))asyncio.ensure_future(consumer())if __name__ &#61;&#61; &#39;__main__&#39;:loop &#61; asyncio.get_event_loop()asyncio.ensure_future(main(loop))loop.run_forever()

    转:https://www.cnblogs.com/PyKK2019/p/aiohttp_spider.html



    推荐阅读
    • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
    • 微软头条实习生分享深度学习自学指南
      本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
    • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
      本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
    • Android中高级面试必知必会,积累总结
      本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
    • Centos7.6安装Gitlab教程及注意事项
      本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
    • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
    • Android实战——jsoup实现网络爬虫,糗事百科项目的起步
      本文介绍了Android实战中使用jsoup实现网络爬虫的方法,以糗事百科项目为例。对于初学者来说,数据源的缺乏是做项目的最大烦恼之一。本文讲述了如何使用网络爬虫获取数据,并以糗事百科作为练手项目。同时,提到了使用jsoup需要结合前端基础知识,以及如果学过JS的话可以更轻松地使用该框架。 ... [详细]
    • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了软件测试知识点之数据库压力测试方法小结相关的知识,希望对你有一定的参考价值。 ... [详细]
    • 第七课主要内容:多进程多线程FIFO,LIFO,优先队列线程局部变量进程与线程的选择线程池异步IO概念及twisted案例股票数据抓取 ... [详细]
    • YOLOv7基于自己的数据集从零构建模型完整训练、推理计算超详细教程
      本文介绍了关于人工智能、神经网络和深度学习的知识点,并提供了YOLOv7基于自己的数据集从零构建模型完整训练、推理计算的详细教程。文章还提到了郑州最低生活保障的话题。对于从事目标检测任务的人来说,YOLO是一个熟悉的模型。文章还提到了yolov4和yolov6的相关内容,以及选择模型的优化思路。 ... [详细]
    • MySQL语句大全:创建、授权、查询、修改等【MySQL】的使用方法详解
      本文详细介绍了MySQL语句的使用方法,包括创建用户、授权、查询、修改等操作。通过连接MySQL数据库,可以使用命令创建用户,并指定该用户在哪个主机上可以登录。同时,还可以设置用户的登录密码。通过本文,您可以全面了解MySQL语句的使用方法。 ... [详细]
    • 上图是InnoDB存储引擎的结构。1、缓冲池InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。因此可以看作是基于磁盘的数据库系统。在数据库系统中,由于CPU速度 ... [详细]
    • HashMap的相关问题及其底层数据结构和操作流程
      本文介绍了关于HashMap的相关问题,包括其底层数据结构、JDK1.7和JDK1.8的差异、红黑树的使用、扩容和树化的条件、退化为链表的情况、索引的计算方法、hashcode和hash()方法的作用、数组容量的选择、Put方法的流程以及并发问题下的操作。文章还提到了扩容死链和数据错乱的问题,并探讨了key的设计要求。对于对Java面试中的HashMap问题感兴趣的读者,本文将为您提供一些有用的技术和经验。 ... [详细]
    • MySQL数据库锁机制及其应用(数据库锁的概念)
      本文介绍了MySQL数据库锁机制及其应用。数据库锁是计算机协调多个进程或线程并发访问某一资源的机制,在数据库中,数据是一种供许多用户共享的资源,如何保证数据并发访问的一致性和有效性是数据库必须解决的问题。MySQL的锁机制相对简单,不同的存储引擎支持不同的锁机制,主要包括表级锁、行级锁和页面锁。本文详细介绍了MySQL表级锁的锁模式和特点,以及行级锁和页面锁的特点和应用场景。同时还讨论了锁冲突对数据库并发访问性能的影响。 ... [详细]
    • Oracle 和 mysql的9点区别【MySQL】
      数据库|mysql教程oracle,Oracle,money,mysql,coun数据库-mysql教程1.组函数用法规则mysql中组函数在select语句中可以随意使用,但在o ... [详细]
    author-avatar
    哈行小DWW_421
    这个家伙很懒,什么也没留下!
    PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有