一个简单的爬虫—电影天堂爬虫 – 热爱改变生活
我的GitHub GitHub |     登录
  • If you can't fly, then run; if you can't run, then walk; if you can't walk, then crawl
  • but whatever you do, you have to keep moving forward。
  • “你骗得了我有什么用,这是你自己的人生”
  • 曾有伤心之地,入梦如听 此歌

一个简单的爬虫—电影天堂爬虫

Python sinvader 3180℃ 0评论

电影天堂是一个下载站,里面有很多经典的电影下载链接,这些链接都可以使用迅雷来下载,今天就来爬一遍这个站,将感兴趣的保存起来。

安装并创建 scrapy 项目

首先要安装好 scrapy, 见 Python 爬虫进阶三之 Scrapy 框架安装配置
安装好之后,创建一个新的 scrapy 项目。使用命令:

scrapy startproject dmoz

最后的 dmoz 是本项目的名字,可以随意命名。

找到或创建爬虫代码文件

项目创建好之后,进入找到一个叫 spiders 的文件夹,在这个文件夹里面可以找到一个名字中包含 spider 的 py 文件,或者自己创建一个放进去也可以,这个 py 文件,就是爬虫的代码文件,这个里面规定了这个爬虫要怎么去爬去网络的数据,以及如何保存爬去到的东西。

编写爬虫代码

from scrapy.spider import BaseSpider
class DmozSpider(BaseSpider):
    name = "dmoz"
    allowed_domains = ["www.dytt8.net"]
    start_urls = [
	"http://www.dytt8.net/plus/sitemap.html"
	]
    def parse(self, response):

name 属性很重要,不同 spider 不能使用相同的 name
start_urls 是 spider 抓取网页的起始点,可以包括多个 url,用逗号隔开
parse 方法是 spider 抓到一个网页以后默认调用的 callback,避免使用这个名字来定义自己的方法。
当 spider 拿到 url 的内容以后,会调用 parse 方法,并且传递一个 response 参数给它,response 包含了抓到的网页的内容,在 parse 方法里,你可以从抓到的网页里面解析数据。上面的代码只是简单地把网页内容保存到文件。

在本例中,parse 中获得网页的内容之后,解析内容,获得网页中的包含下载链接的内容,保存起来即可。
那么要如何解析获得内容呢?
scrapy 提供了方便的办法从网页中解析数据,这需要使用到 HtmlXPathSelector

        hx = HtmlXPathSelector(response);
        title = hx.xpath("//title/text()").extract()
        sites = hx.xpath('//*[@id="Zoom"]//table//td')
        text = title
        try:
            textStr = str(text[0])
        except Exception as e:
            textStr = ""
        urlData = str(response.url)

在这段代码里,我从网页中获得了标签为 title 的文本内容并赋值到 title 变量里面
又从网页中寻找 id 为 Zoom 的标签,从这个标签里面获得所有的 table,从这些 table 中找 td,将这些 td 都放到了 sites 里面
然后我将这个网页的地址通过 response.url 获得之后转化为字符串放到 urlData 里面
这个时候我已经获得了这个网页里面大部分我需要的东西
然后我只要循环 sites 来获得每个 td 里面的内容以及地址就可以了

for sel in sites:
                urltext = [t.encode("utf-8") for t in sel.xpath('a/text()').extract()]
                url = [u.encode("utf-8") for u in sel.xpath('a/@href').extract()]
                # text = [d.encode("utf-8") for d in title]

                try:
                    urlStr = str(url[0])
                except Exception as e:
                    urlStr = ""

                try:
                    urlTextStr = str(urltext[0])
                except Exception as e:
                    urlTextStr=""

urltest 是文字,url 是下载地址
之后将这写东西保存就可以了,可以写入到本地文件中,也可以连接到数据库直接保存到数据库里面
还有很重要的一点,那就是在爬取的时候在页面中找到的链接都要添加到待爬取列表中,否则只爬取一个页面就断了可不是我们的本意

        hrefs = hx.xpath("//a/@href")
        for href in hrefs:
            if href.extract().find('http')==0:
                url = href.extract()
            else:
                url = urlparse.urljoin(response.url, href.extract())
            yield Request(url, callback=self.parse_dir_contents)

这段代码里面首先从网页中找到了所有的 a 标签,然后获得了 a 标签的 href。
判断这个 href 里面是否包含 http,如果不包含,可能是一个相对地址,也可能是一段 js,如果是相对地址,那么就需要补全这个地址,如果不是而是一段 js,那加上也没什么问题,最多就是访问不通(最好是加上判断,我这里没有加),然后去这个地址去请求就可以了,之后会一层一层递归,回到最开始,这个遍历的过程就完成了。
注:scrapy 会自动判断这个地址是否已经访问过,不用我们去记录

代码

#!/usr/bin/python  
# -*- coding:utf-8 -*-  
from scrapy.spider import BaseSpider
from scrapy.selector import HtmlXPathSelector
from pengpai.items import PengpaiItem
import urlparse
from scrapy.http import Request
import sys
import codecs
import MySQLdb
import datetime

class DmozSpider(BaseSpider):
    name = "dmoz"
    allowed_domains = ["www.dytt8.net"]
    start_urls = [
	"http://www.dytt8.net/plus/sitemap.html"
	]
    def toSql(self,dataStr):
        resultId = -1
        db = MySQLdb.connect("dburl","zhanghao","mima","dbname")
        cursor = db.cursor()
        cursor.execute("SET NAMES utf8")
        cursor.execute("SELECT VERSION()")
        try:
            cursor.execute(dataStr)
            resultId = int(db.insert_id())
            db.commit()
        except:
            db.rollback()
        db.close()
        return resultId
    def parse(self, response):
        reload(sys)
        sys.setdefaultencoding('utf-8')
        hx = HtmlXPathSelector(response)
        hrefs = hx.xpath("//a/@href")
        for href in hrefs:
            if href.extract().find('http')==0:
                url = href.extract()
            else:
                url = urlparse.urljoin(response.url, href.extract())
            yield Request(url, callback=self.parse_dir_contents)
        # file_object.close( )

    def parse_dir_contents(self, response):
        hx = HtmlXPathSelector(response);
        title = hx.xpath("//title/text()").extract()
        sites = hx.xpath('//*[@id="Zoom"]//table//td')
        text = title
        try:
            textStr = str(text[0])
        except Exception as e:
            textStr = ""
        urlData = str(response.url)
        resultfile = codecs.open('result.txt','a',"utf-8")
        if(len(sites)>0):
            print(str(len(sites))+"=="+str(response.url))
            #INSERT into movie_name (movie_name.`name`,movie_name.url,movie_name.count) SELECT 'name','http','3' from DUAl WHERE NOT EXISTS (SELECT 1 from movie_name WHERE movie_name.url = 'http' and movie_name.count='3')
            movie_name = "INSERT into movie_name (movie_name.`name`,movie_name.url,movie_name.count) SELECT '"+textStr+"','"+urlData+"','"+str(len(sites))+"' from DUAl WHERE NOT EXISTS (SELECT 1 from movie_name WHERE movie_name.url = '"+urlData+"' and movie_name.count='"+str(len(sites))+"')LIMIT 1;"
            # file_object = codecs.open('thefile.txt', 'a',"utf-8")
            resultIDBack = self.toSql(movie_name)
            resultfile.write(movie_name)
            resultfile.write('\n')
            for sel in sites:
                urltext = [t.encode("utf-8") for t in sel.xpath('a/text()').extract()]
                url = [u.encode("utf-8") for u in sel.xpath('a/@href').extract()]
                # text = [d.encode("utf-8") for d in title]

                try:
                    urlStr = str(url[0])
                except Exception as e:
                    urlStr = ""

                try:
                    urlTextStr = str(urltext[0])
                except Exception as e:
                    urlTextStr=""

                
                dt=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                #data = "insert into movie (movie.`name`,movie.url,movie.urltext,movie.`from`) values (\""+textStr+"\",\""+urlStr+"\",\""+urlTextStr+"\",\""+urlData+"\");"
                #INSERT INTO movie_data (movie_data.nameId,movie_data.url,movie_data.urltext,movie_data.`from`,movie_data.updateTime) SELECT '1','dizhi','wenzi','laiyuan',NOW() FROM DUAL WHERE NOT EXISTS(SELECT 1 from movie_data WHERE movie_data.`from` = 'laiyuan' and movie_data.url = 'dizhi' AND movie_data.urltext = 'wenzi') LIMIT 1;
                #INSERT INTO movie (	movie.`name`,movie.url,movie.urltext,movie.`from`,updateTime) SELECT '"+textStr+"', '"+urlStr+"', '"+urlTextStr+"', '"+urlData+"', '"+dt+"' FROM DUAL WHERE NOT EXISTS ( SELECT 1 FROM movie WHERE movie.url = '"+urlStr+"' AND movie.`from` = '"+urlData+"')LIMIT	1;
                data = "INSERT INTO movie_data (movie_data.nameId,movie_data.url,movie_data.urltext,movie_data.`from`,movie_data.updateTime) SELECT '"+str(resultIDBack)+"','"+urlStr+"','"+urlTextStr+"','"+urlData+"','"+dt+"' FROM DUAL WHERE NOT EXISTS(SELECT 1 from movie_data WHERE movie_data.`from` = '"+urlData+"' and movie_data.url = '"+urlStr+"' AND movie_data.urltext = '"+urlTextStr+"') LIMIT 1;"
                # file_object.write("["+str(text[0])+"] 已添加..")
                # file_object.write('\n')
                resultfile.write(data)
                resultfile.write('\n')
                #print(data)
                self.toSql(data)
        hrefs = hx.xpath("//a/@href")
        for href in hrefs:
            if href.extract().find('http')==0:
                url = href.extract()
            else:
                url = urlparse.urljoin(response.url, href.extract())
            yield Request(url, callback=self.parse_dir_contents)
        resultfile.close( )
        # file_object.close( )

好了,这时候只要运行这个爬虫就可以了

scrapy crawl dmoz

这个里面的 dmoz 就是上面代码中 name 的那个值

¥ 有帮助么?打赏一下~

转载请注明:热爱改变生活.cn » 一个简单的爬虫—电影天堂爬虫


本博客只要没有注明“转”,那么均为原创。 转载请注明链接:sumile.cn » 一个简单的爬虫—电影天堂爬虫

喜欢 (2)
发表我的评论
取消评论
表情

如需邮件形式接收回复,请注册登录

Hi,你需要填写昵称和邮箱~

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址