shell实现抓取豆瓣高评分电影列表

sh/bash/dash/ksh/zsh等Shell脚本
回复
头像
needle
帖子: 78
注册时间: 2009-12-01 13:34

shell实现抓取豆瓣高评分电影列表

#1

帖子 needle » 2013-10-05 5:04

看电影久了,总想把豆瓣高评分电影给抓出来,
网上似乎有python的实现,看不懂~,
大致看了一下,然后参考了
viewtopic.php?f=21&t=448997
的想法。
于是用shell写了一个。

代码: 全选

#!/bin/bash -
#抓取豆瓣电影列表(如科幻, 按评分排序)
#如要修改, 改url应该就可以了.
#
#by needle wang
#
#version2: 增加搜索列表及时间信息
#以及完善减少修改量, 即智能化~
#2013/10/06 周日 05:50
#
#version1: 完成电影列表及top250
#2013/10/05 周六 03:36
#

#choose situation 1(电影列表) or 2(top250)
#若给出搜索关键字, flag标志将自动失效, 且只抓取一页
flag=1

#总共要抓取多少页
pageSum=1

if [ "${flag}" -eq "1" ]
then
	#situation1
	#喜剧列表,按评分排序
	#url_prefix='http://movie.douban.com/tag/%E5%96%9C%E5%89%A7?type=S&start='
	#科幻列表,按评分排序
	url_prefix='http://movie.douban.com/tag/%E7%A7%91%E5%B9%BB?type=S&start='
elif [ "${flag}" -eq "2" ]
then
	#situation2
	#豆瓣电影top250
	url_prefix='http://movie.douban.com/top250?filter=&format=&start='
fi


#situation3
#搜索电影, 根据是否给定搜索词自动判断
if [ "${1}" ]
then
	url_prefix='http://movie.douban.com/subject_search?cat=1002&search_text='
	#显示一页就够了
	pageSum=1
fi

#每页有多少条目: 搜索是15条, 列表是20条, top250是25条
if [ "${1}" ]
then
	onePageNum=15
elif [ "${flag}" -eq "1" ]
then
	onePageNum=20
elif [ "${flag}" -eq "2" ]
then
	onePageNum=25
else
	onePageNum=''
fi

#当前第几页,拼在url_prefix后面
pageIndex=0

#输出电影列表
printListOnePage(){	                  
#电影列表的匹配关键字
echo "$1" | tr '\n' ' ' | grep -oP '(?<=<div class="pl2">).*?(?=</div>)' | \
	while read i
	do
		name=$(echo "$i" | grep -oP '(?<=>).*(?=</a>)' | sed 's;<span.*">;;g;s;</span>;;g;s; ;;g' )
		score=$(echo "$i" | grep -oP '(?<="rating_nums">).*?(?=</span>)' )
		year=$(echo "$i" | egrep -o '[0-9]{4}(-[0-9]{2}){2}' | head -1 )
		test "${year}" && year="${year} "
		people=$(echo "$i" | grep -oP '(?<=<span class="pl">)(.*)(?=</span)' )
		echo "${score:=none}${people} ${year}${name}"
	done
}

#输出top250列表
printTop250OnePage(){
#top250的匹配关键字与电影列表不一样
#html格式也不一样,要改成一行
echo "$1" | tr '\n' ' ' | grep -oP '(?<=<div class="info">).*?inq.*?(?=</div>)' | \
	while read i
	do
		name=$(echo "$i" | grep -oP '<a.*a>' | sed 's/<[^>]*>//g;s/^ *//g;s/&nbsp;/ /g' | tr -s ' ' )
		score=$(echo "$i" | grep -oP '(?<=<em>).*?(?=</em>)' )
		year=$(echo "$i" | egrep -o '[0-9]{4}&nbsp;/' | head -1 )
		people=$(echo "$i" | grep -oP '(?<=<span>).*?(?=</span>)' )
		echo "${score:=none}(${people}) ${year/&nbsp;\// }${name}"
	done
}

#输出搜索结果列表
printSearchOnePage(){
#匹配关键字与电影列表的相似, 但是:
#1.改成文本源转换成一行, 2.name的正则要改成top250的;
echo "$1" | tr '\n' ' ' | grep -oP '(?<=<div class="pl2">).*?(?=</div>)' | \
	while read i
	do
		name=$(echo "$i" | grep -oP '<a.*a>' | sed 's/<[^>]*>//g;s/^ *//g;s/&nbsp;/ /g' | tr -s ' ' )
		score=$(echo "$i" | grep -oP '(?<="rating_nums">).*?(?=</span>)' )
		year=$(echo "$i" | egrep -o '[0-9]{4}(-[0-9]{2}){2}' | head -1 )
		test "${year}" && year="${year} "
		people=$(echo "$i" | grep -oP '(?<=<span class="pl">)(.*)(?=</span)' )
		echo "${score:=none}${people} ${year}${name}"
	done
}

trap "echo '中断';exit 1" INT
for ((count=0;count<${pageSum};count++))
do
	if [ "${1}" ]
	then
		#拼接 要搜索的 电影关键词
		url="${url_prefix}${1}"
	else
		url="${url_prefix}${pageIndex}"
	fi
	echo "--------- url is ${url} ---------"

	oneContent=$(wget -q "${url}" -O - )

	if [ "${1}" ]
	then
		printSearchOnePage "${oneContent}"
	else
		if [ "${flag}" -eq "1" ]
		then
			printListOnePage "${oneContent}"
		elif [ "${flag}" -eq "2" ]
		then
			printTop250OnePage "${oneContent}"
		else
			echo "setting is not clear~~~"
			exit 1
		fi
	fi

	pageIndex=$((${pageIndex}+${onePageNum}))
done

代码量也不是很多啊。
多亏了豆瓣的页面很规范,不然不一定搞得定~
附件
豆瓣top250.jpg
上次由 needle 在 2013-12-11 22:29,总共编辑 3 次。
myshell^_^
xfce4.10最好用了……
舒适的滚轮升起焦点设计,大量快捷键,alt移动,糟糕的桌面图标……
珍爱生命,LFS 三思~
头像
icelee123
帖子: 811
注册时间: 2011-07-16 19:48
系统: Arch

Re: shell实现抓取豆瓣高评分电影列表

#2

帖子 icelee123 » 2013-10-05 17:30

感觉抓什么东西用php最方便了 :em06
其实我是菜鸟、、、
头像
qagkiss
帖子: 15
注册时间: 2012-10-09 22:17
系统: ubuntu

Re: shell实现抓取豆瓣高评分电影列表

#3

帖子 qagkiss » 2013-11-28 14:25

为什么我运行了 效果如下 是不是页面改了 我是用gedit 复制你的代码的


14:23:16tcstory ~/桌面 $ ./2.sh
--------- url is http://movie.douban.com/tag/%E7%A7%91%E ... =S&start=0 ---------
9.6(173人评价)
9.4(169人评价)
9.4(1110人评价) 2011-03-17
9.3(217人评价) 2005-11-18
9.3(659人评价) 1998-03-07
9.3(2586人评价) 2010-01-01
9.3(19309人评价) 1997-07-19
9.3(310364人评价) 2008-06-27
9.2(477442人评价) 2010-09-01
none(尚未上映)
9.2(14490人评价) 1997-03-15
9.2(1438人评价) 2006-01-27
8.9(249人评价)
9.2(2356人评价) 2009-12-25
9.1(1166人评价) 2007-11-16
9.1(2739人评价) 2003-06-01
9.1(1597人评价) 2013-04-20
9.0(2847人评价) 2003-06-03
7.8(49644人评价) 2013-10-31
none(尚未上映) 2016-03-11
14:23:21tcstory ~/桌面 $
头像
qagkiss
帖子: 15
注册时间: 2012-10-09 22:17
系统: ubuntu

Re: shell实现抓取豆瓣高评分电影列表

#4

帖子 qagkiss » 2013-11-28 14:27

为什么我运行了 效果如下 是不是页面改了 我是用gedit 复制你的代码的


14:23:16tcstory ~/桌面 $ ./2.sh
--------- url is http://movie.douban.com/tag/%E7%A7%91%E ... =S&start=0 ---------
9.6(173人评价)
9.4(169人评价)
9.4(1110人评价) 2011-03-17
9.3(217人评价) 2005-11-18
9.3(659人评价) 1998-03-07
9.3(2586人评价) 2010-01-01
9.3(19309人评价) 1997-07-19
9.3(310364人评价) 2008-06-27
9.2(477442人评价) 2010-09-01
none(尚未上映)
9.2(14490人评价) 1997-03-15
9.2(1438人评价) 2006-01-27
8.9(249人评价)
9.2(2356人评价) 2009-12-25
9.1(1166人评价) 2007-11-16
9.1(2739人评价) 2003-06-01
9.1(1597人评价) 2013-04-20
9.0(2847人评价) 2003-06-03
7.8(49644人评价) 2013-10-31
none(尚未上映) 2016-03-11
14:23:21tcstory ~/桌面 $
sarrow
帖子: 403
注册时间: 2007-10-27 1:04

Re: shell实现抓取豆瓣高评分电影列表

#5

帖子 sarrow » 2013-11-29 9:42

修改下句后:
name=$(echo "$i" | grep -oP '(?<=<span style="font-size:12px;">).*?(?=</span>)' )
# name=$(echo "$i" | grep -oP '(?<=<span style="font-size:12px;">).*?(?=</span>)' | sed 's;<span.*">;;g;s;</span>;;g' )

执行脚本,得到:

--------- url is http://movie.douban.com/tag/%E7%A7%91%E ... =S&start=0 ---------
9.6(173人评价)
9.4(169人评价) 天体音乐
9.4(1112人评价) 2011-03-17 弗兰肯斯坦 / 弗兰肯斯坦的灵与肉
9.3(217人评价) 2005-11-18
9.3(659人评价) 1998-03-07 新世紀エヴァンゲリオン劇場版 REVIVAL OF EVANGELION / NEON GENESSI EVANGELION:REV
9.3(2586人评价) 2010-01-01 神秘博士2010特别篇 / 神秘博士:时间尽头(下)
9.3(19312人评价) 1997-07-19 新世纪福音战士剧场版 / Shin seiki Evangelion Gekijô-ban: Air/Magokoro wo, kimi ni
9.3(310414人评价) 2008-06-27 太空奇兵·威E(港) / 瓦力(台)
9.2(477543人评价) 2010-09-01 潜行凶间(港) / 全面启动(台)
none(尚未上映)
9.2(14493人评价) 1997-03-15 Neon Genesis Evangelion: Death & Rebirth / Shin seiki Evangelion Gekijô-ban: Shito shinsei
9.2(1439人评价) 2006-01-27 Kôkaku kidôtai: S.A.C. 2nd GIG - Individual eleven / Ghost in the Shell: S.A.C. 2nd GIG - Indi
8.9(249人评价) Shanhu dao shang de shi guang
9.2(2355人评价) 2009-12-25 神秘博士2009特别篇 / 神秘博士:时间尽头(上)
9.1(1169人评价) 2007-11-16 Children in need special
9.1(2739人评价) 2003-06-01 机器的复兴:第2部 / 黑客帝国动画版
9.1(1599人评价) 2013-04-20 剧场版 斯坦因之门 负荷领域的既视感 / Gekijōban Shutainzu Gēto Fuka Ryōiki no
9.0(2847人评价) 2003-06-03 机器的复兴:第1部 / 黑客帝国动画版
7.8(49932人评价) 2013-10-31 雷神奇侠2:黑暗世界(港) / 雷神索尔2:黑暗世界(台)
none(尚未上映) 2016-03-11 魔兽世界

奇怪的地方:

数据的第一行:
“9.6(173人评价)”,说明该列表有一个评分为9.6分的电影;但是我在豆瓣页面,以及代码上,都看不到9.6分的片子说明;
“none(...)” 这种记录,我同样没有看到;太诡异了吧?

另外,这种网页抓取,还是html分析来的靠谱一点;纯regexp,真蛋疼。
头像
nmsfan
帖子: 18958
注册时间: 2009-10-16 22:46
来自: finland

Re: shell实现抓取豆瓣高评分电影列表

#6

帖子 nmsfan » 2013-11-29 10:43

我的乖乖…………不错嘛
>>>>推Ubuntu 桌面培训~~<<<<
>>>>想加入/了解gimp汉化吗,点我吧~<<<<
——————————————————————
不推荐wubi,也不推荐你给别人推荐wubi…………
随心而为的感觉真好……
强推mayhem!!
强推ensiferum
头像
needle
帖子: 78
注册时间: 2009-12-01 13:34

Re: shell实现抓取豆瓣高评分电影列表

#7

帖子 needle » 2013-12-11 22:18

sarrow 写了:修改下句后:
name=$(echo "$i" | grep -oP '(?<=<span style="font-size:12px;">).*?(?=</span>)' )
# name=$(echo "$i" | grep -oP '(?<=<span style="font-size:12px;">).*?(?=</span>)' | sed 's;<span.*">;;g;s;</span>;;g' )

执行脚本,得到:

--------- url is http://movie.douban.com/tag/%E7%A7%91%E ... =S&start=0 ---------
9.6(173人评价)
9.4(169人评价) 天体音乐
9.4(1112人评价) 2011-03-17 弗兰肯斯坦 / 弗兰肯斯坦的灵与肉
9.3(217人评价) 2005-11-18
9.3(659人评价) 1998-03-07 新世紀エヴァンゲリオン劇場版 REVIVAL OF EVANGELION / NEON GENESSI EVANGELION:REV
9.3(2586人评价) 2010-01-01 神秘博士2010特别篇 / 神秘博士:时间尽头(下)
9.3(19312人评价) 1997-07-19 新世纪福音战士剧场版 / Shin seiki Evangelion Gekijô-ban: Air/Magokoro wo, kimi ni
9.3(310414人评价) 2008-06-27 太空奇兵·威E(港) / 瓦力(台)
9.2(477543人评价) 2010-09-01 潜行凶间(港) / 全面启动(台)
none(尚未上映)
……
奇怪的地方:

数据的第一行:
“9.6(173人评价)”,说明该列表有一个评分为9.6分的电影;但是我在豆瓣页面,以及代码上,都看不到9.6分的片子说明;
“none(...)” 这种记录,我同样没有看到;太诡异了吧?

另外,这种网页抓取,还是html分析来的靠谱一点;纯regexp,真蛋疼。
:em05
页面被改动过,原脚本name的正则有点子问题了,就是:

代码: 全选

name=$(echo "$i" | grep -oP '(?<= >).*(?=</a>)' | ...
我当初为了精确点,grep里多加了个空格匹配,现在页面去掉了这个空格,于是匹配不到了~,改成:

代码: 全选

name=$(echo "$i" | grep -oP '(?<=>).*(?=</a>)' | ...
又正常了。那个none是我脚本里添的,未上映的,评分就赋个none,为了排版好看点。
html分析怎么做呢,我不会~ :em03
你再试试 :em05
myshell^_^
xfce4.10最好用了……
舒适的滚轮升起焦点设计,大量快捷键,alt移动,糟糕的桌面图标……
珍爱生命,LFS 三思~
头像
枫叶饭团
帖子: 14683
注册时间: 2010-06-16 1:05
系统: Mac OS X
来自: Tencent
联系:

Re: shell实现抓取豆瓣高评分电影列表

#8

帖子 枫叶饭团 » 2013-12-11 22:22

高端霸气上流
头像
needle
帖子: 78
注册时间: 2009-12-01 13:34

Re: shell实现抓取豆瓣高评分电影列表

#9

帖子 needle » 2013-12-11 22:27

枫叶饭团 写了:高端霸气上流
你是编辑吧,不然怎么这么快就通过了?
谢谢 :em05
myshell^_^
xfce4.10最好用了……
舒适的滚轮升起焦点设计,大量快捷键,alt移动,糟糕的桌面图标……
珍爱生命,LFS 三思~
头像
needle
帖子: 78
注册时间: 2009-12-01 13:34

Re: shell实现抓取豆瓣高评分电影列表

#10

帖子 needle » 2013-12-11 22:40

nmsfan 写了:我的乖乖…………不错嘛
谢谢 :em02
myshell^_^
xfce4.10最好用了……
舒适的滚轮升起焦点设计,大量快捷键,alt移动,糟糕的桌面图标……
珍爱生命,LFS 三思~
回复