记录一下自己第一次的爬虫,爬豆瓣的正则表达式写的不好,如果以后再看的时候想办法改改
猫眼电影
定义一个响应网页的函数
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
上面的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
='https://maoyan.com/board/4?offset='+str(j
)
html
=response_one_page
(url
)
return html
定义一个解析页面的函数
这个函数用正则来解析页面,提取我们想要的东西,是整个爬虫比较核心的东西
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])
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
(3)
print('*',end
=' ')
完整代码
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'
}
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
()
豆瓣电影
定义一个响应网页的函数 和上面一样 页面变化规律: 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递增定义一个获取网页的函数 和上面类似,把url=改一下
url
='https://movie.douban.com/top250?start='+str(j
)
定义一个解析页面的函数 这个正则可以算是绞尽脑汁了,别骂我菜
c
=re
.sub
(' ','',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,电影名,导演演员名单,但在导演演员名中间有  ;还有大量空格,所以我在< br >前面加了\s*它可以表示空格。在查找之前用re.sub(’  ;’,’’,html)把  ;换成没有,这样方便正则表达式的书写
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() #这里的其他内容和上面一样,如果想保存图片,复制上面的保存图片代码
最后我们写一个主函数,调用它们 这里的递增应该为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
(' ','',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
()