零基础简单爬虫制作(以wjyt-china企业黄页爬虫为例)(中)

四、JavaScript
在“菜鸟教程”或“w3school在线教程”可进行完整地入门学习。 深入学习请参阅《JavaScript高级程序设计》。
JavaScript 是网页编程语言。所有现代的 HTML 页面都使用 JavaScript。
在网页的源代码中,JavaScript被<script>...</script> 标签包裹,浏览器会理解并运行插入的JavaScript代码。JavaScript代码给网页带来生命,让网页从静态变为动态。JavaScript可以修改整个网页的内容或结构,可以为网页动态加载内容,可以验证用户提交的信息……
JavaScript有很多种赋予网页动作的方式,最常见的是监听网页事件,当对应事件发生时调用对应函数。网页事件就是我们在网页上的各类操作,例如移动鼠标,点击鼠标,敲击键盘等。函数是一系列编程语言语句的集合,也即一系列行为的集合。假使说“迈出左脚”是一个编程行为,“迈出右脚”是另外一个,那么两个合起来就可以写作一个函数“走一步”。总的效果就是,当我们在网页上进行某个特殊的操作时,JavaScript就会按照设定产生对应的反应。例如这段代码,<button onclick=某个函数>按钮名称</button> 就生成了一个按钮,当我们单击它时,就激活了onclick关键字(网页事件和对应的关键字名称容易查到)对应的函数。我们可以通过函数名去调用一个函数,也可以在函数名的位置直接把函数的内容写出来。
在掌握了一定的基础知识之后,让我们回到教学用例。我们已经分析过HTML,了解了当前页面上的公司信息是如何储存的。但是当前页面上展示的并不是全部的公司。
这里写图片描述
我们需要访问“下一页”继续获取信息。那么这个“下一页”是不是像之前给出的那样,是一个button元素,监听着onclick事件呢?很可惜,并不是。本例的JavaScript代码是以另外的方式运作的。JavaScript的内容较多,在编写爬虫的时候,常常会遇到意料之外的情况。这时候,就需要我们灵活地分析。
通过箭头工具定位“下一页”按钮的源代码,如图:
这里写图片描述
这说明“下一页”按钮,包括之前的带有数字的页面转跳按钮,都是通过<a> 超链接实现的,他们的工作方式是激活一个值为’javascript:gotoPage(页面数)’的href。可以猜到,这个链接通向一段JavaScript代码,这段代码将会调用gotoPage函数进行页面转跳。我们是不是需要先追踪找到这段JavaScript代码,再分析JavaScript代码的行为呢?本例中,我们采取了更直接的办法。
不论中间有多少弯弯绕绕,最终我们看到的是第二页信息的加载。而新的信息来自一个新的URL。那么,我们只需要找到这个URL就可以了。我们既可以从网页的JavaScript代码入手(假如代码中清晰地说明了新URL的构造规则),也可以绕过JavaScript,直接监听浏览器与网站的交互。在本例中,JavaScript代码的位置不容易找到,所以我们绕过JavaScript采取第二种手段。
这个新的URL是什么呢?我们首先观察浏览器网址栏中的网址。不同黄页页面的网址似乎都是一样的。网址中并没有出现‘’/页面数/‘’这样的结构。这可能是因为,虽然主要的地址是相同的,但是用户向这个地址提交的请求却并不相同。以登录网站为例,不同的人虽然访问的是同一个网站,但是因为每个人向这个网站提交的用户名和密码不同,他们看到的结果就各不相同了。这样登录网站的URL形如http://exampleWebsite?username=exampleName&password=examplePassword。这样的URL具有典型的?&结构。?接在一个主要的网址之后,代表在访问网址的时候同时提交请求,而各个请求由&隔开。这个例子网址的含义是,访问exampleWebsite网址,同时提交用户名为exampleName,密码为examplePassword的请求。观察网址http://www.wjyt-china.org/pagecontrol.do?action=mygslist&object=ToyCompanyYellowAction。我们猜测这个URL的含义是,访问http://www.wjyt-china.org/pagecontrol.do这个地址(根据名称猜想是一个页面控制器),同时提交action=mygslist(访问行为大概是“贸易公司表单”)和object=ToyCompanyYellowAction(访问的对象是玩具公司黄页)两个请求。如果我们能够在这个URL的基础上再加上类似于“&关键字=页面数”的结构,就应该能够访问不同的页面了。
如何寻找到这个关键字呢?我们点击下一页按钮,监测浏览器向网站发出的请求的内容,然后模仿这个请求。开发者工具可以帮助我们监测浏览器与网站的交流。打开开发者工具,进入Network选项卡,监测选项为All(默认)。此时点击下一页。
这里写图片描述
点击下一页后,浏览器的第一个行为正是对这个网站发送请求。点击这个项目,右侧会弹出请求的详细资料。在其中寻找和页面数有关的信息。
这里写图片描述
我们看到了jumpPage关键字,他的值为2。想必就是这个关键字让我们转跳至第二页。我们自己来试一试。访问http://www.wjyt-china.org/pagecontrol.do?action=mygslist&object=ToyCompanyYellowAction&jumpPage=3。成功了!我们转跳到了第三页。这样,只要修改jumpPage的值,我们就可以访问任意页面了。我们一共需要爬取多少页呢?通过手动操作二分法(一种逼近方法,每次取中点),我们发现共有369页,约5500条公司信息。因为这些公司信息的储存方式都是一致的,所以,我们已经掌握了所有目标信息的储存方式。
当我们对需要爬取的对象了如指掌时,网页分析阶段就结束了。

五、Python
请参阅《简明Python教程》。
Python语言容易学习。但是,由于爬取源代码后对于源代码的分析完全基于Python语言,这要求我们有一定的用Python语言解决问题的能力。而对能力的要求和要解决问题的复杂程度是成正比的,本教程不可能也不试图解决所有的问题。因此,这里将不会进行详细的Python语言教学,仅简要提及Python中与爬虫和本教学用例有关的基础知识。请善用《简明Python教程》及搜索引擎。

(一) Python的基本语法
下面简单介绍一部分相关Python语法。
基本知识:
编写Python语言需要编辑器,请利用搜索引擎搜索安装方法。官方的Python IDLE提示功能较弱,如需更完善的功能,推荐使用pycharm。官方Python IDLE打开后为交互页面,可以即时进行代码交互,但爬虫请储存在新建文件(file菜单-new file选项)中。
Python语言(几乎所有的编程语言都)需要英文环境。编码时注意切换输入法至英文,否则会产生如混淆中文括号与英文括号等难以察觉的错误。
Python语句中没有中文字符,但允许在字符串中使用中文字符,前提是要在文件的第一行标明#coding:utf-8,声明本文件采用utf-8编码(一种涵盖了包括中文在内的绝大多数语言的编码模式)。
Python语言中,# 后引导的为注释。不被编辑器解析,仅供人阅读。
Python中的基本储存单元为变量,一个名字就声明一个变量。一个变量像是“一个东西”,因而也称为一个对象。
函数是一系列语句也即一系列程序行为的集合。函数通过def 关键字来定义,之后接函数名,以及函数的传入参数。函数体需要用空格或tab键缩进标示出来。函数被定义之后并不执行,当通过函数名调用这个函数时才发挥作用。函数定义如:

def myFunction(parameter):
    ...
    behaviours
    ...

一些对象具有方法。方法是一个对象可以进行的行为,实际上是一个对象含有的函数。可以通过点操作符调用对象的方法,形如object.method()

基本语句:

import urllib2#import语句能够将现成的库加载进当前文件
              #库被加载之后才能够使用
              #本例加载了之后要学习使用的urllib2库

print 'hello world'#print语句将字符串输出到界面上
                   #常用于监测程序进程或输出程序结果
                   #本例输出结果为hello world

myVariable = 42#赋值语句由一个变量名,一个等号和另一个对象构成
               #赋值语句将后面的对象赋值给前面的变量
               #一个变量名首次出现时必须是在赋值语句的前端,此时它才被创建
myVariable = 233#一个变量可以被重新赋予其他值
myVariable = 'hello world'#甚至是其他类型的值
                          #本例中myVariable从一个数字变成了一个字符串

基本结构:

#if-else结构,用于条件判断
if condition:
    ...
else:
    ...

#for循环,用于循环执行某段代码
#range(1,10)提供了从1到9的9个数字,变量i会被递增地赋予这9个值
#因此本例for循环函数体内的代码会执行9次
for i in range(1,10):
    ...

#函数,函数可以具有返回值,返回值可用于赋值变量
def myFunction(parameter):
    ...
    return 42
result = myFunction()
print result#结果为42

#try-except结构,用于处理代码运行中的异常
#本例处理异常的方式是将异常信息print出来
try:
    ...
except someError,e:
    print e

(二) Python的文件操作
如果爬虫爬取的数据量很小,我们可以直接将这些数据print出来。但是本次教学用例需要爬取至少5500个公司名称,这样的数据量直接print出来会导致混乱和低效。我们应该将爬取的数据储存起来。这就涉及到通过Python操作文件的知识。在本例中,我们只需要操作txt文件,将公司名写入其中即可。

totalName = open(r'...\totalName.txt','w')
#通过open语句打开一个文件
#本例中将爬取到的公司名储存在totalName.txt文件中
#本例中以totalName做为totalName.txt文件在Python中的变量名
#r'...'为原生字符串,以这种字符串表示地址可以避免地址中\符号带来的意外错误
#'w'代表以写(write)模式打开文件,否则我们不能向一个文件写入信息
#写入是有风险的。程序开始时如果被写入的文件中已经有内容,写入操作会将文件清空

totalName.write(companyName)
#通过write语句写入信息
#本例中companyName为我们已经抓取到的公司名称

totalName.flush()
#通过flush语句将缓存中的信息写入硬盘
#write命令可能并不立即生效,而及时地将信息写入是重要的
#万一程序因为异常中途崩溃,而write的信息仍处于缓存中尚未写入
#那么信息将会丢失,而你的时间将会被浪费

totalName.close()
#通过close语句,在文件使用完毕后将文件关闭
#虽然程序正常结束后会自动关闭打开的文件
#但是程序可能无法正常地结束
#那么信息将会丢失,而你的时间将会被浪费

(三) Python的正则表达式
请学习博客《Python爬虫入门七之正则表达式》http://cuiqingcai.com/977.html
在网页分析阶段,我们掌握了目标信息在源代码中的储存位置。如何让程序能够找到这些信息呢?答案是通过“地标”(一个比喻而非专有名词)——特殊的信息样式。“地标”通常是独特的关键字,例如,含有目标信息的<div> 元素的class关键字的值。我们只需要让程序找到这些特殊的“地标”,就能进一步找到目标信息。
对特定样式的搜寻通过字符匹配实现。而字符匹配的一个强大的工具就是正则表达式。正则表达式是一种既简单又复杂的工具。其简单之处在于符号简洁,逻辑清楚。而复杂之处在于功能众多,熟练掌握需要一定的练习。
正则表达式在许多编程语言中都有出现,而我们仅学习的Python语言中的。引用一张Python正则表达式语法说明图。
这里写图片描述
关于Python正则表达式的完整内容请于推荐的博客中学习。在这里仅简要介绍教学用例爬虫中将要使用的正则表达式。

 pattern = re.compile(
 '<div class="neir_neir".*?<a.*?href=".*?shopname=(.*?)">(.*?)</a><span>'
 ,re.S)

这是在企业黄页界面进行字符匹配使用的正则表达式。代码的其他部分在学习推荐博客内容后即可理解。这里仅解释最关键的第二行代码。.*? 是一个固定搭配,含义为匹配尽量短的任意内容,这帮助我们忽略无关的信息。而(.*?) 的含义为将该位置的任意内容(尽量短的)抓取出来,这些就是我们想要的目标信息。
因此,这句正则表达式的含义是——匹配具有如下格式的字符:<div class="neir_neir"任意内容<a任意内容href="任意内容shopname=目标信息">目标信息</a><span> 。这个格式正是黄页中公司信息的储存方式。独特的“地标”信息被作为匹配的向导,中间的内容不做要求,目标信息则抓取出来。

pattern = re.compile('<div class="neiR".*?">(.*?)</div>',re.S)

这是在企业介绍界面进行字符匹配使用的正则表达式。这段正则表达式匹配的格式为<div class="neiR"任意内容">目标信息</div> 。目标信息是公司介绍文本的储存位置。
Python的正则表达式有很多匹配方式。例如match方法会从头开始匹配,如果被匹配文本的第一个字符不能匹配就会终止匹配,search方法则会搜索被匹配文本的全部内容,查找是否有匹配目标。在教学用例中,统一采取了findall方法,这个方法会返还被匹配文本中所有的匹配项。在企业黄页中,一页内所有的公司信息储存格式都是相同的,findall方法可以一次性抓取所有的公司信息。在公司介绍页面中,只存在一个介绍文本,但是为了方便我们依然使用了findall方法。

我们已经初步了解了Python语言,具有了一定通过Python语言制作爬虫,分析源码的能力。Python的学习可以暂时告以段落了。
(未完待续)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值