爬取文章-简书首页推荐文章
页面分析
我们在上一篇中爬取了mm图片,这一次我们来爬取文字类型的操作。
在这里,我们选择简书来做实例。简书入口地址【https://www.jianshu.com/】,
这里是主要输出文字内容的网站,在这里,我们直接抓取主页,获取首页的内容。
比如我们可以看到有标题,简介,作者,点赞数,看不见的有文章的详细链接。
在这里,我们就取【标题】、【描述】、【作者】、【链接】。
下面,我们来看看如何获取这些内容?
页面源码分析
现在我们使用谷歌浏览器打开【简书】首页地址:https://www.jianshu.com/,然后鼠标右键选择其中的某个标题,选择【查看】,可以看到源码中有我们需要的标题、描述、作者和链接;
在这里,需要注意的是,除了文章链接还有广告链接,
我们需要去除广告,所以我们不需要抓取广告内容。
然后我们继续往下拉,可以看到自动加载了【下一页】的内容。
或者是出现了【阅读更多】的情况,从网络日志里面,我们就看到了是JS加载内容,
那我们就可以直接看网络请求情况。
从上图可以看到,在自动加载内容的时候,浏览器发起了网络请求,也就是js根据滑动自动发起数据请求。
跟我们前面判断的结果是一致。
至此,我们就大概了解了简书首页获取内容的整体流程。接下来,我们就是动手写代码。
代码编写
获取第一页的内容
def _handle_main_page():
global _token
sess = sessions.session()
sess.headers = _HEADER
sess.headers[
'Accept'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9'
sess.headers['Accept-Encoding'] = 'gzip, deflate, br'
sess.headers['Accept-Language'] = 'zh-CN,zh;q=0.9'
sess.headers['Connection'] = 'keep-alive'
sess.headers['Host'] = 'www.jianshu.com'
sess.headers['Cache-Control'] = 'no-cache'
sess.headers['Pragma'] = 'no-cache'
p = 'https://www.jianshu.com/'
r = sess.get(p)
c = r.content.decode('utf-8')
soup = BeautifulSoup(c, 'lxml')
# data
ul = soup.select('.note-list')[0]
_parse_li(ul.find_all('li'))
ts = soup.find_all(name='meta')
for t in ts:
if t.has_attr('name') and t['name'] == 'csrf-token':
_token = t['content']
break
_handle_next_page(sess)
在以上代码中,我们做了几个事情:
1.获取第一页面的内容,也就是简书打开首页的默认内容,在’# data’标签之前就是这部分;
2.接下来,我们使用bs4来解析第一页面的内容,_parse_li 有做具体的解析方式;
3.在解析了内容之后,我们解析了后续页面需要用到的token,这个token很关键,是我们进行下一步的核心,
4.最后就是获取下一页的内容,_handle_next_page
解析第一页面的方法:_parse_li()
def _parse_li(lis):
for li in lis:
title_a = li.select('.title')
d = {'id': li['id'], 'href': title_a[0]['href'], 'title': title_a[0].text,
'description': li.select('.abstract')[0].text.strip(), 'nickname': li.select('.nickname')[0].text}
print(d)
_page_data.append(d)
解析这个页面主要是根据下面这个图来操作:
获取下一页的方法:_handle_next_page()
def _handle_next_page(sess):
global _page
global _token
time.sleep(1)
sess.headers['Referer'] = 'https://www.jianshu.com/'
sess.headers['X-INFINITESCROLL'] = 'true'
sess.headers['X-Requested-With'] = 'XMLHttpRequest'
sess.headers['Accept'] = 'text/html, */*;q=0.01'
sess.headers['X-CSRF-Token'] = _token
#
next_url = f'https://www.jianshu.com/?{urlencode(_get_seen_snote_ids())}&page={_page}'
n = sess.get(next_url)
nr = n.content.decode('utf-8')
if n.status_code == 200 and len(nr) > 1:
_parse_next_page(sess, nr)
else:
print(f'code:{n.status_code},content:{n.content}')
print('[*] Crawling is Done')
sess.close()
pass
在这个获取下一页内容的地方,关键的地方在于请求的时候,需要带上前面获取到的token,
另外一个获取下一页标签的方法为:
def _parse_next_page(sess, nr):
global _page
soup = BeautifulSoup(nr, 'lxml')
print(f'[*]------------[{_page}]--------------[*]')
_parse_li(soup.find_all('li'))
_page += 1
_handle_next_page(sess)
pass
至此,完成了从获取首页,解析首页,然后获取下一页并解析下一页的完整流程。
下面,我们看看具体的运行效果。
实例运行
/Users/michaelkoo/work/env/csdn/code/ImgBianhua/venv/bin/python /Users/michaelkoo/work/env/csdn/code/ImgBianhua/main.py
200 21492
{'id': 'note-84834383', 'href': '/p/19abeb567253', 'title': '终于还是出事了', 'description': '我姑家的孩子又突然犯病,拿着剪刀捅伤了好几个人,其中还有个七八十岁的老年人。出事后,孩子那没用的爹直接带着我弟跑来了我家,犯了事不留下来和受...', 'nickname': '池星呀'}
{'id': 'note-83357815', 'href': '/p/5333c1cf4702', 'title': '产品经理逐渐在失业?', 'description': '如今的互联网已经形成了头部玩家的局面,甚至是已经出现一个铁律即:任何互联网中的新小企业走到后面迟早都会变成腾讯系、阿里系、头条系等 单靠一个创意...', 'nickname': 'Kevin改变世界的点滴'}
{'id': 'note-82733395', 'href': '/p/6ac0aa4a99f7', 'title': '崔先生,你被我注意到了', 'description': '崔先生,你干嘛给我点赞这么多呀,你难道是喜欢我的内容吗?还是喜欢我的人呀,我还是很感谢你的。你给我点赞了这么多我都不知道怎么感谢您好了。 在我写...', 'nickname': '杜杜老金不二'}
{'id': 'note-86041519', 'href': '/p/c50940cff14c', 'title': '永恒之井', 'description': '文/自来诗主题:虚幻与现实 “猫,你在哪?喵~喵~” 我的小猫丢了,钻进了屋后的小树林,我循着它的声音跟着。这个地方我一直不敢来,因为那的树上常...', 'nickname': '自来诗'}
{'id': 'note-82218339', 'href': '/p/99997a54c9bc', 'title': '毛毛虫成长记---【6】虚惊一场', 'description': '日日无事,事复日日,忙忙。亦茫茫。 滴答······滴答······滴答······滴答······ 风雨过后的,叶片上的雨珠正顺着叶子的纹路向...', 'nickname': '大熊之影'}
{'id': 'note-84069072', 'href': '/p/82c293d1fd43', 'title': '复杂的人心', 'description': '好久不见的一个朋友给我来了个电话,聊天内容从问候谈到工作,谈到孩子,东拉西扯了十几分钟,我忍不住问:“有什么事情吗?”人家一愣,说就是感觉好久没...', 'nickname': '唐小暖'}
{'id': 'note-84300344', 'href': '/p/ab9a218f4512', 'title': '写作究竟是什么?', 'description': '写这个标题的时候,我在想我写了近一年,今晚似乎是第一次用音响大声放着自己喜爱的音乐在写字。 以往总觉得,安静下来写字(或者说是敲键盘吧~),是一...', 'nickname': '里_拉'}
[*]------------[2]--------------[*]
...
...
...
[*]------------[49]--------------[*]
{'id': 'note-86893238', 'href': '/p/b8ed8d5ac1b9', 'title': '毛姆,你知多少?', 'description': '今天,打开微信读书,读了《人性的枷锁》是关于毛姆的自传体小说。 才看了前100页,就被吸引了。想写写关于毛姆的一些事情。同时,加上自己的思考。 ...', 'nickname': '坚持写下去'}
{'id': 'note-85446117', 'href': '/p/7c80dbd3ab41', 'title': '研究表明,男人对女人的“分寸感”,将决定婚姻是否长久', 'description': '01 要想一段婚姻变得长久,其实夫妻双方都必须要把握好一个度。这个度,将决定这两者的关系是否平衡。 在西方社会,有研究者做过这么一个调查。 他们...', 'nickname': '舒山有鹿'}
{'id': 'note-85365427', 'href': '/p/22da827eabaa', 'title': '男人理想中的女人类型,只有一种', 'description': '近几年,单身率一路飙升。 到了一定的年纪,依然还是单身的,不仅仅有女人,更有不少的男人。 而对于这些单身的男人,好些哪怕已经过了而立之年,似乎也...', 'nickname': '南方姑娘谭檬'}
{'id': 'note-86410793', 'href': '/p/d0736842a869', 'title': '听樊登老师解读《张爱玲传》', 'description': '张爱玲是我非常喜欢的一个作家,不仅是喜欢她的文笔,也喜欢她这个人。对她莫名地崇拜与尊重。 这次听樊老师重新解读张爱玲,收获不小,对张...', 'nickname': '开心当下'}
{'id': 'note-86019413', 'href': '/p/c04a631bd41b', 'title': '温暖的人', 'description': '昨天早上,有个阿姨过来买菜,结账时,我发现她手腕上戴了一个金镯子,崭新锃亮的。 我指着镯子就打趣问她,姨,谁给你买的,闺女还是媳妇。 她笑了笑说...', 'nickname': '小燕五'}
{'id': 'note-84080454', 'href': '/p/7b6c4b0dc413', 'title': '一个19岁女孩的悲惨人生', 'description': '六岁时她的母亲天天打麻将把她一人丢在家里;七岁时母亲冤枉她偷钱罚站一天没吃没喝;八岁时父亲家暴母亲,母亲跟另一个男人逃跑,丢下她一个人,不仅如此...', 'nickname': '安幼鱼'}
{'id': 'note-83383484', 'href': '/p/abcd1106aaea', 'title': '那些平躺着睡的人', 'description': '很早的时候,女人就不知道从哪里知道了一个知识,就是每晚平躺着睡会少生皱纹。 年少的时候不需要在意皱纹,因为那时候觉得皱纹还遥远得很,满脸的胶原蛋...', 'nickname': 'FHL喜悦之心'}
code:400,content:b''
[*] Crawling is Done
Process finished with exit code 0
运行结果效果图:
后续
简书作为内容输出平台,记录的是平民百姓的生活瞬间,可以作为我们了解社会的一角;
在这里,我们只是简单的把简书的内容获取到,其实,真正的“使用”还未派上用场;
如果时间允许,我们可以每天从简书获取内容,然后存储起来进行分析,了解社会的动态。
当然,这只是其中的一种方式,预知更多方式,请待下篇分析。