碎碎念:最近一直在忙着科研搞毕设,博客好久木有更新了。某一天妹子突然说要让我帮她写个爬虫,貌似在她眼里,所有和电脑相关的事儿,程序员都能搞的定…….哈哈,作为一个立志要改变世界的程序员,用Python写爬虫当然是so easy的一件事!废话不多说,直接上正文吧。
1、目标
爬取大众点评上“武汉”这个城市下面所有齿科医院的地址。
2、基本思路
首先,你先想想自己作为一个人是如何去完成这件事的呢?括号内为爬虫是如何实现相同效果的。
Created with Raphaël 2.1.0
打开大众点评首页
选择地区为“武汉”
在搜索框中输入“齿科”
(爬虫访问包含了关键词的URL)
复制页面中的各个诊所的名字和地址到记事本中
(用正则表达式获取想要的字段,并将其保存成txt文件)
收集完毕?
大功告成!
点击“下一页”(输入页数,用
for循环来收集多个页面的信息)
yes
no
而我们写爬虫其实也是为了让计算机去模拟这个行为。
3、具体操作
这里我们观察一下地址栏的变化。图1是将城市切换到武汉之后的URL,图2是输入搜索词之后的URL,图3是点击“下一页”后的URL。
这里讲下什么是URL。
URL是Uniform Resource Locator的缩写,译为“统一资源定位 符”。
通俗地说,URL是Internet上描述信息资源的字符串,主要用在各种WWW客户程序和服务器程序上。采用URL可以用一种统一的格式来描述各种信息资源,包括文件、服务器的地址和目录等。
URL的一般格式为(带方括号[]的为可选项):
protocol :// hostname[:port] / path / [;parameters][?query]#fragment
URL的格式由三部分组成:
①第一部分是协议(或称为服务方式)。
②第二部分是存有该资源的主机IP地址(有时也包括端口号)。
③第三部分是主机资源的具体地址,如目录和文件名等。
第一部分和第二部分用“://”符号隔开,
第二部分和第三部分用“/”符号隔开。
第一部分和第二部分是不可缺少的,第三部分有时可以省略。
知道了这个,让我们重点关注下图2,图2中的方框1(“/search/keyword”)代表的是搜索关键词的路径,方框2(“16”)代表的是武汉这个城市的编号,方框3和方框4表示的是搜索词!
而图3中的内容我们该如何理解呢?经过我的几次实验后,发现“p2”代表的是“page 2”,也就是“第二页”的意思,最后的“?aid=……..”属于 query string,可以忽略,一般是用来标记网页自身的一些信息,所以我们只要改变“p”后面所带的数字,就能实现翻页的效果了!
所以我们就知道了,如果你想搜索任意的一个词,那么在地址栏中按照如下的格式输入即可。
协议(http://) + 域名(www.dianping.com)+ 路径(/search/keyword) + 前缀(/0_) + 关键词(齿科) + 页数 (/p) + 具体页数
4、实际代码
这里因为是要教妹子的,所以加了比较多的注释。这里吐槽下Python 2.X的默认编码居然是ASCII码,然后这个爬虫一半的时间都是用来处理中文编码的问题……..=、=
据说Python 3 处理中文编码会顺畅很多,所以大家还是快快上手Python 3吧,然后在用到Python 2.X时再做个“优雅降级”。
#! python3
# coding:utf-8
import urllib2
import urllib
import re
import os
import shutil # 高效处理文件的模块
#sys为system的缩写,引入此模块是为了改变默认编码
import sys
reload(sys)
sys.setdefaultencoding('utf8') #设置系统的编码为utf8,便于输入中文
host = 'http://www.dianping.com'
#自定义UA头部,直接用即可,不用理解细节
user_agent = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.89 Safari/537.36'
headers = {'User-Agent':user_agent}
key_word = '齿科' #写好要搜索的关键词
city_num = str(16) #武汉的城市编码为16,其他城市的编码可以在点评网的URL中找到
directory = city_num + '\\' + unicode(key_word,'utf8') #Windows系统下,创建中文目录名前需要制定编码,这里统一用UTF-8
if not os.path.exists(directory):
os.makedirs(directory)
print ('create directory successfully')
else:
shutil.rmtree(directory)
os.makedirs(directory) #删除后再创建对应的关键词目录
print ('delete existed directory successfully')
url = host + '/search/keyword/' + city_num
def getDocument(page):
page = str(page)
path_name = directory + '\\page_' + page + '.txt'
file = open(path_name, 'w+'); #创建文件
#由于要搜索的关键词是中文,所以需要进行转码,这里调用了urllib.pathname2url函数
real_url = url + '/' + '0_' + urllib.pathname2url(key_word) + '/p' + page
request = urllib2.Request(real_url, headers = headers) #发送网络请求
response = urllib2.urlopen(request) #得到网络响应
document = response.read().encode('utf-8') #将网页源码用UTF-8解码
items_name = re.findall(r'data-hippo-type="shop"\stitle="([^"]+)"', document, re.S) #正则匹配出商家名
items_address = re.findall(r'([^\s]+)', document, re.S) #正则匹配出地址
result = ''
for index in range(len(items_name)):
result += items_name[index] + ' ' + items_address[index] + '\n'
file.write(result) #将结果存入文件
file.close()
print ('Complete!')
def start_crawl():
for index in range(0, 5):
getDocument(index)
start_crawl() #开始爬数据!