目录

1网站目标:

2网站分析

2.1第一步获取月份

2.2第二部根据月份获取城市url

2.3第三部根据top5景点链接获取景点信息

3所用技术

3.1爬取技术

3.1.1模仿浏览器请求数据包

3.1.2正则表达式提取关键信息,动态构建url请求

3.1.3Beautifulsoup大量获取

3.1.4Xpath精确定位

3.1.5url字典

3.2反扒技术

3.2.1Useragent轮转,PC,安卓,IOS

3.2.2IP代理池设置,免费代理ip获取

3.2.3虚假访问延迟

3.2.4绕开蜜罐

3.3存取技术

3.3.1Json文件存取

3.3.2Sheet分组Excel储存

3.3.3异常不中断爬取

4.原码连接


1网站目标:

Host:马蜂窝旅游网

内容:当季推荐,http://www.mafengwo.cn/mdd/filter-tag-140.html

任务:获取当季推荐所有页数的国家/城市,按国家/城市,获取Top5景点,按景点获取主要数据

2网站分析

2.1第一步获取月份

该网页信息根据月份进行分组,推荐适合当季的观光处,我们在浏览器谷歌浏览器右键检查,选择网络监视窗,重新加载,即可看到传送过来的数据包,不同月数和页数通过FormData传递参数。

依次点开各月份可以发现,月份属性从113开始以3为步长递增。我们可以将所有月份和页数储存在数组中,然后动态生成FormData,这个数据需要我们经常维护。

月份由主机系统时间确定,time.localtime可以获得一个本地时间的元组,第二位表示月份具体使用可以百度

所有月份:113,116,119,122,125,128,131,134,137,140,143,146

所有页数:1,2,3

部分代码如下

class FengWo_crawler:def __init__(self):self.monthList = [113,116,119,122,125,128,131,134,137,140,143,146]self.pageList = [1,2,3]self.time = time.localtime(time.time())self.monthNum = self.monthList[self.time[1]-1]

2.2第二部根据月份获取城市url

我们有了月份便可以获得当即推荐观光数据,数据为json数据包,可通过抓包获取。

Json文件的list键对应显示景点部分的html,已经变为字符串。我们可以先将字符串复制出,利用网上的html格式化工具,美化html,格式如下

这一部分可以通过BeautifulSoup类库获取所有li标签下面的a标签,从而获取链接。

链接内含有城市id,我们要获取的是城市的top5景点,可以从前一个链接提取城市id,然后组装为top5景点url

当即推荐国家城市url:   http://www.mafengwo.cn/travel-scenic-spot/mafengwo/10183.html

城市id:10183

城市top5url:     http://www.mafengwo.cn/jd/10183/gonglve.html

2.3第三部根据top5景点链接获取景点信息

有了top5景点页面,即可获得top5景点url,根据url获取景点详细信息页面,最后使用xpath进行精确爬取。

3所用技术

3.1爬取技术

3.1.1模仿浏览器请求数据包

直接请求数据包可以加快爬虫的速度,缺点是要设置繁琐请求头。项目中都是使用直接请求数据包的形式爬虫的,如下示例获取当季推荐国家/城市:

首先构建formData,将构建好的formData和url作为参数放入request请求中即可获得对于的json数据包,在将json中的list键对应的数据取出

headers为了模仿浏览器而设置的请求头。

Data是所请求数据的筛选条件,有不同请求目标决定是否可选

Proxies是设置代理IP,如设置{localhost:8080}即是本机,同不设置

Verify用于设置是否取消代理警报

我们获得json数据后将里面好的html数据的部分取出,然后使用BeautifulSoup类库解析,建后面章节

class FengWo_crawler:def __init__(self): self.headers = { ... ...  }def getCountryID(self):for item in self.pageList:form_data = 'tag%5B%5D=' + str(self.monthNum) + '&page=' + str(item)... ...req=requests.post(url=self.url_,data=form_data,headers=self.headers,proxies=self.proxies,verify=False).json()......

3.1.2正则表达式提取关键信息,动态构建url请求

还记得我们上述的国家城市url吗:

http://www.mafengwo.cn/travel-scenic-spot/mafengwo/10183.html

其中的10183即使地区id,我们要想办法将他提取出来,然后构建地区的景点信息。通过下面函数即可。

re是python的正则类库,‘\d+’标识只匹配数字且不限制位数,findall方法会匹配所有符合的结果并返回一个数组

在这里,getNum方法会将获得的地区ID储存在全局数组中,然后再利用getNewMddUrl函数构建地区的景点界面url

    def getNum(self,url_str,):pattern = re.compile(r'\d+')m = pattern.findall(url_str)return int(m[0])def getNewMddUrl(self):for cityId in self.CityID:url = 'http://www.mafengwo.cn/jd/'+str(cityId)+'/gonglve.html'self.mdd_urlList.append(url)

3.1.3Beautifulsoup大量获取

在3.1.1小结代码的后保部分,我们讲到了使用BeautifulSoup类库解析数据,这里详细讲解。

如下面这段代码,html参数是数据源,字符串,xml,html等格式皆可,后面的'html.parser'代表将要转换的目标格式,通过将无序文本转换为节点文本,我们可实现数据的精确提取。

Find_all()方法可匹配所有符合的结果,返回数组,可接收两个参数,’li’代表标签类型,也可进行补充描述,如class_ =  ‘???’,注意,这里的class_后面多了一个要加一个下划线,其他属性亦可,如name=’***’,type=’***’

如下面的使用find就包含两个参数,不过find是只查找一个节点。

soup = BeautifulSoup(html, 'html.parser')
for li in soup.find_all('li'):a = li.find('div',class_="img").find('a')self.CityID.append(self.getNum(a['href']))

3.1.4Xpath精确定位

Xpath代表当前节点在文本中的路径,适合爬取固定模板显示的零散信息,主要在爬取景点界面的信息部分使用。

Xpath的写法很多,学起来有一定成本,这里的xpath由火狐浏览器提供,右键页面,查看元素,使用元素选择器,选择元素右键,即可复制xpath

例如这段代码:先是将文本转换为html文件,然后使用xpath获取title标签的text内容

html = req.text
html_ = etree.HTML(html)
a = html_.xpath('/html/head/title')[0].text

3.1.5url字典

如果想要更快的爬取,那就要使用多线程执行任务,这样url必须有一个集合来储存,具体结构,视情况而定。在本次任务,由于城市有很多景点,所以爬取景点内容适合使用多线程来执行。这里依旧是抓包爬取,可以减少诸如图片传输,可以加速爬虫。

这里我们观察两个日本景点的请求头,都是相同的键值即

Referer:http://www.mafengwo.cn/jd/10183/gonglve.html

所以我们在爬取需要为不同城市的景点动态设置Referer,最后储存的结构如下

如下函数,我们将区域的url储存在LIst中,然后进行迭代,作为Top5城市url列表的Key键。

def getGonglveUrl(self):for item in self.mdd_urlList:... ...list = []try:for div in soup.find('div',class_='row row-top5').find_all('div',class_='info'):href = div.find('div',class_='middle').find('h3').find('a')['href']list.append('http://www.mafengwo.cn'+href)self.gonglve_url[item] = listexcept:print 'error'#print self.gonglve_url

3.2反扒技术

3.2.1Useragent轮转,PC,安卓,IOS

爬虫很少会为被爬取的网站创造利益,反倒经常因为爬虫程序大量的访问造成服务器瘫痪,数据的大量采集也是网站经营者不愿意看到的,对于网站经营者来说,既要兼顾客户体验,又要防止爬虫,这是很头疼的,所以为了稳定的数据源,我们爬虫也应该适可而止。保证我们数据来源的同时,还要兼顾数据源服务器的性能。

在我们使用浏览器访问网站时,会有一串信息表示访问者的身份,识别身份应该是防止爬虫的第一关卡,我们可以伪造一段信息,加载光秃秃的request请求中。大部分信息如下。

'User-Agent'键是你的浏览器信息,包含了你的操作系统,浏览器内核等等。

*Url即是目标网站连接,必选

'Referer'键代表你是从那个页面进入这个你要访问的界面的,这个比较有趣,有时你直接复制链接访问某个网站的分页面就是让你进行验证码识别,如果我们不设置referer,也会遇到这种情况。

self.headers = {'Accept': 'application/json,text/javascript,*/*;q=0.01','Connection': 'keep-alive','Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8','Referer': 'http://www.mafengwo.cn/mdd/filter-tag-1400.html','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3610.2 Safari/537.36','X-Requested-With': 'XMLHttpRequest'}

这里我们可以做文章的地方就是 User-Agent,我们收集了大量useragent,随机取出,替换原来的header[‘referer’],每一个usergent都可以生成一个新的headers,即一个新的访问。

self.dict = UserAgent.MY_USER_AGENT
self.headers['User-Agent'] = random.sample(self.dict, 1)[0]

3.2.2IP代理池设置,免费代理ip获取

设置请求头让似乎让我们人多势众起来,不过这时候的程序仍然只是个笨拙的虫子,如果这是目标网站网络监测员正在工作,他会发现某一栋办公楼或学校宿舍内几十个用户在不断的访问自己的网站,因为他们的ip似乎是相同的,或者差不多,而且他们既不访问支付界面,也不是漫无目的的,而是有针对的访问特定界面,就此,爬虫与反爬上升为ip层面。

我们可以在请求中设置代理ip,代理ip可以代替我们访问目标网站,然后将获得的数据传递给我们,免费的代理ip可以从西刺网爬取,据说西刺为了防止爬取提供了一个txt文档,不过我没找到,我用的不多,只爬几页就够了。

如下截图,设置1就爬1页,爬虫中已经对ip进行预筛选,存活时间小于1天的不要,延迟大于200ms的不要。

当然程序还有不足之处。爬好的ip储存在json中,要手动为json加【】才能导出

这些ip代理毕竟是免费的,经过预筛选还会出现失效的ip,这是需要二次删选,即让它去ping一个网站,如果能ping通,那就能用。如下代码测试,查看ip的丢包率

    def check_ip(self):cmd = "ping -n 3 -w 3 %s" # 命令 -n 要发送的回显请求数 -w 等待每次回复的超时时间(毫秒)p = sp.Popen(cmd %self.ip, stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE, shell=True)  # 执行命令lose_time = re.compile(u"丢失 = (\d+)", re.IGNORECASE)out = p.stdout.read().decode("gbk") # 获得返回结果并解码#print (out)lose_time = lose_time.findall(out) # 丢包数# 当匹配到丢失包信息失败,默认为三次请求全部丢包,丢包数lose赋值为3if len(lose_time) == 0:print "----------------LOST IP PACKET---------------------"return Falseelse:lose = int(lose_time[0])if lose > 1:return Falseelse:return True

代理ip还有一个缺点就是慢~,这也降低了爬虫的威胁,如果想高速爬取,只有两个字:充钱

3.2.3虚假访问延迟

爬虫就是因为方位速度过快或频率固定,容易被识别出,我们可以速度低于某个阀值,就可避免被Forbidden,即是403。目标服务器积极拒绝。

如果使用免费代理ip,那么这里依旧基本不需要了,因为免费代理的服务堪忧,而且加上测试筛选的时间,已经是在延迟访问了,想要设置不难,只要使用time函即可,以秒为单位。建议加载request函数之前,这样在延迟时,加上cpu处理数据的时间更加随机了。

            time.sleep(1)req = requests.get(url=url,headers=self.headers_Common, proxies=self.proxies, verify=False)

3.2.4绕开蜜罐

蜜罐就是用来吸引我们这些小虫子的,有一些信息使用浏览器是无法看到的,如果你的request请求附带了这些信息,或者你在访问浏览器看不到的信息,那么你就进入了蜜罐。

比如一些隐藏的字段,标签,或者超出浏览器分辨率的信息。

请求头headers中并不是所有信息都是有用的,相反加的过多就会无法访问你,这个需要反复的尝才行,例如我们获得当季推荐城市列表的请求头,有很多是不可以添加的

3.3存取技术

3.3.1Json文件存取

在持久化和半持久化数据方面本项目都为json存取,如爬取的ip,以及抓取的数据包,使用json有两个处,比如他拥有和字典相媲美的键值结构,而且很擅长处理中文字段。

            req = requests.post().json()data1 = json.dumps(req, ensure_ascii=False)value = json.loads(data1)

3.3.2Sheet分组Excel储存

我这里选择Excel进行储存是为了让程序更倾向办公化,不需要处理安装笨重的数据库,反锁的sql语句,以及各种键值问题。Excel备受职场的青睐,还有诸多数据透视,排序,筛选功能。

Python对Excel的支持主要为openpyxl类库,以及子类库openpyxl.workbook,在本项目先构建Workbook对象,然后咋每个区域中构建Workbook的create_sheet对象,然后将数据逐行写到create_sheet中,create_sheet即是Excel下面的标签页。

Workbook仅在程序开始时被创建,中间过程仅操作Sheet,最后保存Workbook。

def __init__(self):......self.outwb = Workbook()self.wo = self.outwb.active
def getSheet(self,name,site):careerSheet = self.outwb.create_sheet(name,site)careerSheet.append(['名称', '电话', '网址', '用时参考', '交通', '门票', '开放时间', '景点位置', '概况'])return careerSheet
def getPoi(self):... ...sheet = 0for Key,Value in self.gonglve_url.items():careerSheet = self.getSheet(self.SheetName[sheet],sheet)self.headers_Common['Referer'] = Keyfor url in Value:... ... careerSheet.append([A,B,C,D,E,F,G,H,I])sheet = sheet+1

3.3.3异常不中断爬取

单凡涉及数据请求及xpath寻找时都使用了大量try{}except{}语句,例如有的景点就没有主页的信息,有的不需要乘坐铁路,就没有铁路信息,以及我们从url列表中依次访问时,并不是所有url都能100%访问成功,或者突然间我们被Forbidden了,这几需要我们把已经取到的数据保存下来,而不是控制台报错,退出程序,抛出异常。

    def getGonglveUrl(self):for item in self.mdd_urlList:
... ...try:for div in soup.find('div',class_='row row-top5').find_all('div',class_='info'):href = div.find('div',class_='middle').find('h3').find('a')['href']list.append('http://www.mafengwo.cn'+href)self.gonglve_url[item] = listexcept:print 'error'

需要大家自行调整路径问题,如包,Model的引用,Excel储存位置等,视个人情况而异。

4.原码连接

https://github.com/GuoHongYuan/MaFengWoCrawler

马蜂窝爬虫--往期创作整理相关推荐

  1. 京东生鲜全品类爬虫--往期创作整理

    目录 目标 爬取思路 网页加载流程 数据包获取 JS逆向解析 抓包过程 关于并发和分布式 代码连接 目标 爬取京东到家的数据,京东到家没有反爬虫,只要速度不过分即可 品类:新鲜水果.海鲜水产.精选肉类 ...

  2. 利用matlab爬虫从OPGG上整理LOL英雄信息

    问题描述 OPGG是最权威的LOL数据网站,从这个网站上我们可以得到很多有关LOL的非常有用的数据,而matlab爬虫就是一个能够从网站上搜集信息的工具.这篇文章将要讲述如何利用matlab爬虫从OP ...

  3. 北京理工大学·Python网络爬虫与信息提取·知识整理

    学习目标: python爬虫部分的学习 学习内容: mooc北京理工大学·Python网络爬虫与信息提取 对Scrapy内核依然一知半解,但mooc内容已经学完整理 后续将对Scrapy继续进行学习 ...

  4. 全网最全python爬虫+数据分析资源整理

    4.29(第二天) 开篇词 你为什么需要数据分析能力? 第一模块:数据分析基础篇 (16讲) 01丨数据分析全景图及修炼指南 02丨学习数据挖掘的最佳路径是什么? 03丨Python基础语法:开始你的 ...

  5. python爬虫个人文档整理

    之前一直在做web开发,最近根据公司需要再次搞起了爬虫,虽然之前搞过,可是许多东西都忘得东东西西,敲起键盘来也是特别费劲,影响开发效率.今天周末,So特来整理一下.其实我不太喜欢写博客的,可是不写的话 ...

  6. 产品经理如何让问题迎刃而解|PMCAFF工具圈第12期分享整理

    分享主题:让问题迎刃而解-产品经理解决问题的办法 分享时间:12月10日(周四)20:00 分享方式:文字|语音 分享嘉宾:陈清国(合伙人) [关于嘉宾] 陈清国 帅游科技合伙人 10年互联网经验,6 ...

  7. 爬虫图谱(个人整理使用)

    链接: https://pan.baidu.com/s/1sk943FZ 密码: ur7r 使用simplemind软件制作 包括基础知识,进阶知识,相关库,还有工具,框架,书籍等等. 个人推荐静觅制 ...

  8. 爬虫-相关库知识整理(更新)

    requests库主要方法 import requestsrequests.request(method, url, **kwargs) """构造一个请求,支撑下面各种 ...

  9. 【爬虫教程】吐血整理,最详细的爬虫入门教程~

    初识爬虫 学习爬虫之前,我们首先得了解什么是爬虫. 来自于百度百科的解释: 网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信 ...

最新文章

  1. 根据Word表格自动生成SQL数据库脚本的VBScript代码
  2. C#教程5:操作算子(1)
  3. JavaFX 2.0 Hello World
  4. lightgbm 数据不平衡_数据不平衡问题
  5. 服务器按ctrl alt delete没有用_详细教程——用PS制作直邮广告
  6. 蒸妙集团用科学熏蒸法,弥补现代人在运动上的缺乏
  7. SRP6针对于网游登录服的应用
  8. Zabbix 5.0 配置简单WEB网页监测和触发器
  9. 如何交付机器学习项目:一份机器学习工程开发流程指南 1
  10. 6、PXE安装ESXI6.0
  11. android优化 清除无效代码 UCDetector
  12. TNF8SLNO 华为OSN1800全新4路STM-16/8路STM-4/8路STM-1业务板
  13. linux命令 复制文件,linux复制文件的命令是什么?
  14. WoS数据库使用及检索示例
  15. 论文阅读:智能机器故障诊断方法综述Applications of machine learning to machine fault diagnosis: A review and roadmap
  16. java dbutils工具类_DbUtils工具类使用
  17. 计算机电路基础第二版张虹,第1章节电路的基本概念与剖析方法——第1讲.ppt
  18. Android检测模拟器
  19. 【转载】Jupyter Lab中的plot.ly离线模式不显示图
  20. 任何物体都在以光速运动,你能理解这一认识吗?

热门文章

  1. 微信小游戏 资源服务器,Cocos Creator 微信小游戏 远程资源设置
  2. NOIWC 2019 冬眠记【游记】
  3. MacBook上如何运行那些尚未在Mac App Store 上架的 iOS/iPadOS 应用程序分享
  4. 【GBASE】南大通用GBase 8a MPP Cluster技术特点
  5. batT脚本如何自动执行 adb shell 以后的命令(android抓包)
  6. 扫雷游戏9*9(详细到具体每一步)
  7. LaTex常用包及其功能
  8. JavaSE Set HashSet LinkedHashSet TreeSet 集合练习
  9. boost库用property_tree读xml文件
  10. 女士适合学数据分析吗