最近需要修正一些明星头像照片集合中的bad case,手动替换的过程中发现 http://www.manmankan.com 这个网址不错,所以打算先爬取该网站的明星头像照片对我的素材进行替换,然后再修正bad case。这样兴许可以减小工作量。

因为该网站采用了明星信息动态加载的方式,所以直接爬虫是爬不到的。解决该问题的方式有两种:

  • selenium+phantomjs。 Selenium是一个开源的自动化测试工具,可以用于测试web应用程序。PhantomJS是一个没有界面的浏览器。使用Python+Selenium+PhantomJS可以很方便的爬取动态加载的网页。其中PhantomJS 用来渲染解析JS,Selenium 用来驱动PhantomJS 并与 Python 的对接,Python 进行后期的数据处理。但是目前PhantomJS似乎停止维护了。
    关于这种方式,python获取完整网页内容(即包括js动态加载的):selenium+phantomjs 有介绍。
  • 分析js请求。我比较倾向于这个方式。一般动态加载的网页都是通过js向服务器端发送请求获取数据的,这样的话我们就可以截获请求,然后模拟请求进行访问了,相比之下,这种效率更高。

第二种方式如何截获请求呢?

首先,使用开发版Firefox打开相关界面,使用查看器查看相关内容元素。如图所示:

在相关元素旁边有两个比较可疑的东西,loadSearch()函数和 http://hit.manmankan.com/dy2013/search.asp?rnd=0.5952100315643931&keywords=刘亦菲&t=3&fl=0 。都有search关键词,嗯,暂且记下。

然后从查看器切换到网络板块,并在网页上输入刘亦菲进行搜索,观察发生了哪些网络传输行为。这时会有好多传输信息显示,既然我们刚刚发现了search关键词,那么我们可以输入search关键词,看看剩下些什么。

这两个东西貌似很熟悉,第二个网址和之前发现的网址很像啊,输入浏览器看看是啥。

这正是咱们需要的结果嘛。我们可以用Python访问这个网址,就会得到相关网页,然后进行正则提取就好了。

然后再看看两个网址有啥区别,貌似关键词不同,应该是中文网址进行了URL编码。那么我们只需要在Python中对中文名字进行相应编码即可。

1
2
3
http://hit.manmankan.com/dy2013/search.asp?rnd=0.5952100315643931&keywords=刘亦菲&t=3&fl=0

http://hit.manmankan.com/dy2013/search.asp?rnd=0.5952100315643931&keywords=%C1%F5%D2%E0%B7%C6&t=3&fl=0

那么我们再看看search.js文件,看看能不能找到loadSearch()函数,毕竟看名字二者存在很大关联。果不其然,发现如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
function loadSearch() 
{
var key = QueryString("KeyWords");
if (key == undefined || key == null || key == "")
{
$('#lilist').html("<span>请输入要查询的关键字</span>");
return;
}
if(key.indexOf("script")>0)
{
return;
}
key = decodeURIComponent(key);
key=stripscript(key);
var fid = QueryString("fl");
if (fid == undefined || fid == null || fid == "")
{
fid=0;
}
searchlist(key,fid);
}
function searchlist(keywords,fid)
{
keywords = Trim(keywords);
//alert(keywords);
$('#lilist').html("<span>正在搜索中....</span>");
$('#keyword').val(keywords);
$('#kw').html(keywords);
if (keywords == undefined || keywords == "")
{
$('#lilist').html("<span>请输入要查询的关键字</span>");
return;
}
var ReturnScript,ReturnValue;
if (keywords != undefined && keywords != "")
{
ReturnScript=document.createElement('script');
ReturnScript.src="http://hit.manmankan.com/dy2013/search.asp?rnd="+Math.random()+"&keywords="+decodeURIComponent(keywords)+"&t=3&fl="+fid;
document.body.appendChild(ReturnScript);
}
}

//查询结果显示
function SearchResult(innerHTMLValue)
{
var retv=innerHTMLValue;
if(retv=="")
{
$('#lilist').html("<span>没有找到您搜索的明星!!!</span>");
}
else
{
$("#lilist").html("");
$("#lilist").html(retv);
}
}

来吧,我们可以编码了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#coding:utf8
import os
import urllib2
import re
from urllib import quote
import sys
reload(sys)
sys.setdefaultencoding('utf8')

def getPage(url):
# 如果你处于公司内网的话,可以使用代理,方法如下:
# The proxy address and port:
# proxy_info = {'host': 'your_proxy_site', 'port': your_proxy_site}

# We create a handler for the proxy
# proxy_support = urllib2.ProxyHandler({"http": "http://%(host)s:%(port)d" % proxy_info})

# We create an opener which uses this handler:
# opener = urllib2.build_opener(proxy_support)

# Then we install this opener as the default opener for urllib2:
# urllib2.install_opener(opener)

header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0"}

request = urllib2.Request(url=url, headers=header) # 模拟浏览器进行访问
response = urllib2.urlopen(request)
text = response.read()

return text


def getHtml(url):
page = getPage(url)
html = unicode(page,'GBK').encode("utf8")
return html


def getImg(html, reg):
imgre = re.compile(reg)
imglist = re.findall(imgre, html)
return imglist


def loadImg(url, path):
page = getPage(url)
data = page
f1 = open(path, "wb")
f1.write(data)
f1.close()

def load_picname(path):
files = os.listdir(unicode(path, "utf8")) # 得到文件夹下的所有文件名称
pic_name=[]
for f in files:
pic_name.append(f.split(".")[0])
return pic_name


if __name__=="__main__":
#配置 begin

imgpath = "imgs" # 图片保存路径
picname_path=r"D:\\wsp\\明星头像\\dzb" # 获取所有图片名

#配置 end

if not os.path.exists('.\\' + imgpath):
os.mkdir('.\\' + imgpath)
names=load_picname(picname_path)

reg = r'src="([^"]*jpg)" alt="(.*?)"/>'
url = "http://hit.manmankan.com/dy2013/search.asp?keywords=%s&t=3&fl=0"
# names=["赵君","胡歌","裕美 "]


# s="赵君"
# s=s.decode("utf8").encode("gbk")
# print(quote(s))
#s=unicode(s,'utf8').encode("gbk")

count=0
exist_pic_count=0
for name in names:
print(count)
count+=1
name=name.decode("utf8").encode("gbk")
turl = (url) % name
html = getHtml(turl)
d = getImg(html, reg)
print(html)

if len(d)>0:
print("exist_pic_count: "+str(exist_pic_count))
exist_pic_count+=1
# loadList(filed,d)
pic_name=d[0][1].strip().decode("utf8").encode("gbk")
loadImg(d[0][0].strip(),(imgpath + "/%s.jpg") %pic_name)