首先分析电影天堂网站的首页结构。
从上面的菜单栏可以看到整个网站资源的整体分类情况。 正好我们可以利用那个分类,把所有的分类目的地作为爬虫的出发点。
分析首页地址提取分类信息
# #主页的解析
defcrawindexpage (状态) :
正在登上打印首页'
页面=_ _页面(状态) )。
if page=='错误' :
返回
page=page.decode('gbk ',' ignore ' ) )。
tree=etree.html (页)
nodes=树. XPath ((/div ) ) id=)菜单()/a ) ) ) ) )。
用打印首页解决地址“,len(nodes ),条)
节点内节点:
克拉尔德Urls=[ ]
crawled URLs.append (星形)
URL=节点. XPath (' @ href ' ) [0]
ifre.match (r '/html/[ a-za-z0-9 _/] /索引. html ',url ) :
if _ is退出(主机用户) :
传球
else:
try:
catalog=节点路径('文本) ) )0) .编码) ) utf-8 ) ) )。
新dir=' e : /电影资源/'目录
操作系统(新解码器) utf-8 ) )
打印'分类目录创建成功------- '新建dir
thread=my thread (主机故障、新故障、崩溃故障) ) )。
thread.start (
except:
传球
在这个函数中,首先下载网页的源代码,然后用XPath分析其中的菜单分类信息。 创建适当的文件目录。 有一点需要注意的是编码问题,但这个编码也困扰了很久。 如果你看看网页的源代码,就会发现网页的编码采用的是GB2312。 在此,使用XPath构建树对象需要对文本信息进行解码操作,通过将GB2312设为Unicode编码,可以看到DOM树结构是正确的。 否则,以后分析时会出现问题。
分析各分类的主页
# #分析分类文件
efcrawlistpage (索引URL、文件夹、布线URLs ) :
正在解析打印“分类主页资源”
打印索引URL
page=_ _ getpage (索引值) ) )。
if page=='错误' :
返回
crawled URLs.append (索引URL ) )。
page=page.decode('gbk ',' ignore ' ) )。
tree=etree.html (页)
nodes=树. XPath ((/div ) )类=) co_content8) )/a ) ) ) ) )。
节点内节点:
URL=节点. XPath (' @ href ' ) [0]
ifre.match(r'/',url ) :
# #非寻呼地址解析视频资源的地址
if _ is退出(主机用户) :
传球
else:
# #文件名不能使用以下特殊符号
文件名=节点路径('文本) ) )0) .编码) ) utf-8 ) .替换) /,“”) ) ) ) )。
. replace ((((),() ) ) ) ) ) ) ) ) )。
. replace(': ','') () () ) ) ) ) ) ) ) ) ) ) ) ) ) )
. replace('* ','') ) ) ) ) ) ) )。
. replace (? ''() () ) () ) () ) ) ) ) ) ) )
. replace (((((,) ) () ) ) (输出) ) ) ) )变得更加精确,因为它们会变得更加精确。
. replace (','') () ) ) () ) ) ) ) ) )至) )中的一个示例。
. replace (','') () ) ) () ) ) ) ) ) )至) )中的一个示例。
.替换((|,) ) ) )
crawlsourcepage (主机用户、文件夹、文件名、crawled用户) )。
传球
else:
从嵌套重新解析# # #分页地址
打印'从分页地址的嵌套重新解析',url
索引=索引URL.rfind ('/' )
基本URL=索引URL [ 0:索引1 ]
pageurl=基本URL
if _ is退出(页面,卷曲的URLs ) :
传球
else:
打印'从分页地址的嵌套重新解析',pageurl
crawlistpage (页面,文件夹,c
rawledURLs) pass pass打开每一个分类的首页会发现都有一个相同的结构,首先解析出包含资源URL的节点,然后将名称和URL提取出来。这一部分有两个需要注意的地方。一是因为最终想要把资源保存到一个txt文件中,但是在命名时不能出现一些特殊符号,所以需要处理掉。二是一定要对分页进行处理,网站中的数据都是通过分页这种形式展示的,所以如何识别并抓取分页也是很重要的。通过观察发现,分页的地址前面没有“/”,所以只需要通过正则表达式找出分页地址链接,然后嵌套调用即可解决分页问题。
③解析资源地址保存到文件中
#处理资源页面 爬取资源地址 def CrawlSourcePage(url,filedir,filename,CrawledURLs): print url page = __getpage(url) if page=="error": return CrawledURLs.append(url) page = page.decode('gbk', 'ignore') tree = etree.HTML(page) Nodes = tree.xpath("//div[@align='left']//table//a") try: source = filedir + "/" + filename + ".txt" f = open(source.decode("utf-8"), 'w') for node in Nodes: sourceurl = node.xpath("text()")[0] f.write(sourceurl.encode("utf-8")+"n") f.close() except: print "!!!!!!!!!!!!!!!!!"这段就比较简单了,将提取出来的内容写到一个文件中就行了
完整代码
import re import threading import os from urllib2 import Request,urlopen,URLError,HTTPError from lxml import etree class myThread (threading.Thread): #继承父类threading.Thread def __init__(self, url, newdir,CrawledURLs): threading.Thread.__init__(self) self.url = url self.newdir = newdir self.CrawledURLs=CrawledURLs def run(self): #把要执行的代码写到run函数里面 线程在创建后会直接运行run函数 CrawListPage(self.url, self.newdir,self.CrawledURLs) starturl="http://www.ygdy8.com/index.html" host="http://www.ygdy8.com" #判断地址是否已经爬取 def __isexit(newurl,CrawledURLs): for url in CrawledURLs: if url == newurl: return True return False #获取页面资源 def __getpage(url): req = Request(url) user_agent = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 ' '(KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36' req.add_header('User-Agent', user_agent) try: response = urlopen(req, timeout=60) except: return "error" pass else: page = response.read() return page #处理资源页面 爬取资源地址 def CrawlSourcePage(url,filedir,filename,CrawledURLs): print url page = __getpage(url) if page=="error": return CrawledURLs.append(url) page = page.decode('gbk', 'ignore') tree = etree.HTML(page) Nodes = tree.xpath("//div[@align='left']//table//a") try: source = filedir + "/" + filename + ".txt" f = open(source.decode("utf-8"), 'w') for node in Nodes: sourceurl = node.xpath("text()")[0] f.write(sourceurl.encode("utf-8")+"n") f.close() except: print "!!!!!!!!!!!!!!!!!" # 解析分类文件 def CrawListPage(indexurl,filedir,CrawledURLs): print "正在解析分类主页资源" print indexurl page = __getpage(indexurl) if page=="error": return CrawledURLs.append(indexurl) page = page.decode('gbk', 'ignore') tree = etree.HTML(page) Nodes = tree.xpath("//div[@class='co_content8']//a") for node in Nodes: url=node.xpath("@href")[0] if re.match(r'/', url): # 非分页地址 可以从中解析出视频资源地址 if __isexit(host + url,CrawledURLs): pass else: #文件命名是不能出现以下特殊符号 filename=node.xpath("text()")[0].encode("utf-8").replace("/"," ") .replace("\"," ") .replace(":"," ") .replace("*"," ") .replace("?"," ") .replace("""," ") .replace("<", " ") .replace(">", " ") .replace("|", " ") CrawlSourcePage(host + url,filedir,filename,CrawledURLs) pass else: # 分页地址 从中嵌套再次解析 print "分页地址 从中嵌套再次解析",url index = indexurl.rfind("/") baseurl = indexurl[0:index + 1] pageurl = baseurl + url if __isexit(pageurl,CrawledURLs): pass else: print "分页地址 从中嵌套再次解析", pageurl CrawListPage(pageurl,filedir,CrawledURLs) pass pass #解析首页 def CrawIndexPage(starturl): print "正在爬取首页" page = __getpage(starturl) if page=="error": return page = page.decode('gbk', 'ignore') tree = etree.HTML(page) Nodes = tree.xpath("//div[@id='menu']//a") print "首页解析出地址",len(Nodes),"条" for node in Nodes: CrawledURLs = [] CrawledURLs.append(starturl) url=node.xpath("@href")[0] if re.match(r'/html/[A-Za-z0-9_/]+/index.html', url): if __isexit(host + url,CrawledURLs): pass else: try: catalog = node.xpath("text()")[0].encode("utf-8") newdir = "E:/电影资源/" + catalog os.makedirs(newdir.decode("utf-8")) print "创建分类目录成功------"+newdir thread = myThread(host + url, newdir,CrawledURLs) thread.start() except: pass CrawIndexPage(starturl)最后爬取的结果如下:
.