豆瓣网站https://movie.douban.com的电影详细信息爬取
- python 3.9.7
- python module: random, bs4, re, urllib, json, time, requests, fake_useragent, os
- Neo4j云数据库:Neo4j Aura
-
搜索策略
一个简单的搜索策略是爬取豆瓣的前250评分电影,这里我希望探索不一样的搜索策略:对电影的推荐进行深度搜索。豆瓣对每部电影都会进行一个相关推荐,即“喜欢这部电影的人也喜欢”栏目,其中会推荐十部电影,如图。通过这个推荐,我们可以从任意一部电影出发,进行一个深度优先搜索,不断获取相关电影的信息。一个需要注意的问题是,爬取过程中,新的电影可能推荐已经搜索过的电影。我发现豆瓣对每个电影有一个唯一编号,在URL看到:https://movie.douban.com/subject/1292064/,编号为1292064,则根据编号对已搜索电影建立列表即可避免重复搜索。
![](D:\data analysis and pratice\results\report_pic1.png)
-
网页获取
起先使用 urllib 库进行网页获取,由于后续实验中出现被封IP的问题,转用 requests 库,使用 session() 对象进行爬取,同时使用 fake_useragent 库的 UserAgent() 函数随机产生UA,用
time.sleep(2*random())
产生随机延迟。# urllib库获取网页内容 def askURL(url): head = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) \ Chrome/99.0.4844.51 Safari/537.36" } req = urllib.request.Request(url, headers=head) html = "" try: response = urllib.request.urlopen(req) html = response.read().decode("utf-8") #print(html) except urllib.error.URLError as e: if hasattr(e,"code"): print(e.code) if hasattr(e,"reason"): print(e.reason) response.close() return html
if __name__ =="__main__": #*********code********* sess = requests.session() #*********code*********
# requests库获取网页内容 def askURL2(url): head = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) \ Chrome/99.0.4844.51 Safari/537.36" } fake_headers = {"User-Agent":UserAgent().random} response = sess.get(url=url, headers=fake_headers) return response.content
-
网页解析
使用 bs4 库的 BeautifulSoup 进行网页处理,用 re 库进行正则匹配,获得目标信息。如正则表达式
findLink=re.compile(r'<a href="(.*)">')
用来获取推荐电影的链接。 -
推荐关系存储
使用Neo4j图数据库线上版本Neo4j Aura对搜索路径和推荐关系进行存储。Neo4j提供了云数据库Neo4j Aura及其python支持库neo4j,对电影建立节点并对推荐建立关系可以得到图数据。这里我采集了两张图,搜索路径图(不含重复推荐,无环)和推荐关系图(含重复推荐),如下。可以发现,电影间存在很强的互推荐关系,事实上我从《楚门的世界》进行了深度为8的搜索,理论上一棵满10叉树有10^7^+个节点,而实际搜索只得到173部电影。而与之相比,从《千与千寻》开始的搜索结果甚至更少,只有91部,我认为原因很可能是动漫电影之间的互推荐关系更强,导致集合更趋近于封闭。
在main中修改mode变量为'tree'/'map'进行生成图的选择。
-
搜索路径图![tree](D:\data analysis and pratice\results\tree.svg)
-
推荐关系图![map](D:\data analysis and pratice\results\map.svg)
-
电影封面图片的爬取是在原来基础上使用正则式获得图片URL,然后进行下载即可。
# 电影封面保存
def saveCover(url,name):
head = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) \
Chrome/99.0.4844.51 Safari/537.36"
}
fake_headers = {"User-Agent":UserAgent().random}
with open(name, 'wb') as f:
f.write(sess.get(url=url, headers=fake_headers).content)
爬取电影信息存储在result.json文件中,电影图片存储在covers文件夹中。由于每次爬取会清空之前的结果,我将一份完整的结果放在results文件夹中,直接打开查看即可。