猫眼,豆瓣电影的requests和re爬虫

2 篇文章 0 订阅
2 篇文章 0 订阅

记录一下自己第一次的爬虫,爬豆瓣的正则表达式写的不好,如果以后再看的时候想办法改改

猫眼电影

  1. 定义一个响应网页的函数
def response_one_page(url):    #传入的参数是网址
	header={
		'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
	}        #提供UA,否则猫眼会无响应
	response=requests.get(url,headers=header)
	if response.status_code == 200:    #用状态码判断获取网页是否成功
		return response.text
	return None

上面的User-Agent可以在网页源码的Network下找到

Firefox,Chrome都可以找到User-Agent,然后复制粘贴
因为这次要获取的信息分了很多页面,但它们的变化是有规律的:
https://maoyan.com/board/4
https://maoyan.com/board/4?offset=10
https://maoyan.com/board/4?offset=20
给第一个页面加上?offset=0仍然是同一个页面: https://maoyan.com/board/4?offset=0
所以,我们可以找到规律,100个电影分了10个页面,每个页面的URL只有最后的offset在以10递增
2. 定义一个获取网页的函数

def get_one_page(j):   #参数为URL最后变化的数字
	url='https://maoyan.com/board/4?offset='+str(j)  #传入的参数为int型,所以要强制类型转换
	html=response_one_page(url)   #调用上面的响应函数,得到网页
	return html     #把得到的网页返回,以供后面解析网页使用
  1. 定义一个解析页面的函数

这个函数用正则来解析页面,提取我们想要的东西,是整个爬虫比较核心的东西

在这里插入图片描述

pattern=re.compile('<dd>.*?board-index.*?>(.*?)</i>.*?data-src="(.*?)".*?name.*?a.*?>(.*?)</a>.*?star.*?>(.*?)</p>.*?releasetime.*?>(.*?)</p>.*?integer.*?>(.*?)</i>.*?fraction.*?>(.*?)</i>.*?</dd>',re.S)
  • re的comile方法可以把正则字符串编译成正则表达式对象,方便复用
  • 观察网页源代码可知,每一个电影都是在dd标签里面,.*?(点,星,问号)表示任意字符,非贪婪
  • 在 i 标签里,我们可以得到排名,用括号括起来意味着我们一会儿可以提取它
  • data-src=""之间有我们需要的图片链接
  • 最后面的re.S帮我们匹配换行符
i=0
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)  #这里用的是正则解析页面
	global i    #传入参数,在下面保存图片时会用到
	for item in items:
		dict={
			'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].strip() + item[6].strip()
			}    #这里是把得到的信息存成字典
		r=requests.get(item[1])  #item[1]是每个电影图片的网页链接,通过get方法可以得到文本内容
		path="D:/images/"+str(i)+".png"  #为了存下图片并给图片命名,所以把路径提出来设置
		f=open(path,"wb")
		f.write(r.content) #requests的content方法,可以得到二进制数据,用于抓取图片,视频,音频等
		f.close()
		i+=1
		f=open("D:/moves.txt","a+")
		f.write(str(dict)+'\n')   #将所有信息写入文本文件,记住转成str型
		f.close()
  1. 最后我们写一个主函数,调用它们
def main():
	for k in range(0,100,10):
		htmls=get_one_page(k)    #传入数字,用于改变URL的offset的值
		parse_one_page(htmls)
		time.sleep(3)        #响应过快会被猫眼反爬虫,所以要等待1,2秒
		print('*',end=' ')    #每完成一个页面,输出一颗星,就是为了好看

完整代码

import requests
import re
import time    #第三方库没有的可以在 windows的命令行里用 pip install requests下载

def response_one_page(url):
	header={
		'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
	}
	response=requests.get(url,headers=header)
	if response.status_code == 200:
		return response.text
	return None

def get_one_page(j):
	url='https://maoyan.com/board/4?offset='+str(j)
	html=response_one_page(url)
	return html

i=0
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)
	global i
	for item in items:
		dict={
			'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].strip() + item[6].strip()
			}
		r=requests.get(item[1])
		path="D:/images/"+str(i)+".png"
		f=open(path,"wb")
		f.write(r.content)
		f.close()
		i+=1
		f=open("D:/moves.txt","a+")
		f.write(str(dict)+'\n')
		f.close()

def main():
	for k in range(0,100,10):
		htmls=get_one_page(k)
		parse_one_page(htmls)
		time.sleep(5)
		print('*',end=' ')
main()

豆瓣电影

  1. 定义一个响应网页的函数
    和上面一样
    页面变化规律:
    https://movie.douban.com/top250
    https://movie.douban.com/top250?start=25
    https://movie.douban.com/top250?start=50
    给第一个页面加上?start=0仍然是同一个页面:https://movie.douban.com/top250?start=0
    所以,我们可以找到规律,250个电影分了10个页面,每个页面的URL只有最后的start在以25递增
  2. 定义一个获取网页的函数
    和上面类似,把url=改一下
url='https://movie.douban.com/top250?start='+str(j)
  1. 定义一个解析页面的函数
    这个正则可以算是绞尽脑汁了,别骂我菜
    在这里插入图片描述
c=re.sub('&nbsp;','',html)
	pattern=re.compile('<div class="pic">.*?<em class="">(.*?)</em>.*?<img.*?src="(.*?)" class="">.*?div class="info.*?class="hd".*?class="title">(.*?)</span>.*?class="other">.*?</span>.*?<div class="bd">.*?<p class="">\s*(.*?)<br>.*?</p>.*?class="star.*?<span class=".*?"></span>.*?span class="rating_num".*?average">.*?</span>',re.S)

在图片里可以看见,每个电影的信息保存在了li标签里,我想提取的是排名,图片url,电影名,导演演员名单,但在导演演员名中间有&nbsp ;还有大量空格,所以我在< br >前面加了\s*它可以表示空格。在查找之前用re.sub(’&nbsp ;’,’’,html)把&nbsp ;换成没有,这样方便正则表达式的书写

def parse_page(html):
	pattern=re.compile('<div class="pic">.*?<em class="">(.*?)</em>.*?<img.*?src="(.*?)" class="">.*?div class="info.*?class="hd".*?class="title">(.*?)</span>.*?class="other">.*?</span>.*?<div class="bd">.*?<p class="">\s*(.*?)<br>.*?</p>.*?class="star.*?<span class=".*?"></span>.*?span class="rating_num".*?average">.*?</span>',re.S)
	items=re.findall(pattern,c)
	for item in items:
		dict={
			'index': item[0],
			'img': item[1],
			'title': item[2],
			'doctor': item[3]
		}
		f=open(file="D:/h.txt",mode="a+",encoding="utf-8")
		f.write(str(dict)+'\n')
		f.close()        #这里的其他内容和上面一样,如果想保存图片,复制上面的保存图片代码
  1. 最后我们写一个主函数,调用它们
    这里的递增应该为25

完整代码

import requests
import re
import time

def response_one_page(url):
	header={
	'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
	}
	respone=requests.get(url,headers=header)
	if respone.status_code==200:
		return respone.text
	return None
def get_one_page(j):
	url='https://movie.douban.com/top250?start='+str(j)
	html=response_one_page(url)
	return html
def parse_page(html):
	c=re.sub('&nbsp;','',html)
	pattern=re.compile('<div class="pic">.*?<em class="">(.*?)</em>.*?<img.*?src="(.*?)" class="">.*?div class="info.*?class="hd".*?class="title">(.*?)</span>.*?class="other">.*?</span>.*?<div class="bd">.*?<p class="">\s*(.*?)<br>.*?</p>.*?class="star.*?<span class=".*?"></span>.*?span class="rating_num".*?average">.*?</span>',re.S)
	items=re.findall(pattern,c)
	for item in items:
		dict={
			'index': item[0],
			'img': item[1],
			'title': item[2],
			'doctor': item[3]
		}
		f=open(file="D:/h.txt",mode="a+",encoding="utf-8")   #指定存入文档的编码格式
		f.write(str(dict)+'\n')
		f.close()

def main():
	for i in range(0,250,25):
		html=get_one_page(i)
		parse_page(html)
		print('*',end=' ')
		time.sleep(3)
main()
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值