python多线程小爬虫之练练手
序:
叮咚叮咚,走过路过不要错过啊。。。
好久没写博客,上次都是几年前了,写过一些android的文章,然而我连账号都忘记了,真尼玛。。。
大数据时代,人工智能,机器学习开始流行了,赶上了这个时代是好的,也是不那么好的,好的是将会为社会带来革命性的洗礼,不那么好的是感觉出生还是太早了点哈哈哈,要是晚几十年生,等我风华正茂的时候,那是多壮观的世界,yy中.....
正文:
好了 ,上个线程还在沉浸在yy中,作为一个多任务处理的灵长类,必须开个线程要说点正事了。
大家都知道机器学习是需要大量的数据来训练模型,通过大量训练模型才能自我进化,然而我们不是在BAT这样的巨头的话,是很难获得巨额数据的,那只能干个苦力活自己去网上找咯,身为程序员还是要让代码来做吧,爬虫就很适合啦,刚好python就是爬虫的利器,之前学习的时候写了个爬百度贴吧评论的小爬虫,贴出来先献丑啦(吸取硬盘挂了的教训,写过的轮子交给csdn帮我保存吧 /大哭/大哭)
用到的知识:
python多线程
xpath
python的多线程是一一映射到系统层的,也就是说,每开一个python的线程,其内部也会调用系统接口去开启一个对应的系统级别的C程序线程,真正干活的就是这些对应c线程,但是这些c线程是系统级的,使用python的我们在代码级层面是无法控制它们的,失去控制的线程时可怕的,说白了就会乱搞数据,所以就有了著名的GIL,它帮助我们控制这些c线程。
学习python的都知道,python的GIL(全局解释锁,解释器Cpython加入的一种机制)是个麻烦的家伙,由于它的限制作用,使得程序在同一个时刻只有一个C线程在工作,无法充分发挥cpu多核心多线程的能力,就相当于单核作战(本质上就相当于单核CPU通过不断的分配时间片来模拟多线程的方法),换言之就是你的工厂有8个人,但是他们都不同时工作,根据策略切换,每次切换只有一个人在干活,其他7个人傻愣着,这就恶心了,你工厂的效能就无法全部发挥出来,所以正因为这个点,python无法真正做到并行,只是并发(伪并行,一起启动,但不能一起执行),但是我们要注意的是GIL只是python解释器内核级的锁,解释器上层还有用户层,用户层面python也提供了lock类,因为GIL的存在只是相当于把多核变成了单核,但无论多核还是单核,对于操作共有资源,并发操作,存在资源竞争的话就几乎会有锁的应用,不然数据混乱往往就会发生在线程切换时,每个线程看到的资源都会不一样了,所以在单核时代多线程也是会加锁的,举个例子:
import threading,time,random
sum = 0
class Sum(threading.Thread):def run(self):global sumfor i in range(2):time.sleep(random.randint(50,100)/100.0)# 仔细对比如果不加锁,有时候会最终结果出现199,甚至198,要有耐心,不容易出现,# 并发运行中包含资源竞争就一定会用锁,我们可以做的是将锁的粒度降到最小 并且找出原子操作...# lock.acquire() sum += 1# ock.release() python3测试了下不需要再我们代码加锁了,貌似对解释器做了优化,我猜测是在target指向的函数外层默认加了把锁。print sum
for i in range(100):s = Sum()s.start()
在前端页面中很多标签,在javaWeb中有三种方法解析xml里的标签,分别是Dom解析,sex解析和pull解析,Dom解析是把整个文档树封装成对象载入内存,再去获取你想要的节点,这样使得无论你处于哪个节点你都能获得上下文,而sex解析是逐行解析的,所以不知道当前节点的前后关系。。。哎妈呀,扯远了。。
xpath是一种技术,是一种语言规则,通过使用这种语言规则可以使得在解析页面的时候可以类似js那样通过Dom对象来获取前端页面中的各个节点(注意,只是个人感觉大概类似,用法是不一样的),以此来获取节点中的数据,xpath就封装在lxml的模块中,可以通过pip install lxml来导入模块,有些同学可以会说BeautifulSoup也很不错,确实就用户友好性而言,BeautifulSoup甩了xpath几条街。。。,但是就性能而言xpath是用c语言实现的,BeautifulSoup是用python实现的,xpath在速度上是有优势的,你想想还有除了汇编还有啥比c快的。。。,而且BeautifulSoup是基于Dom解析的,是把整个文档数加载进内存的,比较占用内存资源,查找起来也比较就耗时了,但是就使用友好性来说,BeautifulSoup总算是扳回一局了,举个例子:
title = soup.select('.title.content div .cc') #BeautifulSoup支持css选择器,够人性啊
title = selector.xpath("//div[@class='content']/div[@class='content']/") #这xpath看起来就感觉复杂很多了,不过我觉得本质上也是逐层往下选择的。。。
综合各方面,只要用多了我觉得xpath还是很有可取之处的,偏向于xpath吧,至于最后的正则表达式,恩!!!此时脑海中飘过一堆(.*?),.*,我不想说。。 好难记啊,基于理解去记忆都难,但是该用的时候还得用不是么....一万点悲伤
前面说完了要用的东西也说了下自己掌握的知识,现在就要用上了,贴代码。。
#coding=utf8
from lxml import html
from lxml import etree
import requests
import json
from multiprocessing.dummy import Pool as ThreadPool
import sys
reload(sys) #模块加载时sys.setdefaultencoding被通过反射删除了,要使用需重新加载
sys.setdefaultencoding('utf-8')def write_to_txt(comment):f.writelines('评论用户:' + comment['user_name'] + '\n')f.writelines('用户ID:' + str(comment['user_id']) + '\n') #注意json中有恶心的数据。。。f.writelines('评论内容:' + comment['comment'] + '\n')f.writelines('评论时间:' + comment['date'] + '\n')f.writelines('\n\n')def get_content(url):# 这里用的requests的模块,在https下是有问题的,我这里是http,看不出来,客官可自行调试https会报openssl的错,在centos下有些可以有些不可以,windows下100%错# 因为我windows没装openssl证书哈哈哈,还要下载个vs编译,太大了,我就换种方式了。。。# 在python3上requests就应该没问题了,因为人家提示你升级啦,python2的使用urllib2吧,我试了https没问题data = requests.get(url)selector = etree.HTML(data.text)#//表示从根节点开始,关于xpath的语法大家要自行去预习啦comment_list = selector.xpath('//div[@class="l_post j_l_post l_post_bright "]')item = {}for each in comment_list:try:json_obj = json.loads(each.xpath('@data-field')[0])item['user_name'] = json_obj['author']['user_name']item['user_id'] = json_obj['author']['user_id']item['date'] = json_obj['content']['date']#这里的这么一大串无非就是逐层标签往下找,class的就在前段页面copy,因为不是从根节点开始找了,所以无需//开头comment = each.xpath('div[@class="d_post_content_main"]/div/cc/div[@class="d_post_content j_d_post_content clearfix"]/text()')[0]item['comment'] = comment#因为没有做同步,最后爬出来的数据仔细看时间会发现是乱序的,but没关系,我们只是看数据内容,顺序无妨write_to_txt(item)except Exception as e:continuereturnif __name__ == '__main__':pool = ThreadPool(4)f = open('teiba_cpmment', 'w')url_list = []for i in range(1, 21):#经过分析,某帖子的翻页只是参数的变化,那就比较简单了url = "http://tieba.baidu.com/p/3522395718?pn=%s" %i url_list.append(url)#这里使用了multiprocessing.dummy里面的一个线程池,它还有个进程池,还有一种常规方式就是使用for循环,某天发现居然还能通过map函数来实现并发,一句话的事啊#略叼略叼,for循环方式好好在可能拿到线程的集合,方便对线程做存活判断,下一篇我再写个for循环的,域名逐层爬链接,配合下队列实现pool.map(get_content, url_list)pool.close()pool.join()f.close()
爬出来的的结果:
值得注意的是这个效果是分析url和前端页面标签后配合xpath得出的,如果小伙伴们换了url要重新分析xpath的筛选字符哦,比如抓个https的试试啦啦啦
大概就是爬出来这些,20页除去报错的也有差不几百条了,一个用户算一条吧,展示的图片数据我做了id和和用户名更改的,虽然去网页上能直接看到,但是还是
不要这么直接啦,小小保护哈哈哈。。。每次写文章都写很久。。。五一快乐,洗个澡睡觉觉。
python多线程小爬虫之练练手相关推荐
- python多线程爬虫实例-Python多线程在爬虫中的应用
题记:作为测试工程师经常需要解决测试数据来源的问题,解决思路无非是三种:(1)直接从生产环境拷贝真实数据 (2)从互联网上爬取数据 (3)自己用脚本或者工具造数据.前段时间,为了获取更多的测试数据,笔 ...
- python多线程异步爬虫-Python异步爬虫试验[Celery,gevent,requests]
以往爬虫都是用自己写的一个爬虫框架,一群Workers去Master那领取任务后开始爬.进程数量等于处理器核心数,通过增开线程数提高爬取速度. 最近看了Celery,接口真是优美,挺想试验下异步模型来 ...
- kdj python实现_一颗韭菜的自我修养:用Python分析下股市,练练手
一颗韭菜的自我修养. 机器之心报道,编辑:魔王.陈萍. 股市跌宕起伏.7 月初 A 股飙升,股票瞬间成为大家的热门讨论话题,「现在入场还来得及吗?」几乎成为新的问候语. 然而,经历了连续近 10 个交 ...
- python mysql股票分析_一颗韭菜的自我修养:用Python分析下股市,练练手
股市跌宕起伏.7 月初 A 股飙升,股票瞬间成为大家的热门讨论话题,「现在入场还来得及吗?」几乎成为新的问候语. 然而,经历了连续近 10 个交易日的快牛行情后,上证指数上涨势头放缓.这是牛市,还是熊 ...
- python 计算每日累计_一颗韭菜的自我修养:用 Python 分析下股市,练练手
(给Python开发者加星标,提升Python技能) 来源:机器之心 一颗韭菜的自我修养. 股市跌宕起伏.7 月初 A 股飙升,股票瞬间成为大家的热门讨论话题,「现在入场还来得及吗?」几乎成为新的问候 ...
- 一颗韭菜的自我修养:用Python分析下股市,练练手
一颗韭菜的自我修养. 股市跌宕起伏.7 月初 A 股飙升,股票瞬间成为大家的热门讨论话题,「现在入场还来得及吗?」几乎成为新的问候语. 然而,经历了连续近 10 个交易日的快牛行情后,上证指数上涨势头 ...
- python怎么计算总值_一颗韭菜的自我修养:用Python分析下股市,练练手
一颗韭菜的自我修养. 机器之心报道,编辑:魔王.陈萍. 股市跌宕起伏.7 月初 A 股飙升,股票瞬间成为大家的热门讨论话题,「现在入场还来得及吗?」几乎成为新的问候语. 然而,经历了连续近 10 个交 ...
- python多线程队列爬虫流程图_python 多线程爬虫 队列queue问题。
思路是 先构造url列表 all_url 然后 for i in range(0, len(all_url)): urlqueue.put(all_url[i]) 然后get 做到每次从列表中取出ur ...
- 斗图斗不过小伙伴?python多线程爬取斗图网表情包,助你成为斗图帝!
最近python基础课讲到了多线程,老师让交个多线程的实例练习.于是来试试多线程爬虫,正好复习一下mooc上自学的嵩天男神的爬虫知识.想法很美好,过程却很心酸,从早上开始写,每次出现各种奇怪问题,到现 ...
最新文章
- Lucene 简单手记
- bloom filter 的Java 版
- 关于farpoint公司的控件:SPREAD for .NET Windows Forms Ed.的一些简单方法.
- 计算机英语input,人教版高中英语选修计算机英语VoiceInput.ppt
- c语言中switch函数6,C语言萌新,想问问如何让下面那个switch函数输出的结果继续...
- Python 3.4中文编码
- 线程同步:喂,SHE
- Kaggle —— 泰坦尼克号
- 英特尔cpu与主板芯片组对应关系(包含12代)
- CTF密码学之RSA攻击算法
- 半加器设计(结构描述法)
- 单击即可提高游戏速度:什么是可调整大小的BAR?
- 斐讯k2搭建php环境,斐讯K2T SDK编译环境
- ROS机器人建模与仿真(一)——URDF模型的建立和改进
- Nginx控制IP(段)的访问策略配置
- 针对C64x+的一些优化经验(转帖)
- MySQL基础教程系列-约束(三)唯一约束
- 基于88E6095的链路冗余协议开发(四)
- python2 python3 通信_基于Python的串口通信(2)
- 错误:【terminate called after throwing an instance of 'std::logic_err】