不知道这里有没有喜欢刷it之家的小伙伴,我反正每天早上醒来第一件事就是打开it之家,看看有没有新鲜的段子 逃~

其实这次是要来抓取it之家的热门评论,因为数量较多(上万),所以我们这次采用MongoDB来存数数据

关键词:

这次爬虫不像原本的小脚本啦,

对速度和质量都有比较高的要求,

所以会涉及到一些我原本没有介绍的知识:Ajax

多进程

MongoDB

生成器...

先来看一下成果

数据库展示:

这是MongoDB的GUI软件(RoBo 3T)的截图

可以看到 在 ithome这个数据库里我们

抓到了 21745条object 即21745条热门评论

点开一条记录是这样显示的:

既抓取的内容为:

发帖人、评论内容、手机厂商、手机型号、位置、时间

爬虫运行的时候是这样的:

思路分析

首先看一下项目目录:

.

├── __pycache__

│ ├── config.cpython-36.pyc

│ └── pipeline.cpython-36.pyc

├── apple.json # 导出的数据结果

├── config.py # 数据库的配置信息

├── datahandleer.py # 数据后期处理的文件

├── pipeline.py # 数据处理

└── spider.py # 爬虫主文件

如和获取热评呢

一开始肯定是直接尝试用requests访问新闻的链接,

并用解析工具解析出热评的位置,在抓取就好

可是我尝试后发现,requests抓去下来的源文件

并没有评论的内容

仔细一想,那一般是通过ajax来动态加载内容的用到ajax的情形一般是这样的:你访问一个网页,不用刷新跳转,只要点一个按钮,或者鼠标往下滚,新的信息就会自动出来,例如Facebook的timeline

猜到了大概方向之后,

我们 切换到开发者工具的 Network

并勾选Preserve log

最后切换到 XHR这个标签页

这个时候我们在刷新页面,就能捕捉到网页的各种请求了。

热评是在一个名为(getajaxdata.aspx)的连接里出来的

通过这个名字,大家也能看出来这是一个ajax请求吧?

我们再来看一下这个请求的headers

newsID:323076 type:hotcomment

再仔细的分析一下,发现这个newsid 就明文写在新闻的url之中

我们重新整理一下思路热评是通过ajax请求获取的

该POST请求需要两个参数:newsid 、type

那是不是意味着,我们不需要访问新闻的页面,

直接向it之家ajax服务器发送符合要求的请求就可以获取到数据呢?

我直接告诉你们,是可以的!

那么,只剩下一个问题了:

newsid如何获取呢?

这个其实更简单了,我们只要点开随便一个新闻分类

我这里用苹果作为演示分类

打开这个页面,发现所有的新闻链接都包裹在li 标签之中,

我们只需要找到并用办法解析出最后的newsid就可以了。

等等,最下面那个红色按钮是不是感到很眼熟?

是不是又是通过Ajax请求来获取下一页的新闻?

当然是的!(这里我就不截图演示了,大家可以自己去尝试一下分析)

爬虫流程

当所有的思路都通顺之后,

我们的热评爬虫是这样运行的:spider不停的访问某一新闻分类下的page页面,并获取newsid

将newisd 交给hotcomment爬虫来爬取热评数据

将数据交给pipeline里的函数,

最后将数据存入数据库

代码展示:

由于前面的思路已经详细的讲过了

代码里也有比较详细的注释,

我就不一一说明了

获取newsid的部分

def parse_news_id(categoryid, page_start):

'''找到当前分类下首页的文章的idretrun newsid '''

data = {

'categoryid': categoryid,

'type': 'pccategorypage',

'page': '1',

}

# 循环获取newsid 最早可到2014年12月

# 默认每次取10页

for page in range(page_start, page_start + 11):

data['page'] = str(page)

try:

r = requests.post(

'http://it.ithome.com/ithome/getajaxdata.aspx', data=data)

soup = BeautifulSoup(r.text, 'lxml')

news_list = soup.find_all('a', class_='list_thumbnail')

# 找到当前页的所有新闻链接之后,用生成器返回newsid

for news in news_list:

yield news['href'].split('/')[-1].replace('.htm', '')

except:

return None

这里我稍微说一下,

这里用到了关键字 yeild

这样,就将我们的parse_news_id()函数变成了一个生成器函数用起来是这样的:每当抓到一个newsid,就返回给parse_hot_comment使用,当热评抓完了之后,调回头来据需抓取下一个newsid。这样动态的抓取,既节省了内存,又能提高效率,Scrapy框架也是这么设计的哟

获取热评的部分

def parse_hot_comment(newsid):

'''找到it之家新闻的热评return :info_list '''

info_list = []

data = {

'newsID': newsid,

'type': 'hotcomment'

}

try:

r = requests.post(

'https://dyn.ithome.com/ithome/getajaxdata.aspx', data=data)

r.raise_for_status()

r.encoding = r.apparent_encoding

soup = BeautifulSoup(r.text, 'lxml')

comment_list = soup.find_all('li', class_='entry')

for comment in comment_list:

# 评论内容

content = comment.find('p').text

# 用户名

name = comment.find('strong', class_='nick').get_text()

# 其他信息

info = comment.find('div', class_='info rmp').find_all('span')

# 判断用户是否填写了手机尾巴

# 对信息做出咸蛋的处理

# 抓取到 手机厂商、型号、位置、时间

# 方便最后做数据分析

if len(info) > 1:

phone_com = info[0].text.split(' ')[0]

phone_model = info[0].text.split(' ')[1]

loc = info[1].text.replace('IT之家', '').replace(

'网友', ' ').replace('\xa0', '').split(' ')[0]

time = info[1].text.replace('IT之家', '').replace(

'网友', ' ').replace('\xa0', '').split(' ')[2]

else:

phone_com = '暂无'

phone_model = '暂无'

loc = info[0].text.replace('IT之家', '').replace(

'网友', ' ').replace('\xa0', '').split(' ')[0]

time = info[0].text.replace('IT之家', '').replace(

'网友', ' ').replace('\xa0', '').split(' ')[2]

info_list.append(

{'name': name, 'content': content, 'phone_com': phone_com, 'phone_model': phone_model, 'loc': loc, 'time': time, })

return info_list

except:

return None

数据存储的部分

# config.py

# 数据库url

MONGO_URL = 'localhost'

# 数据库名

MONGO_DB = 'ithome'

# 数据库表

MONGO_TABLE = 'hotcomment_it'

# pipeline.py

from pymongo import MongoClient

from config import *

client = MongoClient(MONGO_URL, connect=True)

db = client[MONGO_DB]

# 将记录写入数据库

def save_to_mongo(result):

if db[MONGO_TABLE].insert(result):

print('存储成功', result)

return True

return False

有可以优化的地方么?

有!速度!

# 写了一个检测函数运行时间的装饰器

def clock(func):

def clocked(*args):

t0 = time.perf_counter()

result = func(*args) # 装饰被装饰的函数

timepassed = time.perf_counter() - t0

name = func.__name__

arg_str = ', '.join(repr(arg) for arg in args)

print('[{:.8f}s]{}({}) ->{}'.format(timepassed, name, arg_str, result))

return clocked

@clock

def main(page_start):

# 新闻分类的id

ID = '31'

# 建立苹果新闻分类对象

apple = parse_news_id(ID, page_start)

# 利用迭代器抓取热评

for newsid in apple:

hot_comment_dic = parse_hot_comment(newsid)

if hot_comment_dic:

for comment in hot_comment_dic:

save_to_mongo(comment)

else:

print('没有抓取到热评,一般是文章太过久远')

'''开启多进程之前 ,抓取一页新闻的所有热评所话费的时间[8.45930967s] main() -> None抓取10页:[112.86940903s] main(61) -> None'''

利用进程池开启多进程

if __name__ == '__main__':

# 单进程模式

# main(1)

# 开启多进程模式

from multiprocessing import Pool

pool = Pool()

# 进程池,每个进程抓取10页新闻的热评

groups = ([x for x in range(111, 191,10)])

pool.map(main, groups)

pool.close()

pool.join()

'''开启后:不能使用装饰器测时间了AttributeError: Can't pickle local object 'clock..clocked'改为第三方秒表计时:爬取1~40页:time:1:56.54可以看到 速度快了三倍!'''

由于整体的代码太长了,

就不再贴上来了,有需要全部代码的,

可以去我的github(放在文末了)上看

最后总结一下

这次一共抓取了2W+条数据

但如果仅仅是有这些数据,

而不去分析,整理,那么数据就没有任何意义。

我们很多人是通过学爬虫入门Python的。

但爬虫重要的并不是爬虫本身,而是爬出来的数据。

那么我们是不是应该想想,

有什么办法能够将数据整理并展示出来呢?

熟悉我的小伙伴都知道,

我现在主要在发展的方向是Python Web

对于数据分析 我是有所逃避的

因为在我的潜意识里,我就是个文科生,

拼 算法、思路、最优解、对数据的敏感程度

我是肯定拼不过那些理科工科生的

帮助我入门的@路人甲就是做数据分析的

大家都喊他数据帝

现在在他的建议下,我不在逃避这方面的弱点,

开始经常刷leetcode上的算法题,

虽然过程很难熬,有的时候半个小时都没有思路。

但毕竟会是有用的对吧?

咳咳,其实说了这么多,

一是想告诉大家,不要为了写爬虫而写爬虫

二是,我其实已经将这数据做出了一点点分析,回头我整理好会发出来

题目大概叫 帮你上热评

大家要多来点赞哦

逃 ~

python爬取知乎评论_从零开始写Python爬虫 --- 爬虫应用:IT之家热门段子(评论)爬取...相关推荐

  1. python爬虫代理的使用_从零开始写Python爬虫 --- 2.4 爬虫实践:代理的爬取和验证...

    爬网站的时候,由于各种原因,ip被锁了,这个时候我们就需要通过代理来突破封锁.网上有很多代理网站,付费和免费的都有,这次我们就来写一个scrapy爬虫,爬一些免费的代理下来用. 目标分析: 本次爬取了 ...

  2. python 小说爬虫_从零开始写Python爬虫 --- 1.7 爬虫实践: 排行榜小说批量下载

    从零开始写Python爬虫 --- 1.7 爬虫实践: 排行榜小说批量下载Ehco 5 个月前 本来只是准备做一个爬起点小说名字的爬虫,后来想了一下,为啥不顺便把小说的内容也爬下来呢?于是我就写了这个 ...

  3. python爬取知乎文章_大佬分享Python编程实现爬取知乎用户信息的例子

    有一天 , 我发现我心仪已久的妹子在朋友圈里分享了知乎专栏的文章 , 就知道她也刷知乎 . 如果在知乎上关注她 , 我就能知道 , 她最近关注什么 , 心里想些什么 , 了解了解她喜欢的方面 , 还能 ...

  4. python爬斗鱼直播_从零开始写Python爬虫 --- 爬虫应用: 利用斗鱼Api抓取弹幕

    七月末的南京简直开启了「微波炉」模式,白天要学车的我,晚上自然选择宅在家看直播,看着狗贼叔叔满屏幕的弹幕,我就想着能不能把弹幕爬下来呢?说干就干 结果的展示: 这里只抓到弹幕内容和发送用户 并输出在终 ...

  5. node爬取app数据_从零开始写一个node爬虫(上)—— 数据采集篇

    爬虫相信大家都知道,这里我们从一个空的文件夹开始,也来写一写我们自己的爬虫程序吧. github入口 下一篇--数据分析篇入口 爬虫毕竟涉及到数据的爬取,所以其实有一个道德的约束,那就是Robots协 ...

  6. python的read函数调用报错_从零开始学Python(七):文件存储I/O流和异常捕捉

    这两天在搞小程序开发,耽搁了一下更新的进度,今天补上.一个完整的前端程序肯定离不开数据存储和网络两个模块,今天我们就先来讲讲python中的一种常见数据存储:文件存储!~! 文件存储(I/O操作) 何 ...

  7. 用python做我的世界代码_从零开始用Python做一个Minecraft成就(进度)生成器

    最近看到mcmod百科上有个叫成就生成器的东西,于是也想用Python做一个. 大致思路: 一张成就图像,需要有底图,图标和和说明文字三个部分. 成就的图标比较难搞,我使用的是Minecraft Wi ...

  8. python 模拟浏览器selenium_从零开始写Python爬虫 --- 3.1 Selenium模拟浏览器

    本来说好要写Mechanize模拟浏览器的,结果一看居然只支持2.x版本的Python,而且已经长久没有更新维护了,本着学新不学旧的原则,我决定跳过他,直接开学Selenium(其实就是我懒,逃 Se ...

  9. 从零开始写Python爬虫 --- 1.5 爬虫实践: 获取百度贴吧内容

    从零开始写Python爬虫 --- 1.5 爬虫实践: 获取百度贴吧内容 Ehco 5 个月前 经过前期大量的学习与准备,我们重要要开始写第一个真正意义上的爬虫了.本次我们要爬取的网站是:百度贴吧,一 ...

最新文章

  1. python大神-6年Python大神总结10个开发技巧,80%的人都不会
  2. NIPS 2017论文解读 | 基于对比学习的Image Captioning
  3. Linux系统下GitLab服务的的搭建
  4. 在计算机的通信子网中 其操作方式有两种,全国自考计算机网技术模拟试卷(八)及答案.doc...
  5. Python函数参数传递:传值还是传引用
  6. for循环执行 mybatis_Mybatis中使用循环遍历
  7. Effective C# Item30:尽可能实现CLS兼容的程序集
  8. java四大模块_Spring框架七大模块
  9. Node连接MySQL并封装其增删查改
  10. php伪静态之APACHE配置篇
  11. java点击按钮弹出警告_GUI求教~~~我想点击按钮确定后,弹出一个提示框输入有误!,,…...
  12. BZOJ4568 [Scoi2016]幸运数字
  13. 姓氏头像制作生成头像组合微信小程序源码
  14. 土豆网总裁回忆与乔布斯的会面
  15. NAT技术与代理服务器详解
  16. 诛仙mysql数据库清空_数据库管理,启动命令,输入密码,用户名,虚拟机诛仙zx1324-1345一键镜像端、纯端kfvip - Welcome to XiongTianQi.CN...
  17. 微信公众号使用H5获取地理位置信息并定位
  18. k8s-client-go源码剖析(一)
  19. matlab入门教程五 ----- 绘制空间图形
  20. 这几个excel神操作,让你从入门到大神 ,涨完工资再来谢我……

热门文章

  1. 跨域解决方式——JSONP,CORS
  2. 大数据基础课04 大数据开发必备工具和来源
  3. linux赛门铁克扫描,赛门铁克数据扫描程序(Symantec Data Scanner, SDS)技术简介
  4. ROC曲线与AUC值
  5. 如何通过提问更快地获得想要的答案
  6. JMeter 配置元件-CSV Data Set Config 参数化配置
  7. 字节跳动成都java后端开发岗实习生面试
  8. 时间序列分解法(Time-series Decomposition)
  9. DA1458x使用之第一篇——GPIO
  10. 使用Python制作证件照