Python爬虫|Python爬虫入门(一):爬虫基本结构&简单实例

本爬虫系列入门教程假设读者仅有一点点Python基础或者近乎为零的基础。如果是有Python基础的可以跳过一些对于Python基本知识的补充。

本爬虫系列教程会持续完善,有看不懂的地方或者有错误的地方欢迎大家在评论区指出~如果是比较大的问题我会专门写专栏讲~

友情链接:标签 Crawler 下的文章 - xlzd杂谈 这是一个非常好的爬虫教程~推荐大家去学习~

系列专栏目录:

第一讲:Python爬虫|Python爬虫入门(一):爬虫基本结构&简单实例

第二讲:Python爬虫|Python爬虫入门(二):请求

第三讲:Python爬虫|Python爬虫入门(三):解析

第四讲:Python爬虫|Python爬虫入门(四):储存

------------------------萌萌哒的分割线------------------------


爬虫能干什么呢?一句话概括,正常通过浏览器可以获取的数据,爬虫都可以获取。这句话可以说是包罗万象。一是说明了爬虫的本质是一个服务端,实现的功能类似于浏览器;二是说明了爬虫的界限,如果不能正常访问到的数据就不能通过爬虫获取;三是爬虫的最高境界,只要是浏览器能正常访问的都可以用爬虫获取。更多爬虫的神奇用处,请戳:利用爬虫技术能做到哪些很酷很有趣很有用的事情? - 互联网 - 知乎

下面我们讲讲爬虫的基本结构和简单实现。这篇专栏我不准备详细地讲具体怎么写爬虫,只是先用一个非常简单的实现,给大家看看爬虫是个什么样子。详细的内容我们后面一个一个慢慢说。

一、爬虫的基本结构

让我们忽略掉来自各种各样的资料对于爬虫结构的描述,把问题尽可能地描述简单一点。前面说到,爬虫是一个获取正常浏览器可以获取的数据的自动化获取程序。那么,从这个功能出发,我们需要干的事情其实就两件事情:找到我们需要的网页,然后把他们一个一个处理一遍。(这句话很重要,我们在后面的后面讲到海量数据爬取策略的时候还要回到这句话。)那么问题就来了:一,怎么找到我们需要的网页的那个入口?二,怎么处理我们需要处理的网页?

对于单个页面来说,入口的来源有两种,一种是已知地址,比如我们院的网站的教学研究人员:教学研究人员 - WISE ;另外一种是你可以通过前面爬下来的网页中获取入口,比如这个页面上所有老师的个人主页。这一点很重要,后面我们在把小爬虫逐步变大的时候还要反复回到这里。

好的,后面的部分,让我们通过解决第二个问题(处理网页)的过程,顺便看看怎么解决第一个问题(获取更多入口)。我们一起开看看一个单页爬虫是怎么实现的。

二、爬虫实例:简单的单页爬虫

好了,现在我们要处理网页了。可是网页要怎么处理呢?让我们回忆一下我们使用浏览器的过程:你先把一个地址复制进浏览器的框框里面,或者点开一个链接;然后浏览器的进度条跑一下(有可能快也有可能慢),然后我们就在浏览器里面看到了数据。首先,进度条跑的过程完成了一个对网页的请求,然后浏览器把请求下来的数据进行处理,然后就输出出来。这是一个极其简化但是不太准确的对于浏览器工作原理的描述。那么爬虫和浏览器有什么不同呢?一般来说,我们是只需要解析网页,而不需要渲染浏览器环境的;另外,我们需要特定网页的特点数据,因此要用一定的方式把数据组织并储存起来。所以,爬虫的核心模块有三个:请求、解析、储存

首先我们给一个入口:教学研究人员 - WISE。这就是我们今天要处理的目标网页。我们今天要实现的目的就是把这个页面上所有老师的姓名和个人主页的链接(也就是可能的下一次爬虫的入口)提取出来。下面开始写爬虫吧~

1. 请求

这里我们使用的package是requests。这是一个第三方模块(具体怎么下载以后再说),对HTTP协议进行了高度封装,非常好用。所谓HTTP协议,简单地说就是一个请求过程。我们先不管这玩意是啥,以后再讨论。这个部分,我们要实现的目的是把网页请求(或者说下载)下来。

首先我们导入requests:

import requests

下面调用requests的get函数,把网页请求下来:

r = requests.get('http://www.wise.xmu.edu.cn/people/faculty')

返回的“r”的是一个包含了整个HTTP协议需要的各种各样的东西的对象。我们先不管都有啥,先把我们需要的网页提取出来:

html = r.content

好了,到这一步我们已经获取了网页的源代码。具体源代码是什么样的呢?右键,点击“查看源文件”或者“查看源”就可以看到:

view-source:http://www.wise.xmu.edu.cn/people/faculty

2. 解析

当然从这一大坨代码里面找信息太麻烦了。我们可以用浏览器提供的另外一个工具:审查元素。这里我们先不讲怎么使用审查元素,先从源代码里面找。找到的我们需要的信息如下:

 <div class="people_list">
        <table>
            <tr class="people_title">
                <th>
                    姓名
                </th>
                <th>
                    职称
                </th>

                <th>
                    电子邮件
                </th>
            </tr>
            
            <tr class="people_cate">
                <td colspan="4">
                    <a name="key0"></a><span>
                        B</span> <a class="more" href="#top">Top</a>
                </td>
            </tr>
            
            <tr>
                <td>
                    <a href="/people/faculty/4b901e30_5f2a_4609_96ee_2d154954d22e.html" target="_blank">
                        Bluhm, Marcel</a>
                </td>
                <td>
                    助理教授
                </td>
                <td>
                    bluhm@xmu.edu.cn
                </td>
            </tr>
            
            <tr>
                <td>
                    <a href="/people/faculty/47557237_8d2f_4f54_a889_7ea6b2e41c91.html" target="_blank">
                        Bowers, Roslyn</a>
                </td>
                <td>
                    英语教师
                </td>
                <td>
                    bowers.roslyn@yahoo.com
                </td>
            </tr>
            
            <tr>
                <td>
                    <a href="/people/faculty/b16b86f2_0eed_40da_ad4a_0b559864109e.html" target="_blank">
                        Caroline Botsford</a>
                </td>
                <td>
                    英语教师
                </td>
                <td>
                    carolinebotsford@hotmail.com
                </td>
            </tr>
            
            <tr>
                <td>
                    <a href="/people/faculty/85baa506_9087_4c89_979e_4a9fd19ff60b.html" target="_blank">
                        鲍小佳</a>
                </td>
                <td>
                    助理教授
                </td>
                <td>
                    xiaojiabao@xmu.edu.cn
                </td>
            </tr>
            
            <tr class="people_cate">
                <td colspan="4">
                    <a name="key1"></a><span>
                        C</span> <a class="more" href="#top">Top</a>
                </td>
            </tr>
            
            <tr>
                <td>
                    <a href="/people/faculty/d0c8f922_2c64_4bbb_99d9_b3d40a04cefe.html" target="_blank">
                        Chang, Seong Yeon</a>
                </td>
                <td>
                    助理教授
                </td>
                <td>
                    sychang@xmu.edu.cn
                </td>
            </tr>
            
//中间省略一大段相同结构的源码
            
            <tr>
                <td>
                    <a href="/people/faculty/c8d8f928_1fbf_4cdb_86e5_eb93b910e31b.html" target="_blank">
                        邹至庄</a>
                </td>
                <td>
                    教授
                </td>
                <td>
                    gchow@princeton.edu
                </td>
            </tr>
            
        </table>

这里我们使用bs4来解析。bs4是一个非常好的解析网页的库,后面我们会详细介绍。这次的解析先给大家看bs4里面最常用的几个BeautifulSoup对象的方法(method)。我们使用的这几个方法,主要是通过HTML的标签和标签里面的参数来定位,然后用特定方法(method)提取数据。

首先还是导入package:

from bs4 import BeautifulSoup

然后创建一个BeautifulSoup对象:

soup = BeautifulSoup(html,'html.parser')    #html.parser是解析器

下面我们根据我们看到的网页提取。首先提取我复制的这部分的代码的第一行,先定位到这部分代码:

div_people_list = soup.find('div', attrs={'class': 'people_list'})

这里我们使用了BeautifulSoup对象的find方法。这个方法的意思是找到带有‘div’这个标签并且参数包含" class = 'people_list' "的HTML代码。如果有多个的话,find方法就取第一个。那么如果有多个呢?正好我们后面就遇到了,现在我们要取出所有的“a”标签里面的内容:

a_s = div_people_list.find_all('a', attrs={'target': '_blank'})

这里我们使用find_all方法取出所有标签为“a”并且参数包含“ target = ‘_blank‘ ”的代码,返回一个列表。“a”标签里面的“href”参数是我们需要的老师个人主页的信息,而标签里面的文字是老师的姓名。我们继续:

for a in a_s:
    url = a['href']
    name = a.get_text()

这里我们使用BeautifulSoup支持的方法,使用类似于Python字典索引的方式把“a”标签里面“href”参数的值提取出来,赋值给url(Python实际上是对对象的引用),用get_text()方法把标签里面的文字提起出来。

事实上,使用这四个方法就可以正常地解析大部分HTML了。不过如果只用这四个方法,很多程序会写的异常原始。所以我们后面再继续介绍更多解析方法。

3. 储存

这里我们先弱化一下具体的储存方法,先输出到控制台上面。我们在刚才的代码的基础上加一行代码:

for a in a_s:
    url = a['href']
    name = a.get_text()
    print name,url

使用print关键词把得到的数据print出来。让我们看看结果:

# result

'''

                        Bluhm, Marcel /people/faculty/4b901e30_5f2a_4609_96ee_2d154954d22e.html

                        Bowers, Roslyn /people/faculty/47557237_8d2f_4f54_a889_7ea6b2e41c91.html

                        Caroline Botsford /people/faculty/b16b86f2_0eed_40da_ad4a_0b559864109e.html

                        鲍小佳 /people/faculty/85baa506_9087_4c89_979e_4a9fd19ff60b.html

                        Chang, Seong Yeon /people/faculty/d0c8f922_2c64_4bbb_99d9_b3d40a04cefe.html

                        蔡熙乾 /people/faculty/f642c7bf_ac86_42dd_a6ac_a85720d45c8e.html

                        蔡宗武 /people/faculty/55981260_ddce_43aa_97b5_3d7ad0ae2844.html

                        陈灯塔 /people/faculty/899ecc03_5fc6_4fd7_89d7_af93901ef6b1.html

                        陈国进 /people/faculty/22627c95_155a_4f18_a586_df9ac4f1d7ce.html

                        陈海强 /people/faculty/382f444e_a849_4818_9d34_ed6347d9cbf7.html

                        程立新 /people/faculty/ab01c285_bbcc_4354_b27e_3bfb947a3690.html

                        丁锦秀 /people/faculty/de839f24_9947_43a6_9857_580ec3d07e2d.html

                        董晓芳 /people/faculty/abd60523_953f_48aa_862d_4b0893c88f4a.html

                        范青亮 /people/faculty/739b6285_0f8e_4683_b71c_640a896b687f.html

                        方颖 /people/faculty/94656316_8cb0_4d02_a822_4d06c12dddbe.html

                        冯峥晖 /people/faculty/cb02c396_6b12_497f_a724_9127aa37da33.html

                        Graham, Brett  /people/faculty/3af92170_844d_48a4_875f_98ed85d04207.html

                        耿森 /people/faculty/04a8870f_d728_4e83_ba95_1d00b53cf6df.html

                        龚天益 /people/faculty/d7c4cd68_7489_419a_a23a_85265e67d6f9.html

                        管中闵 /people/faculty/d7ecca89_f116_4757_8c1e_759e435ab813.html

                        郭晔 /people/faculty/69499729_7f5d_4b32_9a3d_29413a8e7f71.html

                        韩乾 /people/faculty/27b6b1c7_9787_4747_bd44_9f2e481b5a0f.html

                        韩晓祎 /people/faculty/f0852907_3fc8_422e_8517_4c2c6343d3fa.html

                        何亚男 /people/faculty/04cbc55f_a447_4e01_b30b_ebf9d01b6f4c.html

                        洪永淼 /people/faculty/07848586_e55c_4e2b_8934_4df456307d7b.html

                        黄娟娟 /people/faculty/e03b1af7_9119_49d8_ac3a_1fd7e4843ee2.html

                        薛绍杰 /people/faculty/cb05eba1_f8f9_419d_86f3_f6d7e557d006.html

                        荆海伟 /people/faculty/5f0a030f_bcdb_4c92_87f8_f16fc4a454cc.html

                        赖小琼 /people/faculty/159be896_9a94_4bb9_b967_65dacbef6332.html

                        李嘉楠 /people/faculty/45495497_f951_4f46_8546_17bafe4148e9.html

                        李梦玲 /people/faculty/44f6af2b_a423_4913_83ed_f83d0fa635e5.html

                        李木易 /people/faculty/386198a6_ff09_4105_8337_98be8d9eaf50.html

                        李培 /people/faculty/8799c2eb_2ac1_4354_b2a6_25f60eb93aa5.html

                        李迎星 /people/faculty/91a6e77b_4e97_4a7b_98ba_15a08f8bc5ef.html

                        李志文 /people/faculty/67b3184d_9989_42f1_84e4_c280962320a2.html

                        李智 /people/faculty/22c3d25f_913e_4f03_b40f_cd80a71a8cf7.html

                        廖谋华 /people/faculty/76d14b07_96cd_40de_bff1_276647bafb88.html

                        林光平 /people/faculty/b5a0449b_d991_4345_8802_e45be1adbda3.html

                        林海 /people/faculty/bf8bd4a1_dca2_4c08_8128_91120a5ffd84.html

                        林娟 /people/faculty/6714b425_91ba_40b4_95a1_e98299ffd21d.html

                        林明 /people/faculty/fadf2e50_6736_43b6_94a4_f0d69a3efb4b.html

                        刘鼎铭 /people/faculty/92f33f3c_4cdb_4abf_b030_8942ec17329f.html

                        刘继春 /people/faculty/aad04279_03c4_4182_be07_4bf5f59f0e41.html

                        刘婧媛 /people/faculty/c85a8534_b940_4fad_b220_1e9ed73aacf0.html

                        龙小宁 /people/faculty/a4ba4fec_65fa_4775_9802_0200645bca74.html

                        马超 /people/faculty/e1544cf5_21a6_4c35_b03f_3ba4845ef11c.html

                        马双鸽 /people/faculty/d8d1b107_2dfc_437a_b302_e4a1b43f0817.html

                        茅家铭 /people/faculty/600cf256_34ab_465b_8f60_d7a15bf56934.html

                        蒙莉娜 /people/faculty/61cd935f_51d0_4891_805e_b43354688765.html

                        孟磊 /people/faculty/78bdea7b_42dd_456c_bbc2_02c1db9ff980.html

                        牛霖琳 /people/faculty/3dd722d5_3c4f_41c2_a7bc_c69948e4714f.html

                        潘越 /people/faculty/a2c16c29_ba98_4883_bf69_a63d7de6c43f.html

                        屈文洲 /people/faculty/7b9aa674_62fb_4acf_b293_ff569f0a991a.html

                        任宇 /people/faculty/b134ac71_c990_4578_a730_4e90e1c50a4d.html

                        White, Chris /people/faculty/4c9e3afb_cb0b_4746_bbd5_e9e4302ed93a.html

                        王璐航 /people/faculty/dcb7ab35_a252_4e37_a31d_9ce86229cd85.html

                        王学新 /people/faculty/cfecc858_9c39_4fff_b056_eaf5999b83e6.html

                        王艺明 /people/faculty/f4448009_5c81_4725_9798_42ce40412ffb.html

                        王云 /people/faculty/06fc08d7_5dbd_4d28_8de9_4e7b57c04163.html

                        萧政 /people/faculty/da83c84c_cb80_431c_97ea_0bb6bd31745f.html

                        谢沛霖 /people/faculty/a9a0a3b2_99cb_43a6_b683_43861065fe38.html

                        徐海峰 /people/faculty/faa2370a_0b25_40c5_80f3_75862906b6a3.html

                        许文超 /people/faculty/dc8a8b18_3b1e_443d_bd49_81d15fd56cde.html

                        杨荷 /people/faculty/90b06e5e_d49d_43e1_b18c_dd3c855e001c.html

                        姚加权 /people/faculty/0550534a_6c10_4e82_930c_20cec564e781.html

                        叶茂亮 /people/faculty/39653e4b_d311_4de5_8974_041b546ad9dc.html

                        张晶 /people/faculty/9ce540c8_708e_4cf7_8f37_9f00c7edc6a5.html

                        张烁珣 /people/faculty/17d9773b_6c4d_4314_b35f_ba0d614e2164.html

                        张宇 /people/faculty/e9bd8598_728f_490d_ab99_87bf6828d544.html

                        赵宏飙 /people/faculty/81a49a75_1576_4127_983c_3922c8d30e3b.html

                        赵敏强 /people/faculty/1c12aee5_f441_4978_b4d8_e7e71668e114.html

                        赵西亮 /people/faculty/86e0f1dd_132f_424c_a14d_ababd7e46463.html

                        赵燕菁 /people/faculty/66984253_3868_41cc_92da_f17231137282.html

                        郑鸣 /people/faculty/721ba480_06f3_4c63_8a91_a562159360ff.html

                        郑挺国 /people/faculty/c5e82359_fd50_4b65_b263_cd974783eb0d.html

                        钟威 /people/faculty/353d37aa_7187_4486_9712_9f70cf6c4222.html

                        衷楠 /people/faculty/58717416_c68a_48a5_a60c_8457ddc06e8b.html

                        周颖刚 /people/faculty/78caf248_ab50_47bc_8f9d_2351a66d1db0.html

                        邹至庄 /people/faculty/c8d8f928_1fbf_4cdb_86e5_eb93b910e31b.html

'''

好的,到这里一个原型就完成了。这就是一个非常简单的爬虫,总代码不过十几行。复杂到几百几千行的爬虫,都是在这样的一个原型的基础上不断深化、不断完善得到的。

后面的爬虫系列,我们会详细讲解三个部分,然后把每个模块拼起来成一个爬虫。之后我们还会见到更多爬虫方法和爬虫实例。我们下次见~


------------------------萌萌哒的分割线------------------------


非商业转载注明作者即可,商业转载请联系作者授权并支付稿费。本专栏已授权“维权骑士”网站(rightknights.com)对我在知乎发布文章的版权侵权行为进行追究与维权。


项目联系方式:

编辑于 2017-02-07

文章被以下专栏收录

    WISER Club是厦门大学的一个数据科学(包括但不限于R&Python)学习兴趣组织,我们团队有一批对R语言和Python有浓厚兴趣的爱好者,我们将要承担第九届中国R语言会议(厦门会场)的举办。我们想通过这个专栏给大家分享一些关于R、关于Python、关于数据科学的技术文章和资源。

    微信公众号同名,欢迎投稿。全平台约20万开发者关注,会员来自全球十多个国家和地区,拥有十多个线上线下技术社群,向本专栏投稿即默认发布到Python中文社区全平台。Telegram:t.me/PyChina