目标
通过Request+正则表达式爬取猫眼电影TOP100电影的排名、名字、电影封面图片、主演、上映时间、猫眼评分,将爬取的内容写入文件中。
流程框架
进入到猫眼电影TOP100的页面,此时的URL为http://maoyan.com/board/4
,点击第2页,会发现此时的URL为http://maoyan.com/board/4?offset=10
,点击第3页,会发现URL变成了http://maoyan.com/board/4?offset=20
,由此可以推断出offset参数为偏移量,如果偏移量为n,则显示电影序号就是n+1到n+10,每页显示10个,所以,如果想获取TOP100电影,只需要分开请求10次,而10次的offset参数分别设置为0、10、20......90即可,这样获取不同的页面之后,再用正则表达式提取出相关信息,就可以得到TOP100的所有电影信息了。获取信息后,可以将信息写入txt文件,当然可以存入数据库(此处为了偷懒,就不存入数据库了)。为了加快爬取网页的速度,可以开启循环和多线程(当需要爬取的信息很大时,这是一个不错的技巧)。
下图展示了具体的流程框架:
(1)抓取单页内容
# 获取单个页面的HTML代码
def get_one_page(url):
try:
# 此处如果不加headers进行伪装,将会返回403错误(拒绝访问)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"
}
response = requests.get(url, headers = headers)
# 如果返回的状态码是200,表示请求正常,返回页面HTML代码
# 否则,返回None
if response.status_code == 200:
return response.text
return None
except RequestException:
return None
接下来测试一下是否可以获取页面内容:
if __name__ == '__main__':
url = 'http://maoyan.com/board/4'
html = get_one_page(url)
print(html)
(2)正则表达式分析
可以对get_one_page(url)函数爬取的HTML代码进行分析(此处为了方便观看,直接在浏览器控制台分析),利用正则表达式获取到有用的信息(电影的排名、名字、电影封面图片、主演、上映时间、猫眼评分)。
# 解析单个页面的HTML代码,利用re模块提取出有效信息
def parse_one_page(html):
# re.S:表示“.”的作用扩展到整个字符串,包括“\n”
pattern = re.compile('<dd>.*?board-index.*?>(\d+)</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],
'actor': item[3].strip()[3:],
'time': item[4].strip()[5:],
'score': item[5]+item[6]
}
接下来测试一下是否可以得到我们想要的内容:
if __name__ == '__main__':
url = 'http://maoyan.com/board/4'
html = get_one_page(url)
items = parse_one_page(html)
for item in items:
print(item)
控制台输出如下:
单个页面信息解析正确,那么,想要获得多个页面的信息,只需写一个循环遍历即可:
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)
if __name__ == '__main__':
for i in range(10):
main(i*10)
(3)保存至文件
只需写一个简单的函数即可完成,但此处需要注意一点,为保证输出文件为中文,在读写文件时要添加参数endcoding="utf-8"
。
# 将解析出的内容写入文件
def write_to_file(content):
# 添加endcoding="utf-8"确保输出到文件中为中文
with open('result.txt', 'a', encoding='utf-8 ') as f:
# 此处建议将解析出的内容编码为json格式再写入文件,json的好处在此不过多叙述
# 如果使用了json进行编码,务必添加参数ensure_ascii=False确保编码数据为中文
# json.dumps():编码json数据
f.write(json.dumps(content, ensure_ascii=False) + '\n')
f.close()
运行代码,目标信息被写入result.txt文件中:
(4)开启循环及多线程
为了加快页面爬取速度,可以使用多线程(针对大量数据时非常有效)。
if __name__ == '__main__':
pool = Pool()
pool.map(main, [i*10 for i in range(10)])
项目完整代码已托管到github:https://github.com/panjings/python-spider