投稿    登录
  您好,欢迎光临崔庆才的博客,祝大家新年快乐,鸡年大吉!

Python爬虫实战六之抓取爱问知识人问题并保存至数据库

Python 崔庆才 36222浏览 38评论

大家好,本次为大家带来的是抓取爱问知识人的问题并将问题和答案保存到数据库的方法,涉及的内容包括:

  • Urllib的用法及异常处理
  • Beautiful Soup的简单应用
  • MySQLdb的基础用法
  • 正则表达式的简单应用

环境配置

在这之前,我们需要先配置一下环境,我的Python的版本为2.7,需要额外安装的库有两个,一个是Beautiful Soup,一个是MySQLdb,在这里附上两个库的下载地址,

Beautiful Soup     MySQLdb

大家可以下载之后通过如下命令安装

环境配置好之后,我们便可以开心地撸爬虫了

框架思路

首先我们随便找一个分类地址,外语学习 – 爱问知识人,打开之后可以看到一系列的问题列表。

我们在这个页面需要获取的东西有:

总的页码数,每一页的所有问题链接。

接下来我们需要遍历所有的问题,来抓取每一个详情页面,提取问题,问题内容,回答者,回答时间,回答内容。

最后,我们需要把这些内容存储到数据库中。

要点简析

其实大部分内容相信大家会了前面的内容,这里的爬虫思路已经融汇贯通了,这里就说一下一些扩展的功能

1.日志输出

日志输出,我们要输出时间和爬取的状态,比如像下面这样:

[2015-08-10 03:05:20] 113011 号问题存在其他答案 我个人认为应该是樱桃沟很美的

[2015-08-10 03:05:20] 保存到数据库,此问题的ID为 113011

[2015-08-10 03:05:20] 当前爬取第 2 的内容,发现一个问题 百度有一个地方,花儿带着芳香,水儿流淌奔腾是什么意思 多多帮忙哦 回答数量 1

[2015-08-10 03:05:19] 保存到数据库,此问题的ID为 113010

所以,我们需要引入时间函数,然后写一个获取当前时间的函数

以上分别是获取带具体时间和获取日期的函数,在输出时,我们可以在输出语句的前面调用这函数即可。

然后我们需要将缓冲区设置输出到log中,在程序的最前面加上这两句即可

这样,所有的print语句输出的内容就会保存到out.log文件中了。

2.页码保存

爬虫爬取过程中可能出现各种各样的错误,这样会导致爬虫的中断,如果我们重新运行爬虫,那么就会导致爬虫从头开始运行了,这样显然是不合理的。所以,我们需要把当前爬取的页面保存下来,比如可以保存到文本中,假如爬虫中断了,重新运行爬虫,读取文本文件的内容,接着爬取即可。

大家可以稍微参考一下函数的实现:

这样,不管我们爬虫中途遇到什么错误,妈妈也不会担心了

3.页面处理

页面处理过程中,我们可能遇到各种各样奇葩的HTML代码,和上一节一样,我们沿用一个页面处理类即可。

我们可以用一段含有HTML代码的文字,经过调用replace方法之后,各种冗余的HTML代码就会处理好了。

比如我们这么一段代码:

经过处理后便会变成如下的样子:

经过上面的处理,所有乱乱的代码都会被处理好了。

4.保存到数据库

在这里,我们想实现一个通用的方法,就是把存储的一个个内容变成字典的形式,然后执行插入语句的时候,自动构建对应的sql语句,插入数据。

比如我们构造如下的字典:

构造sql语句并插入到数据库的方法如下:

这里我们只需要传入那个字典,便会构建出对应字典键值和键名的sql语句,完成插入。

5.PHP读取日志

我们将运行结果输出到了日志里,那么怎么查看日志呢?很简单,在这里提供两种方法

方法一:

PHP倒序输出所有日志内容

此方法可以看到所有的输入日志,但是如果日志太大了,那么就会报耗费内存太大,无法输出。为此我们就有了第二种方法,利用linux命令,输出后十行内容。

方法二:

上面两种方法都是5秒刷新一次网页来查看最新的日志。

源代码放送

好了,闲言碎语不多讲,直接上源码了

数据库建表SQL如下:

运行的时候执行如下命令即可

代码写的不好,仅供大家学习参考使用,如有问题,欢迎留言交流。

运行结果查看

我们把PHP文件和log文件放在同一目录下,运行PHP文件,便可以看到如下的内容:

20150908222744

小伙伴们赶快试一下吧。

转载请注明:静觅 » Python爬虫实战六之抓取爱问知识人问题并保存至数据库

喜欢 (102)or分享 (0)

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请狠狠点击下面的

  1. u81f4uff1au81f4u9001u3001u8868u8fbeu7684u610fu601duff0cu656cu8bcdu3002请问楼主大大,为什么中文输出会变成这样啊

  2. 关于页码的问题,最简单的方式就是:在当前页抓取下一页的地址,然后一直循环抓取,直到抓取不到下一页地址,就说明到最后一页了。

  3. 一共就100页,可以把页码对应的 URL 中的数字爬下来,用字典做映射,保存到 Json 文件中,之后再从字典中找到对应页码的数字,构造新的 URL 就行了

  4. @亲爱的楼主大人,小女子在debug 过程中遇到几个问题,甚是烦恼,劳烦大人有时间帮忙答疑解惑;1、传入的url 链接现在貌似已经变更,原来网址打不开;现在加了 new 字符串 比如: http://iask.sina.com.cn/c/978-all-3-new.html2、pattern = re.compile( u’.?(.?)s*’, re.S) 这句正则匹配返回的match 对象是none;因为不太懂正则,不知道哪里出错;导致“获取总页码失败”。。。。3、questions = soup.select(“div.question_list ul li”) 这句过滤的条件一是不明白,二是 不知道哪不对;debug发现没办法正确返回questions 列表 🙏🙏

    • 抱歉呀,一直没看到,发现现在爱问知识人也已经改版了,太不靠谱了。所以URL什么的也变了。所以第一个第二个问题应该无法解答了。第三个问题或许因为板式的变化也受到影响了。不好意思啊。

  5. 好像最后的源代码显示有问题。真正的源代码就一个类Spider啊。源代码在这个网页的源文件中可以看到。