抓取动态网页(有些网页就是动态网页的图片元素是怎么自动形成的)
优采云 发布时间: 2021-10-01 03:26抓取动态网页(有些网页就是动态网页的图片元素是怎么自动形成的)
好的,上次我们讲了如何抓取豆瓣美子和暴走*敏*感*词*页面的图片,但是这些页面都是静态页面,几行代码就可以解决问题,因为图片的src在页面(具体来说,失控的*敏*感*词*和尴尬的百科全书如何自动形成一个静态页面是要讨论的)。静态页面的优点是加载速度非常快。
然而,并不是所有的网页抓取都那么简单。有些网页是动态网页,也就是说页面中的图片元素是由js生成的。原来的html没有图片的src信息,所以希望Python可以模拟浏览器加载js,执行js后返回页面,这样就可以看到src信息了。我们知道图片在哪,不能下载到本地吗(其实如果有链接你可能抓不到,后面再讲)。
有些网站为了防止别人获取图片,或者说是知识产权,有很多方法,比如*敏*感*词*网站、爱*敏*感*词*和腾讯*敏*感*词*,前者是动态网页生成的图片我说,所以当你打开一个有*敏*感*词*的页面时,图片加载会很慢,因为它是由js生成的(毕竟它不会让你轻易抓取它)。后者比较棘手,或者如果你想捕捉Flash加载的图像,你需要Python来模拟Flash。以后再研究这部分。
那么上面说的,即使我已经实现了Python用js加载页面并获取了图片元素的src,在访问src的时候,也会说404,比如这个链接。这是爱情*敏*感*词*的全职猎人之一。在*敏*感*词*页面上,当我使用浏览的F12功能时,找到了图片的src属性。当我将链接复制到浏览器时,他告诉我一个 404 错误。该页面不存在。是什么原因?显然是这个地址。啊,而且多次刷新的页面地址也是一样的(别告诉我你能看到这张图,是浏览器缓存的原因,你可以尝试清除缓存,骚年)?那是因为,如果你捕捉网页加载,你会发现获取页面图片的Get请求有以下信息:
GET /Files/Images/76/59262/imanhua_001.jpgHTTP/1.1
接受 image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5
推荐人
接受语言 zh-CN
用户代理 Mozilla/5.0(WindowsNT6.1;WOW64;Trident/7.0;rv:11.0)likeGecko
接受编码 gzip,放气
主持人
连接保持活动
在这里,你只需要模拟他的Get请求来获取图片,因为网站过滤了Get,只有你自己的请求网站才会返回图片,所以我们要在request中添加以上信息在header中,经过测试,只需要添加Referer
信息会做。URL 是当前网页的 URL。
我们已经说明了具体实现的原理,接下来看看用的是什么包:
1.BeautifulSoup包用于根据URL获取静态页面中的元素信息。我们用它来获取爱*敏*感*词*网站中某部*敏*感*词*的所有章节的url,并根据章节的url获取该章节的总页数,并获取每个页面的url,参考材料
2.Ghost包,用于根据每个页面的url动态加载js,加载后获取页面代码,获取image标签的src属性,Ghost官网,参考资料
3.urllib2包,模拟Get请求,使用add_header添加Referer参数获取返回图片
4.chardet 包,解决页面乱码问题
我们依次以以上四个步骤为例,或者以抢爱*敏*感*词*网站的*敏*感*词*为例:
1. 输入*敏*感*词*号,通过BeautifulSoup获取所有章节和章节下的子页面url
2. 根据第一步动态获取的页面url,使用Ghost动态加载页面,传入url获取页面图片的src
#通过Ghost模拟js获取动态网页生成的图片src
class FetcherCartoon:
def getCartoonUrl(self,url):
if url is None:
return false
#todo many decide about url
try:
ghost = Ghost()
#open webkit
ghost.open(url)
#exceute javascript and get what you want
page, resources = ghost.wait_for_page_loaded()
result, resources = ghost.evaluate("document.getElementById('comic').getAttribute('src');", expect_loading=True)
del resources
except Exception,e:
print e
return None
return result
3.urllib2 模拟Get请求并写入图片
#传入url模拟Get请求,获取图片内容
def GetImageContent(wholeurl,imgurl):
time.sleep(0.1)
req = urllib2.Request(imgurl)
req.add_header('Referer', wholeurl)
content = urllib2.urlopen(req).read()
rstr = r"[\/\\\:\*\?\"\\|]" # '/\:*?"|'
new_title = re.sub(rstr, "", str(imgurl)[-20:])
with open(cartoonName+'/'+new_title,'wb') as code:
code.write(content)
4.chardet 解决乱码问题
#解决乱码问题
html_1 = urllib2.urlopen(basicURL,timeout=120).read()
mychar = chardet.detect(html_1)
bianma = mychar['encoding']
if bianma == 'utf-8' or bianma == 'UTF-8':
html = html_1
else :
html = html_1.decode('gb2312','ignore').encode('utf-8')
整体代码如下:
<p># -*- coding:utf8 -*-
import urllib2,re,os,time
import chardet
import cookielib,httplib,urllib
from bs4 import BeautifulSoup
from ghost import Ghost
webURL = 'http://www.imanhua.com/'
cartoonNum = raw_input("请输入*敏*感*词*编号:")
basicURL = webURL + u'comic/' + cartoonNum
#通过Ghost模拟js获取动态网页生成的图片src
class FetcherCartoon:
def getCartoonUrl(self,url):
if url is None:
return false
#todo many decide about url
try:
ghost = Ghost()
#open webkit
ghost.open(url)
#exceute javascript and get what you want
page, resources = ghost.wait_for_page_loaded()
result, resources = ghost.evaluate("document.getElementById('comic').getAttribute('src');", expect_loading=True)
del resources
except Exception,e:
print e
return None
return result
#解决乱码问题
html_1 = urllib2.urlopen(basicURL,timeout=120).read()
mychar = chardet.detect(html_1)
bianma = mychar['encoding']
if bianma == 'utf-8' or bianma == 'UTF-8':
html = html_1
else :
html = html_1.decode('gb2312','ignore').encode('utf-8')
#获取*敏*感*词*名称
soup = BeautifulSoup(html)
cartoonName = soup.find('div',class_='share').find_next_sibling('h1').get_text()
print u'正在下载*敏*感*词*: ' + cartoonName
#传入url模拟Get请求,获取图片内容
def GetImageContent(wholeurl,imgurl):
#time.sleep(0.1)
req = urllib2.Request(imgurl)
req.add_header('Referer', wholeurl)
content = urllib2.urlopen(req).read()
rstr = r"[\/\\\:\*\?\"\\|]" # '/\:*?"|'
new_title = re.sub(rstr, "", str(imgurl)[-20:])
with open(cartoonName+'/'+new_title,'wb') as code:
code.write(content)
#创建文件夹
path = os.getcwd() # 获取此脚本所在目录
new_path = os.path.join(path,cartoonName)
if not os.path.isdir(new_path):
os.mkdir(new_path)
#解析所有章节的URL
chapterURLList = []
chapterLI_all = soup.find('ul',id = 'subBookList').find_all('a')
for chapterLI in chapterLI_all:
chapterURLList.append(chapterLI.get('href'))
#print chapterLI.get('href')
#遍历章节的URL
for chapterURL in chapterURLList:
chapter_soup = BeautifulSoup(urllib2.urlopen(webURL+str(chapterURL),timeout=120).read())
chapterName = chapter_soup.find('div',id = 'title').find('h2').get_text()
print u'正在下载章节: ' + chapterName
#根据最下行的最大页数获取总页数
allChapterPage = chapter_soup.find('strong',id = 'pageCurrent').find_next_sibling('strong').get_text()
print allChapterPage
#然后遍历所有页,组合成url,保存图片
currentPage = 1
fetcher = FetcherCartoon()
uurrll = str(webURL+str(chapterURL))
imgurl = fetcher.getCartoonUrl(uurrll)
if imgurl is not None:
while currentPage