Python学习(网络爬虫精讲)

来源:互联网 发布:如何开淘宝企业网店 编辑:程序博客网 时间:2024/06/03 20:30

我已在前面的博客中粗略讲过一些爬虫的知识,刚入门的同学可以看这里。今天又拿jupyter来精讲一遍,希望对想要深入研究爬虫的同学有所帮助。本文是基于anaconda3环境,未安装的同学可以去这里下载安装,其中自带jupyter。

一、运行jupyter:

打开anaconda3中的Anaconda Prompt,输入jupyter notebook+回车打开jupyter,在Home中选择Python3进入下一界面。在Help选项中你可以查看用到的快捷键,最常用的是ctrl+enter:执行输入的代码;shift+enter:执行输入的代码并再创一个输入框,可以继续写代码并进行这两步的操作,是可以承接上一个输入框中的代码继续执行的。



二、requests模块和BeautifulSoup模块:刚入门的同学请参考这里。


不同网站得到的res.text可能出现乱码问题,所以我指定了编码方式。


link以字典的形式储存了由'a'所选择出的所有条目,所以其每一个条目所包含的属性就可以用link['href']来得到。

三、选取网站页面中的特定内容:以火狐浏览器为例,按F12进入界面元素查看器,点击左上角第一个按钮,然后在界面选取某些新闻列表中的某个条目(或者其他条目),然后在控制台查看被选中的相关信息,找到select()筛选的条件。


如图所示是新闻列表部分的内容和跳转链接,通过查看器,我们知道选择条件是.news-item,然后重复查看操作,继续寻找每条中的相关元素。news.select('.time')[0]:选出time中的内容,其中只有一个元素,所以[0]就是这个元素;href = news.select('h2')[0].select('a')[0].get('href'):href = news.select('a')[0]['href']同样可以找到相应链接,我使用的方式只是为了思路更清晰,但执行效率会降低。

四、分步获取文章详细内容:点开上面获取到的一篇新闻的链接,让我们分步获取其中的数据内容。

1.新闻ID和标题:通过查看器找到标题选择标志为artibodyTitle。

import requests, bs4res = requests.get('http://news.sina.com.cn/c/2017-08-31/doc-ifykpuuh9842453.shtml')res.encoding = 'utf-8'soup = bs4.BeautifulSoup(res.text, 'html.parser') title = soup.select('#artibodyTitle')print(title[0].text)ID = title[0]['docid']print(ID)

汪洋:脱贫攻坚最难的是安于现状“不怕穷”fykpuuh9842453

2.发布时间:新浪文章的时间中嵌套了发布方的信息,如果使用time[0].text,将同时取出时间和发布方两条信息,我们只要时间,所以用contents方法来分开这两条数据,进而进行选择取用,strip()方法可以去掉其中的空白标志。取出的time为字符串,如果需要存入数据库,则需要进一步加工数据格式,对时间加工模块不清楚的可以参考我这篇博客。

import datetimetime = soup.select('#navtimeSource')[0].contents[0].strip()print(time)dt = datetime.datetime.strptime(time, '%Y年%m月%d日%H:%M')print(dt)

2017年08月31日09:402017-08-31 09:40:00

3.新闻来源:soup.select('#navtimeSource span a'):可以在选择的条件中加入多个条件,前提是所要寻找的元素条件易于提取,简单说就是可以直接找到。

soup.select('#navtimeSource span a')[0].text
'新京报'
4.新闻内容:这里用[:-2]去掉了编辑部分的内容,对字符串操作或者列表操作不清楚的可以去我前面的博客查看相关内容。

content = []for p in soup.select('#artibody p')[:-2]:    content.append(p.text.strip())'  '.join(content)
很熟练的同行可以用一句话来代替:

'  '.join(p.text.strip() for p in soup.select('#artibody p')[:-2])

5.责任编辑:直接借助上面取内容的方法。

'  '.join(p.text.strip() for p in soup.select('#artibody p')[-1:]).strip('责任编辑:')
'桂强'
6.查看评论:上面的新闻没有评论,所以我找了一条有评论的新闻。接下来让我们找到评论列表的内容并查看它们的选择条件:soup.select('.list'),发现返回来一个空列表,明明是有评论的,怎么没有数据呢。在控制台由一条评论的定位出发向外面更大的范围查找,发现评论的开始处,是一个javascript的href,说明这些数据是在js中通过数据请求加载的。如何在js中找到这个链接呢,你可以点击控制台的网络选项,刷新页面,然后在筛选中输入comment,点击js选项筛选,找到回应状态值为200的那个网址,然后点击查看它的请求链接,就个就是我们要的评论链接了。当然,找到这个链接的方式还有很多,你可以试试自己的想法。其实查看评论数量的那个链接也正是这些评论数据链接的前一部分。

import requestsres = requests.get('http://comment5.news.sina.com.cn/page/info?version=1&\format=js&channel=gn&newsid=comos-fykpysa2239461&group=&compress=0&\ie=utf-8&oe=utf-8&page=1&page_size=20&jsvar=loader_1504168106106_46225366')print(res.text)
在这个请求链接中newsid=comos-fykpysa2239461红色部分就是这条新闻的ID,page_size=20为一页的大小,后面的内容是附加的东西,其实对我们而言没有什么作用。返回的数据为json的数据格式,需要转化为能在python中使用的数据格式。

import requests, jsonres = requests.get('http://comment5.news.sina.com.cn/page/info?version=1&\format=js&channel=gn&newsid=comos-fykpysa2239461&group=&compress=0&\ie=utf-8&oe=utf-8&page=1&page_size=20')js = json.loads(res.text.strip('var data='))print(js)
此时数据以字典的形式被保存,我们可以尝试查找一下总的评论数:

js['result']['count']['total']
1514
五、抽取评论的轮子:对于正则抽取表达不清楚的同学可以参考我的这篇博客。

import re, requests, jsondef getCommentTotal(htmlUrl):    idStr = re.search('doc-i(.+).shtml', htmlUrl)    ID = idStr.group(1)    commentURL = 'http://comment5.news.sina.com.cn/page/info?version=1&\format=js&channel=gn&newsid=comos-{}&group=&compress=0&\ie=utf-8&oe=utf-8&page=1&page_size=20'    res = requests.get(commentURL.format(ID))    js = json.loads(res.text.strip('var data='))    return js['result']['count']['total']
htmlUrl = 'http://news.sina.com.cn/c/nd/2017-08-31/doc-ifykpysa2239461.shtml'getCommentTotal(htmlUrl)
1877
当然你也可以把抽取文章、作者、发布时间等方法都放到定义的轮子里面,只要传入一个网页,就可以拿到文章所有的东西了。

原创粉丝点击