要求:
获取豆瓣top250的电影信息,包括:
排名
名字
国家
年份
导演
评分
评分人数
类型
宣传语
将这些电影信息保存在一个名为movie.txt的文件里
思路:
1.用requests获取源代码
2.用re获取信息
3.将获得的数据存储在movie.txt中
示例浏览器:chrome
1.先导入库,定义url(requests要提前安装,指令pip install requests,没有pip的百度如何下载)?
import requests
import re
import os
import time
# os和time模块到时候会用到
url = "https://movie.douban.com/top250"
2.打开浏览器,进入豆瓣页面(movie.douban.com/top250),按下f12,会出现以下界面:
?然后,找到网络(Network),单击打开:
?
随便点击一个项目(没有就刷新),在“标头”处找到user-agent,保存下来,下一步要用到:
?
?3.因为豆瓣有反爬机制,所以我们要手动指定headers:代码也很简单,只要把上面的user-agent复制来就可以了(不同系统的headers不一样,需要自行查看)
headers = {
"user-agent":
"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36"
}
接着,我们要去查看网页的请求方法,请求方法分为get和post,在我们看user-agent的上面就有了
可以看到豆瓣是get请求方法,行了,接下来我们来获取网页源代码requests.get(url地址,你的headers),因为get方法的返回值不是文本,所以我们用text方法+一个变量来保存源代码文本
resp = requests.get(url, headers=headers)
page_content = resp.text # page_content 保存源代码
?
3.以上方法做完以后,re最难的正则表达式就来了,不过我会尽量讲明白滴~
回到浏览器,刷新网页,上拉会看到一个叫"top250"的项,打开
?打开后点击"响应",切换到网页源代码,按ctrl+shift+f打开搜索框
?
?然后,我们要了解一下这次会遇到的正则符号
(一)
.*? 这个标识符不会的就理解成从标识符前面的内容跳到标识符后面的内容
举个栗子:
"兄弟有时间打游戏吗?兄弟在吗,打游戏呗,今晚上号?喂喂喂,你在不在啊,打游戏上头了?"
在这里,如果你的正则表达式是: 兄弟.*?游戏 的话
那匹配的就是:
兄弟有时间打游戏
而不是别的,就连后面的 吗? 都不匹配
能明白了吧?
(二)
?P 这个标识符很好理解,你们就把他看成一个数据类型就可以了,格式是(?P<名字>内容)
就以上面的例子来说,如果想获取标识符.*?中的内容,也就是"有时间打"这个字符串,那我们可以这么写:
兄弟(?P<string>.*?)游戏
这样我们的<string>中就成功存入了中间的部分~
至于怎么输出后面再讲
?了解完后,我们来获取电影的信息,在搜索框搜索一部电影的名字(这里我以第一名的为例):
?
然后,我们发现,这部电影所有的数据都在这里了,用之前的那两个标识符,我们就能把这些正则写出来了
这是我写的,仅供参考.我为了装逼?让思路更清楚多写了亿点点没必要的
obj = re.compile('<li>.*?<div class="item">.*?<span class="title">(?P<name>.*?)</span>.*?'
'<div class="bd">.*?<p class="">(?P<dy>.*?) .*?<br>(P<year>.*?) '
'.*?/ (?P<country>.*?) .*? (?P<lx>.*?)</p>'
'.*?<span class="rating_num" property="v:average">(?P<score>.*?)</span>'
'.*?<span>(?P<people>.*?)</span>'
'.*?</div>.*?<span class="inq">(?P<xcy>.*?)</span>', re.S)
用obj中的finditer方法来获取结果,同样变量保存
result = obj.finditer(page_content)
写入文件,要访问obj中的name dy等变量,用.group("变量名")方法
这边我在开头定义了一个s=0用来统计排名
with open("movie.txt", mode="a", encoding="utf-8") as f:
for it in result:
s+=1
f.write("排名:"+str(s)+"\n")
f.write("电影名:"+it.group("name").strip()+"\n")
f.write("国家:"+it.group("country").strip()+"\n")
f.write("年份:"+it.group("year").strip()+"\n")
f.write(it.group("dy").strip()+"\n")
f.write("评分:"+it.group("score").strip()+"\n")
f.write("评分人数:"+it.group("people").strip()+"\n")
f.write("类型:"+it.group("lx").strip()+"\n")
f.write("宣传语:"+it.group("xcy").strip()+"\n")
f.write("----------------------------------\n")
f.write("\n")
print("已成功爬取", s, "项电影信息")
不要忘记把resp关掉,不然会被封ip
resp.close()
但是这样我们会发现一个问题,在movie.txt中只有一页的内容,此时不要以为自己代码有问题,网页切到下一页看地址栏:
?
看到了吧?每翻一页其中的start值就会增加25,所以我们改写一下开头,记得把后面的代码进行缩进
for i in range(10):
a = i * 25
url = "https://movie.douban.com/top250?start="+str(a)+"&filter="
?
这样就没问题了!
接着,我们只需要把代码稍微润色一下就可以了
由于我们写入的时候是用的"a"追加模式,如果多次写入就会信息爆炸,所以我们的os模块就起作用了,用os.path.exists方法判断文件是否存在,有就删除
if not os.path.exists("./movie.txt"):
pass
else:
os.remove("./movie.txt")
因为我习惯用终端运行程序,所以我加上了os.system("cls"),linux请用clear,然后,为了让程序不一开始就跑起来,我在开头加了几句
os.system("cls")
print("在3秒后开始爬取豆瓣top250电影信息...")
time.sleep(1)
print("3...")
time.sleep(1)
print("2...")
time.sleep(1)
print("1...")
time.sleep(1)
至此,程序就写完辣!完整代码:
import requests
import re
import os
import time
s = 0
os.system("@echo off")
# 删除文件避免重复文本
if not os.path.exists("./movie.txt"):
pass
else:
os.remove("./movie.txt")
os.system("cls")
print("在3秒后开始爬取豆瓣top250电影信息...")
time.sleep(1)
print("3...")
time.sleep(1)
print("2...")
time.sleep(1)
print("1...")
time.sleep(1)
for i in range(10):
a = i * 25
url = "https://movie.douban.com/top250?start="+str(a)+"&filter="
headers = {
"user-agent":
"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36"
}
resp = requests.get(url, headers=headers)
page_content = resp.text # page_content 保存源代码
obj = re.compile('<li>.*?<div class="item">.*?<span class="title">(?P<name>.*?</span>.*?'
'<div class="bd">.*?<p class="">(?P<dy>.*?) .*?<br>(?P<year>.*?) '
'.*?/ (?P<country>.*?) .*? (?P<lx>.*?)</p>'
'.*?<span class="rating_num" property="v:average">(?P<score>.*?)</span>'
'.*?<span>(?P<people>.*?)</span>'
'.*?</div>.*?<span class="inq">(?P<xcy>.*?)</span>', re.S)
result = obj.finditer(page_content)
with open("movie.txt", mode="a", encoding="utf-8") as f:
for it in result:
s+=1
f.write("排名:"+str(s)+"\n")
f.write("电影名:"+it.group("name").strip()+"\n")
f.write("国家:"+it.group("country").strip()+"\n")
f.write("年份:"+it.group("year").strip()+"\n")
f.write(it.group("dy").strip()+"\n")
f.write("评分:"+it.group("score").strip()+"\n")
f.write("评分人数:"+it.group("people").strip()+"\n")
f.write("类型:"+it.group("lx").strip()+"\n")
f.write("宣传语:"+it.group("xcy").strip()+"\n")
f.write("----------------------------------\n")
f.write("\n")
print("已成功爬取", s, "项电影信息")
resp.close()
os.system("cls")
print("爬取完毕,请在本目录下的movie.txt查看")
新人博主,欢迎捧场ヾ(゚?゚ゞ)
|