一个简单的爬虫—电影天堂爬虫 – 热爱改变生活
我的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 7138℃ 0评论

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

安装并创建 scrapy 项目

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

  1. scrapy startproject dmoz

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

找到或创建爬虫代码文件

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

编写爬虫代码

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

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

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

  1. hx = HtmlXPathSelector(response);
  2. title = hx.xpath("//title/text()").extract()
  3. sites = hx.xpath('//*[@id="Zoom"]//table//td')
  4. text = title
  5. try:
  6. textStr = str(text[0])
  7. except Exception as e:
  8. textStr = ""
  9. urlData = str(response.url)

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

  1. for sel in sites:
  2. urltext = [t.encode("utf-8") for t in sel.xpath('a/text()').extract()]
  3. url = [u.encode("utf-8") for u in sel.xpath('a/@href').extract()]
  4. # text = [d.encode("utf-8") for d in title]
  5.  
  6. try:
  7. urlStr = str(url[0])
  8. except Exception as e:
  9. urlStr = ""
  10.  
  11. try:
  12. urlTextStr = str(urltext[0])
  13. except Exception as e:
  14. urlTextStr=""

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

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

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

代码

  1. #!/usr/bin/python
  2. # -*- coding:utf-8 -*-
  3. from scrapy.spider import BaseSpider
  4. from scrapy.selector import HtmlXPathSelector
  5. from pengpai.items import PengpaiItem
  6. import urlparse
  7. from scrapy.http import Request
  8. import sys
  9. import codecs
  10. import MySQLdb
  11. import datetime
  12.  
  13. class DmozSpider(BaseSpider):
  14. name = "dmoz"
  15. allowed_domains = ["www.dytt8.net"]
  16. start_urls = [
  17. "http://www.dytt8.net/plus/sitemap.html"
  18. ]
  19. def toSql(self,dataStr):
  20. resultId = -1
  21. db = MySQLdb.connect("dburl","zhanghao","mima","dbname")
  22. cursor = db.cursor()
  23. cursor.execute("SET NAMES utf8")
  24. cursor.execute("SELECT VERSION()")
  25. try:
  26. cursor.execute(dataStr)
  27. resultId = int(db.insert_id())
  28. db.commit()
  29. except:
  30. db.rollback()
  31. db.close()
  32. return resultId
  33. def parse(self, response):
  34. reload(sys)
  35. sys.setdefaultencoding('utf-8')
  36. hx = HtmlXPathSelector(response)
  37. hrefs = hx.xpath("//a/@href")
  38. for href in hrefs:
  39. if href.extract().find('http')==0:
  40. url = href.extract()
  41. else:
  42. url = urlparse.urljoin(response.url, href.extract())
  43. yield Request(url, callback=self.parse_dir_contents)
  44. # file_object.close( )
  45.  
  46. def parse_dir_contents(self, response):
  47. hx = HtmlXPathSelector(response);
  48. title = hx.xpath("//title/text()").extract()
  49. sites = hx.xpath('//*[@id="Zoom"]//table//td')
  50. text = title
  51. try:
  52. textStr = str(text[0])
  53. except Exception as e:
  54. textStr = ""
  55. urlData = str(response.url)
  56. resultfile = codecs.open('result.txt','a',"utf-8")
  57. if(len(sites)>0):
  58. print(str(len(sites))+"=="+str(response.url))
  59. #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')
  60. 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;"
  61. # file_object = codecs.open('thefile.txt', 'a',"utf-8")
  62. resultIDBack = self.toSql(movie_name)
  63. resultfile.write(movie_name)
  64. resultfile.write('\n')
  65. for sel in sites:
  66. urltext = [t.encode("utf-8") for t in sel.xpath('a/text()').extract()]
  67. url = [u.encode("utf-8") for u in sel.xpath('a/@href').extract()]
  68. # text = [d.encode("utf-8") for d in title]
  69.  
  70. try:
  71. urlStr = str(url[0])
  72. except Exception as e:
  73. urlStr = ""
  74.  
  75. try:
  76. urlTextStr = str(urltext[0])
  77. except Exception as e:
  78. urlTextStr=""
  79.  
  80. dt=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
  81. #data = "insert into movie (movie.`name`,movie.url,movie.urltext,movie.`from`) values (\""+textStr+"\",\""+urlStr+"\",\""+urlTextStr+"\",\""+urlData+"\");"
  82. #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;
  83. #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;
  84. 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;"
  85. # file_object.write("["+str(text[0])+"] 已添加..")
  86. # file_object.write('\n')
  87. resultfile.write(data)
  88. resultfile.write('\n')
  89. #print(data)
  90. self.toSql(data)
  91. hrefs = hx.xpath("//a/@href")
  92. for href in hrefs:
  93. if href.extract().find('http')==0:
  94. url = href.extract()
  95. else:
  96. url = urlparse.urljoin(response.url, href.extract())
  97. yield Request(url, callback=self.parse_dir_contents)
  98. resultfile.close( )
  99. # file_object.close( )

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

  1. scrapy crawl dmoz

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

¥ 有帮助么?打赏一下~

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


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

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

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

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

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