1. 环境以及工具使用
我们使用的是python3
的requests
库,requests
比urllib
更加的方便,同时使用正则表达式作为解析的工具。
在工具方便这次我们使用一个新的抓包工具用来对http
协议的包进行分析
1.1 工具介绍
Fiddler
的官方网址:http://www.fiddler2.com/
Fiddler
是最强大最好用的Web
调试工具之一,它能记录所有客户端和服务器的http
和https
请求,允许你监视,设置断点,甚至修改输入输出数据,Fiddler
包含了一个强大的基于事件脚本的子系统,并且能使用.net
语言进行扩展 你对HTTP
协议越了解, 你就能越掌握Fiddler
的使用方法。你越使用Fiddler
,就越能帮助你了解HTTP
协议。
为什么使用Filddler
主要是使用特别方便,它还可以对手机进行抓包,自动监视所有的http
协议。 给个简单的学习手册供大家学习:
https://kb.cnblogs.com/page/130367/#introduce
2. 实战
首先设置打开Fiddler
,然后浏览器输入http://maoyan.com/board/4?offset=0
,然后点击第一条request
我们可以看到右边的上侧是request
,下面是response
。
我们首先爬取第一页:
import requests
def get_one_page(url):
headers={
'User-Agent':'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134'
}
response=requests.get(url,headers=headers)
if response.status_code==200:
return response.text
return None
def main():
url='http://maoyan.com/board/4'
html=get_one_page(url)
print(html)
main()
运行成功得到第一页的数据,接下来我们需要进行一个解析,使用正则表达式分别获取电影排名、电影名称、主演、电影图片。 我们发现
<dd><i class="board-index board-index-1">1</i>
电影排名在这个dd
标签,i
标签的里面1
就是排名,接下来我们构造正则表达式:
<dd>.*?board-index.*?>(.*?)</i>
.?
就是非贪婪模式的匹配,.
代表的是匹配任意字符,代表的是匹配前面字符无限次,让我联想到编译原理课的*
闭包,就是乘以很多次。()
就是我们要选择提取的字符。接下来我们需要解析影片的图片,
<a href="/films/1203" title="霸王别姬" class="image-link" data-act="boarditem-click" data-val="{movieId:1203}">
<img src="//ms0.meituan.net/mywww/image/loading_2.e3d934bf.png" alt="" class="poster-default" />
<img data-src="http://p1.meituan.net/movie/20803f59291c47e1e116c11963ce019e68711.jpg@160w_220h_1e_1c" alt="霸王别姬" class="board-img" />
图片是第二个img
标签里面的东西,正则表达式改写成为:<dd>.*?board-index.*?></i>.*?data-src="(.*?)"
接下来提取名称,
<dd>
<i class="board-index board-index-1">1</i>
<a href="/films/1203" title="霸王别姬" class="image-link" data-act="boarditem-click" data-val="{movieId:1203}">
<img src="//ms0.meituan.net/mywww/image/loading_2.e3d934bf.png" alt="" class="poster-default" />
<img data-src="http://p1.meituan.net/movie/20803f59291c47e1e116c11963ce019e68711.jpg@160w_220h_1e_1c" alt="霸王别姬" class="board-img" />
</a>
<div class="board-item-main">
<div class="board-item-content">
<div class="movie-item-info">
<p class="name"><a href="/films/1203" title="霸王别姬" data-act="boarditem-click" data-val="{movieId:1203}">霸王别姬</a></p>
<p class="star">主演:张国荣,张丰毅,巩俐</p>
<p class="releasetime">上映时间:1993-01-01(中国香港)</p>
</div>
<div class="movie-item-number score-num">
<p class="score"><i class="integer">9.</i><i class="fraction">6</i></p>
</div>
电影名称在p
节点,class
为name
,所以用name
做标志位,提取a
节点里面的正文内容,同时提取主演、发布时间、评分等内容,改写正则表达式
<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>.*?integer.*?>(.*?)</i>.*?fraction.*?(.*?)</i>.*?</dd>
最后调用findall()
提取所有的内容。
完整代码如下:
import json
import requests
import re
import time
def get_one_page(url):
headers={
'User-Agent':'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134'
}
response=requests.get(url,headers=headers)
if response.status_code==200:
return response.text
return None
def parse_one_page(html):
pattern=re.compile('<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>.*?integer.*?>(.*?)</i>.*?fraction.*?(.*?)</i>.*?</dd>',re.S)
items=re.findall(pattern,html)
for item in items:
yield{
'index':item[0],
'image':item[1],
'title':item[2].strip(),
'actor':item[3].strip()[3:] if len(item[3])>3 else '',
'time':item[4].strip()[5:] if len(item[4])>5 else '',
'score':item[5]+item[6]
}
def write_to_file(content):
with open('result.txt','a',encoding='utf-8') as f:
f.write(json.dumps(content,ensure_ascii=False)+'\n')
def main(offset):
url='http://maoyan.com/board/4?offset='+str(offset)
html=get_one_page(url)
for item in parse_one_page(html):
print(item)
write_to_file(item)
if __name__=='__main__':
for i in range(10):
main(offset=i*10)
time.sleep(1)