好久不见!
今天我们来爬取 去哪儿网站 的 旅游攻略 数据。
0x00 找一个合理的作案动机作为一名立志成为技术宅的普通肥宅,每次一到周末就会面临一个人生难题:这周末怎么过?
本来是没有这些问题的,该吃吃该睡睡,打打游戏敲敲代码,也挺自在。
只是后来毕业,来到一个新的城市,赚的钱除了吃住还有富余,总觉得如果不趁着周末和假期出去好好逛逛这个城市,就等于白来一趟,那就太亏了。
话虽如此,旅游岂是说走就走的。好几次我下定决心出门,结果在小区门口的十字路口,看着车来车往陷入沉思:我特么去哪儿玩啊!思索半天,最后去超市买了一提肥宅快乐水,回家躺床上打开了王者荣耀。。。
哎!
都怪没有一份完整的旅游攻略,导致我想出去玩都不知道去哪儿玩!
为了防止我以后再找这种自欺欺人的借口,我决定爬取 去哪儿 2021最新游记有什么好玩的地方-适合年轻人的旅游攻略-去哪儿攻略 网站的旅游攻略库。
0x01 分析目标网站分析流程主要有以下几步:
1. 打开网站,看看网页上展示一些什么数据。
2. 通过 F12 开发者工具,找到数据的获取接口(数据是 html 还是 json,翻页是 url 控制还是 ajax)
3. 编写简单的代码,发起网络请求,试探对方网站的反爬机制。
4. 完成以上三步之后,就可以完善代码,正式爬取数据了。
1. 我们可以获取哪些数据
如图,通过观察,我们可以发现网站上展示了以下数据:
文章标题:走入松江,不一样的上海郊野风情作者昵称:麻小薯出发日期:2020-06-06 出发游玩天数:共21天照片数量:126张照片人均消费:人均1000元同行人数:三五好友旅游类型:深度游 环游 短途周末(由于篇幅原因网页中隐藏显示此项,但是在开发者工具中可以看到)旅游途经:途经:上海旅游行程:行程:外白渡桥>武康路>外滩>思南路>豫园阅读量:246点赞数:0评论数:0而且,多翻阅不同的文章,可以发现
【文章标题】【作者昵称】【出发日期】【游玩天数】【阅读量】【点赞数】【评论数】【途经】【行程】这些数据项是每一篇游记文章中共有的数据。
【照片数量】【人均消费】【同行人数】【旅游类型】这四项,会根据作者的设置,显示全部,显示部分,或者全部隐藏。
2. 抓取数据的接口
一般情况下,网站的数据加载方式有两种,一种是直接存放在静态的HTML网页中,另一种是通过 Ajax 动态的加载到网页中。
那怎么判断我们要爬取的网站,到底采用的是哪一种数据加载方式呢?这里教大家几个小办法。
① 通过翻页
如果翻页的时候,网址中出现类似于 “p=2” "p=3" 或者 "page=2" "page=3" 的字样,并且后面的数字在翻页的时候跟着页码在变化,那么,这个网站大概率就是静态的 HTML 网页。如果在翻页的时候,网页中的数据变化了,但是地址栏中的 URL 没有出现与页码相关的参数,甚至全程没有变化,那么这个网站数据大概率是通过 Ajax 动态加载的。有的网站没有翻页按钮,也不知道是第几页,当滑动条滚动到底部时会自动加载后面的数据。这种毫无疑问是 Ajax 动态加载的。② 开发者工具抓包
通过上面 翻页 的方式大致确定了数据加载方式之后,我们可以在浏览器中按 F12,调用 开发者工具 进行抓包,验证我们的想法,并找到数据的接口。
Ⅰ. 打开开发者工具,切换到 Network 项,然后在网页中进行翻页操作(这一步主要是是网站出现 “加载新数据” 这一过程,方便我们抓包分析)。
Ⅱ. 开发者工具会为我们抓取整个过程中网站与服务器通信的所有数据包。如截图所示,这些数据包类型有 XHR,JS,CSS,Img 等等,这里我们主要关注 XHR 和 Doc 这两类(一般情况下,XHR 中的数据是 json 格式的,Doc 中的数据是 Html 格式的)。
如果在翻页过程中,XHR 中抓取到了新的请求,而且 json 中含有新加载的数据,那么这个网页就是动态加载数据的,且这个请求就是获取数据的接口。如果在翻页的过程中,XHR 中没有捕获到数据,而在 Doc 中有,那么这个网页就是静态加载在html中的,这个请求就是获取数据的接口。通过测试,我们在 Doc 中找到了 去哪儿网 旅游攻略数据的接口。
3. 试探网站的反爬机制
找到网站的数据接口之后,我们还不能大意,需要简单地编写代码,调用这个接口,来试探网站的反爬机制。只有绕过了反爬机制,用代码获取到了数据,才算是成功了。
这是我们上一步找到的接口,在 Headers 选项卡中可以看到这个接口的基本参数,我们主要关注以下几个:
Request Url : 请求的 URLRequest Method :请求方式Request Headers :请求头(通常包含 user-agent 和 accept 即可,有些网站可能需要 cookie)Query String Parameters :请求参数然后我们在 python 中,用代码构造这些参数,访问这个接口,看是否可以获取数据
import requests# Request Urlurl = "https://travel.qunar.com/travelbook/list.htm?page=2&order=hot_heat"# Request Headersheaders = {'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9','user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36',}# Query String Parametersparams = {'page': 2,'order': 'hot_heat',} # 发起网络请求,请求方式是 getr = requests.get(url, data=params, headers=headers)r.encoding = r.apparent_encodingprint(r.text)执行代码,很幸运,这个网站没有太多的反爬机制,直接就获取到了数据。
0x02 编写代码上述的操作一步步做下来,我们基本上已经攻克了整个爬虫中最困难的一步了。接下来,只需要对爬取到的内容进行解析,提取出我们需要的数据即可。
由于爬到的数据是 HTML 格式,我们选用 BeautifulSoup 库进行解析。
bsObj = BeautifulSoup(html,"html.parser")我们对照网页源码来简单分析(有条件的可以去 旅游攻略库 网站,打开开发者工具对照着分析)。
攻略列表存放在一个 class="b_strategy_list" 的 ul 标签下,每一个 li 标签对应一篇旅游攻略。 bookList = bsObj.find("ul",attrs = {"class":"b_strategy_list"})li_List = bookList.find_all("li") 文章