之前爬取过基于html跳转的豆瓣TOP250网页,还有基于ajax跳转的美团评论网页,这次将介绍如何爬取基于html和ajax两种跳转方式且含有反爬虫程序和异常值的电影信息网页
电影信息网页链接:
http://movie.mtime.com/boxoffice/#CN/2019
爬取电影信息
1.分析网页
(1)爬取目标
(2)分析2018年的电影信息
可以看出网页左边,电影年度可以分为2018,2019,2020年三个部分,我们先针对2018年时的网页进行分析并爬取
- 分析点击2018年时,第一页的网页链接:
切换到2018年时第二页的网页为:
分析结果:
据以上结果可看出,当点击选择到2018年的电影信息,并进行切换时,链接都为
http://movie.mtime.com/boxoffice/#CN/2018
切换网页时链接没有发生改变,说明在2018年的电影信息这个部分,网页是基于ajax
跳转的,可利用抓包技术对网页进行爬取
(3)分析点击2018年时10个页面的json文件
- 寻找
json
文件方法:
- 找到页面
json
文件后复制链接的方法:
2018年时第一个页面的json
文件链接为:
http://movie.mtime.com/boxoffice/?year=2018&area=china&type=MovieRankingYear&category=all&page=0&display=list×tamp=1586871242566&version=07bb781100018dd58eafc3b35d42686804c6df8d&dataType=json
2018年时第二个页面的json
文件链接为:
http://movie.mtime.com/boxoffice/?year=2018&area=china&type=MovieRankingYear&category=all&page=1&display=list×tamp=1586871698868&version=07bb781100018dd58eafc3b35d42686804c6df8d&dataType=json
2018年时第十个页面的json
文件链接为:
http://movie.mtime.com/boxoffice/?year=2018&area=china&type=MovieRankingYear&category=all&page=9&display=list×tamp=1586871775520&version=07bb781100018dd58eafc3b35d42686804c6df8d&dataType=json
-
对以上三个链接进行分析可得出,有以下两个个地方不一样:
第一个不同的地方:
因为我们找的是第一页,第二页和第十页的链接,所以此处的0,1,9表示的是第一页,第二页和第十页第二个不同的地方:
此处的timestamp
是时间戳
(4)请求并筛取信息
- 导入接下来要用的库
# 导入需要的库
import csv,requests,time
from lxml import etree
- 设置浏览器代理,构造字典,向服务器请求
json
文件
# 导入需要的库
import csv,requests,time
from lxml import etree
# 设置浏览器代理,构造字典
headers={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36'
}
#此处的url暂时放入的是page=0时,2018年的电影信息第一页
url="http://movie.mtime.com/boxoffice/?year=2018&area=china&type=MovieRankingYear&category=all&page=0&display=list×tamp=1587124108705&version=07bb781100018dd58eafc3b35d42686804c6df8d&dataType=json"
requests.get(url=url,headers=headers).text
因为遇到了反爬虫程序,所以请求的json
文件内容为乱码,运行结果为:
将.text
去掉,再次运行:
# 导入需要的库
import csv,requests,time
from lxml import etree
# 设置浏览器代理,构造字典
#同时构造多个字典时,字典之间要用逗号隔开(不是在最后一个字典结尾加)
headers={
"Cookie":"userId=0; defaultCity=%25E5%258C%2597%25E4%25BA%25AC%257C290; _tt_=D9331474480AD125C85AB3E287E95970; __utmz=221034756.1586868641.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); _userCode_=20204162141329; _userIdentity_=20204162141328735; _movies_=240425; _ydclearance=04675d66f1c55a48a22c96aa-331d-4098-8bbe-985e4209326e-1587128407; Hm_lvt_6dd1e3b818c756974fb222f0eae5512e=1586868641,1586911472,1587042989,1587121484; __utmc=221034756; __utma=221034756.607018261.1586868641.1587121484.1587123654.6; __utmt=1; __utmt_~1=1; Hm_lpvt_6dd1e3b818c756974fb222f0eae5512e=1587123708; __utmb=221034756.4.10.1587123654",
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36'
}
#此处的url暂时放入的是page=0时,2018年的电影信息第一页
url="http://movie.mtime.com/boxoffice/?year=2018&area=china&type=MovieRankingYear&category=all&page=0&display=list×tamp=1587124108705&version=07bb781100018dd58eafc3b35d42686804c6df8d&dataType=json"
response=requests.get(url=url,headers=headers) #向服务器请求内容,返回200代表成功不加.text时
#给返回的json文件内容赋值
response
运行结果为:
- 利用
cookie
解决请求json
源代码时返回乱码的问题
什么是cookie
?
相当于一个能够成功访问网页内容的钥匙,有了这个钥匙,在面对反爬虫程序时,我们就能成功破解反爬虫程序,使得请求源代码时成功返回内容,而不再返回乱码
怎么找cookie
值?
将cookie
值构造为字典:
# 导入需要的库
import csv,requests,time
from lxml import etree
# 设置浏览器代理,构造字典
#同时构造多个字典时,字典之间要用逗号隔开(不是在最后一个字典结尾加)
headers={
"Cookie":"userId=0; defaultCity=%25E5%258C%2597%25E4%25BA%25AC%257C290; _tt_=D9331474480AD125C85AB3E287E95970; __utmz=221034756.1586868641.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); _userCode_=20204162141329; _userIdentity_=20204162141328735; _movies_=240425; _ydclearance=04675d66f1c55a48a22c96aa-331d-4098-8bbe-985e4209326e-1587128407; Hm_lvt_6dd1e3b818c756974fb222f0eae5512e=1586868641,1586911472,1587042989,1587121484; __utmc=221034756; __utma=221034756.607018261.1586868641.1587121484.1587123654.6; __utmt=1; __utmt_~1=1; Hm_lpvt_6dd1e3b818c756974fb222f0eae5512e=1587123708; __utmb=221034756.4.10.1587123654",
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36'
}
#此处的url暂时放入的是page=0时,2018年的电影信息第一页
url="http://movie.mtime.com/boxoffice/?year=2018&area=china&type=MovieRankingYear&category=all&page=0&display=list×tamp=1586871775520&version=07bb781100018dd58eafc3b35d42686804c6df8d&dataType=json"
requests.get(url=url,headers=headers).text #向服务器请求内容,返回200代表成功
运行结果为:
从结果可以看出,使用了cookie
以后,向网页请求源代码时,成功返回了内容,不再是乱码
在要返回值的后面加.text
可以直接看到返回的内容,若不加,就会返回下面的结果,返回200
表示请求成功,加或者不加.text
都可以,可根据自己的需求来定
-
另外还要注意一点,
cookie
值会根据时间变化,如头一天运行代码时所用的cookie
值第二天来再次运行就会出现网页返回json
文件内容仍然是乱码的情况,此时重新复制网页上的cookie
值即可
前后间隔一天的两个cookie
值对比后发现,很多地方都发生了变化,说明cookie
值这把钥匙具有时效性 -
从成功返回的
json
文件源代码中提取html
文件
将成功返回的json
文件源代码放到json
在线解析中进行解析:
解析出的结果和在jupyter
上成功返回的内容一样,如下:
可以看到其中有我们需要的html
的内容,将它从json
文件中提取出来:
提取语句为:response.json()["html"]
提取后运行结果为:
与上一张运行结果相比,这张的运行结果缩小到了html
中的内容,即从返回的json
文件源代码中成功提取html
文件 -
对从返回的
json
文件源代码中成功提取html
文件网页信息进行解析,筛取
from lxml import etree
html_etree=etree.HTML(response.json()["html"])
运行后无结果,也无错误,说明筛取信息成功
2.提取信息
(1)提取电影名及电影排名
提取信息关键语句:
html_etree.xpath('')
括号内为自己根据网页中要提取的内容的html
语句而构造的查找提取信息的路径
- 怎么构造上述语句中的路径?(以提取2018年度第一页上的第一个电影“红海行动”为例)
按上述操作复制得到的xpath
链接为:
/html/body/div[3]/div[2]/div[1]/div[2]/div/dd[1]/div/div[2]/h3/a
这个链接是我们要提取的"红海行动"在整个html
中的定位,而我们可以用另一种基于html
标签的定位方式,来查找到这个信息的所在位置并提取,但这种基于html
标签的定位方式需要我们自己根据网页中的html
标签来构造路径
例如在爬取另外一个网页时,我们曾用过这样一个语句:
其中,//*
表示在所有内容中查找,[@id="content"]
表示在所有内容中要查找的目标信息,后缀的一系列链接为当时爬取网页的所有链接的共同部分
基于以上例子,我们构造出提取"红海行动"时的路径为:
//div[@class="boxofficelist"]/div/dd[1]/div/div[2]/h3/a
各部分的标签含义、路径与标签间的对应关系如下:
其中,第一个div
标签表示从div
标签中查找class="boxofficelist"
的部分以及路径后面的标签,层层推进,最终找到我们所要的目标信息,dd[1]
表示"红海行动"所在的位置是第一个,即"红海行动"是该页面的第一个电影名,可以通过改动dd[1]
中的数字来获取该页面的其他电影名,代码及运行结果如下:
from lxml import etree
html_etree=etree.HTML(