一开始参考:
https://blog.csdn.net/qq_16546829/article/details/79511997
后来换了:
https://blog.csdn.net/five_east_west/article/details/108627097
Ajax动态分析
待抓取的微博内容:https://m.weibo.cn/u/1742566624
在cmd 中输入
因为我之前已经安装好这两个库,所以在此安装的时候是显示的下图的内容:
打开Chrome浏览器,我们进入这个网站:https://m.weibo.cn/u/1742566624。鼠标右键,选择查看网页源代码,这时候我们会发现网页源代码中并没有显示出来我们在首页看到的那些文字内容,这就说明这个网页是Ajax动态加载的。(下图中左边为展现给我能够看到的网页,而右边则是网页源代码)
我们到右边随意选择一条内容到左边进行搜索都不会有结果,这里以“烟火人间,风味长存。”为栗子进行搜索:
我们看到源代码中并没有出现我们搜索的内容,所以该网页是Ajax动态加载的。
Ajax,全称为Asynchronous JavaScript and XML,即异步的JavaScript和XML。它不是一门编程语言,而是利用JavaScript在保证页面不被刷新、页面链接不改变的情况下与服务器交换数据并更新部分网页的技术。
对于传统的网页,如果想更新其内容,那么必须要刷新整个页面,但有了Ajax,便可以在页面不被全部刷新的情况下更新其内容。在这个过程中,页面实际上是在后台与服务器进行了数据交互,获取到数据之后,再利用JavaScript改变网页,这样网页内容就会更新了。
可以到W3School上体验几个示例来感受一下:http://www.w3school.com.cn/ajax/ajax_xmlhttprequest_send.asp。
其实很多网页都是这样的,我们把网页接着往下滑,会不断的刷新加载新的内容呈现在我们眼前。
既然我们已经知道它是用Ajax动态加载的,我们就来分析一波它是如何进行数据交换的。
鼠标右键,选择检查(或者按下键盘上的F12),进入开发者模式。网页的样式便展示在了我们眼前。
在Elements中我们能看到网页源代码,右侧是节点的内容,但这并不是我们想要的内容,如果按照常规的网页请求并提取网页标签中的数据是无法得到我们想要的内容的。
我们转到Network,选择Network下的XHR,我们会看到以下内容(第一次进入是没有这些内容的,刷新一下网页就好了):
随着我们不断的滚动鼠标滚轮,XHR下加载的内容越来越多,我们会看到一个getIndex开头的请求,点开它,可以看到它的详细信息
我们看到Request Headers它里面有一个参数是X-Requested-With: XMLHttpRequest。通过这个参数我们可以更加肯定它是Ajax动态加载的。然后点一下 Headers 旁边的 Preview,它里面的数据是 json(类似python字典的一种字符串) 格式的。
点开cards下面有10条内容,我们在进到下面9条内容中的mblog里面去一 一查看,我们会发现,微博正文中包含的文字都包含在了raw_text中
(其实图片也包含在这个请求中,想要把图片下载下来的看客朋友可以自己去研究研究图片的链接)。既然已经找到我们想要的东西了,就开始写BUG吧,把这些文字给“抓”下来,放到自己的“口袋”中。
我们用requests.get(url)来请求网页,因为我们要请求的网页已经不是开头给出的那个网页了,而是通过我们分析之后找到的那个Ajax的网页请求。所以我们真正请求的应该是这个网页https://m.weibo.cn/api/container/getIndex?uid=1742566624&t=0&luicode=10000011&lfid=100103type%3D1%26q%3D%E6%80%9D%E6%83%B3%E8%81%9A%E7%84%A6&type=uid&value=1742566624&containerid=1076031742566624,打开这个网页我们会发现,密密麻麻的字符、数字,我们在浏览器中随便找一个json数据在线解析网址http://json.cn/,这里的这个就可以,将上面网页的内容复制到json网页中我们就可以看到整齐的json数据了,很像python中的字典型式。
在jupyter中这样写:
我们直接将它转成json格式,在jupyter中打印出来,随时查看网页返回的信息是个什么样子的东西。(爬虫、数据分析等建议使用jupyter,方便随时查看结果)
运行上述代码,得到以下输出:
不难发现,这个数据就和我们之前在 Preview 中看到的数据是一样的,说明我们拿到的就是我们想要的数据,接下来将我们要的微博正文内容从这个字典从取出来就行了。代码如下:
运行结果如下:
因为cards是一个列表,它里面包含了十条数据,所以我们用一个for循环来遍历整个列表,将数据从提取出来,因为我们返回的数据是字典类型的,所以我们可以直接用get来提取数据,或者按照键值对来索引(建议使用get,如果没有当前键而进行索引会报错,而get是返回一个空值,不会使程序出错停下来)。就这样,我们提取了“第一页”的十条数据,但这个数据量往往不能满足我们的需求。
如果我们一个网页一个网页的去复制粘贴到到我们的脚本中,10个可能问题还不大,先找到getIndex然后将网页复制,粘贴到脚本中,总共三步,10个网页也就30步,可如果是100个网页呢?这时候处理起来就比较麻烦了。所以我们需要找到一个构造网页的“好方法”,让脚本它自己去“ 寻 找 网 页 ” → “ 复 制 ” → “ 粘 贴 ” “寻找网页”\rightarrow“复制”\rightarrow“粘贴”“寻找网页”→“复制”→“粘贴”,一般面对这种重复的工作我们都可以交给程序来完成。所以我们现在要做的就是”教会“我们的爬虫脚本去做这个事情。
在回过头来看看我们请求的网页:https://m.weibo.cn/api/container/getIndex?uid=1742566624&t=0&luicode=10000011&lfid=100103type%3D1%26q%3D%E6%80%9D%E6%83%B3%E8%81%9A%E7%84%A6&type=uid&value=1742566624&containerid=1076031742566624这是我们请求的第一个网页,我们再来看看第二个我们要请求的网页长得怎么样:https://m.weibo.cn/api/container/getIndex?uid=1742566624&t=0&luicode=10000011&lfid=100103type%3D1%26q%3D%E6%80%9D%E6%83%B3%E8%81%9A%E7%84%A6&type=uid&value=1742566624&containerid=1076031742566624&since_id=4551744417694196。第二个网页好像和第一个网页不太一样,它比第一个网页要多出一个小尾巴since_id,其实我们再去看第三个、第四个、第五个……从第二个网页开始,它们都有了一个since_id的参数,所以我们只要在第一个网页的基础上给往后的每个网页都加上一个since_id的参数就行。但是好像每个网页对应的since_id 都是不一样的,所以我们如果是想胡诌一个的方法貌似是行不通的。但是,它这个网页毕竟是人写的,不是神创的,所以它这个since_id一定是有办法通过我们聪明的小脑袋瓜”造“出来的。
既然它这个网页的since_id要被浏览器抓到,并不断请求下一页数据,那么这个since_id被我们自己找出来也不会是难事。
果然,我们可以在json数据的cardlistInfo中找到一个since_id的键
我们将这个since_id和下一个网页中的since_id 进行比较,它两就是一样的(我这里截的是首页的since_id,随着时间变化这个since_id也会变化,看客朋友看到的和我的不一样是正常的),我们像提取文本信息一样用get将since_id 获取下来。现在我们找到了这个since_id 的构造规律,我们就可以来请求多页的网页数据了,我们只要教会我们的爬虫脚本如何利用我们为它找出来的since_id来构造网页,它就能不断的获取网页上的内容了。
构造网页的代码如下:
urlencode是在urllib.parse中的方法,以下是官方文档:
函数中传入的since_id就是我们为爬虫找到的since_id。然后我们把构造好的网页返回给网页请求函数,在解析提取我们要的内容以及since_id,这样就可以一直不停的循环下去了。
写个爬虫,应该不会只是为了爬一爬数据,而且我们如果下次还要用这个数据又要重新爬,也会很麻烦,所以我们将我们从网络上”窃取“下来的东西”藏“起来。这里我们用记事本将这些文本数据存下来(当然也可以写到数据库里面去,感兴趣的看客老爷可以自己去网上搜搜写入数据库的操作)。保存数据代码如下:
因为我们这里抓取的是思想聚焦的微博文章,所以写入的标题就是”思想聚焦的微博正文“,然后每写完一行都空一行(这样看起来工整一些)参数newline就是这个作用。
到这儿我们的爬虫也就写完了,感兴趣的可以做做词云图、做一下情感分析等……
完整代码:
在这个脚本脚本中我们设置了请求头,让我们的爬虫看上去更像是浏览器在访问。
运行结果:
我们检查网页源代码时,发现源代码中没有我们在网页上看到的信息时我们就要想到它时Ajax动态加载的。对于Ajax的网页的抓取我们应该要去分析它的动态加载包,而不是直接请求它的源代码,通过构造Ajax网页网址来实现多页信息的抓取,不同的网站它的url的构造方法不一样,这一点需要看客朋友自己去找规律,构造url。看完这篇文章如果你觉得你会爬取Ajax的网页了,可以去试试爬取今日头条上面的内容,它也是Ajax加载的。
提取网页信息的方法也是有很多种,只是在这个栗子中我们这个恰巧是字典形式,如果遇到其他情况我们要随机应变,自己最熟悉的信息提取方式将网页信息抓取下来。就介绍到这里吧,有些简陋,但大致能看。
————————————————————————————————————————
但是遇到有展开全文的博文时,
通过判断text后面是否有“全文”两字,若有,则导出前面的那串数字,通过新的地址(全文地址),拿到全文。(常常有tag,爬下来的全文中还存在很多地址,需要后续删减
代码:
用此函数在main中代替上文get_infos(html)
(有点小错误还需在改正