apispider.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #-*-coding:utf-8-*-
  2. #支持中文必须加上上面一句话
  3. __author__ = 'Administrator'
  4. import scrapy
  5. #正则表达式模块
  6. import re
  7. #包含scrapy中的Request请求,在yield request中用到
  8. from scrapy.http import Request
  9. #引入将要保存到数据库的类名称
  10. from ApiCrawler.items import ApiItem
  11. class ApiSpider(scrapy.spiders.Spider):
  12. name = "api"
  13. #只爬api.1473.cn网址
  14. allowed_domains=["api.1473.cn"]
  15. #开始爬的网址
  16. start_urls=[
  17. "http://api.1473.cn"
  18. ]
  19. #目的是去除重复的url。
  20. URLS=[]
  21. #计数,一共爬了多少次
  22. count=0
  23. def parse(self, response):
  24. #allUrl=response.url
  25. #print allUrl
  26. #从response中获取内容,保存到数据库,为什么能保存到数据库呢?应该是架构写好的。
  27. #extract方法返回unicode字符串
  28. apiItem=ApiItem()
  29. apiItem['url'] = response.url
  30. # normalize-space 解决xpath取出的title值有很多回车空格的问题
  31. #text()函数获取标签下面的文本
  32. _titles=response.xpath(' normalize-space(/html/head/title/text())')
  33. if _titles:
  34. apiItem['title'] =_titles[0].extract()
  35. else:
  36. apiItem['title'] =""
  37. #获取meta中的content比较麻烦,国内居然没有资料。
  38. _keywords=response.xpath("//meta[@name='keywords']/@content")
  39. if _keywords:
  40. apiItem['keywords'] = _keywords[0].extract()
  41. else:
  42. apiItem['keywords'] = ""
  43. _description=response.xpath("//meta[@name='description']/@content")
  44. if _description:
  45. apiItem['description'] = _description[0].extract()
  46. else:
  47. apiItem['description']=""
  48. #首先获取body标签,然后再获取body标签中的所有字符串,为节约代码,下面使用三元操作符号,不熟悉的学生去学习一下三元
  49. #python的三元比较奇葩,估计是不入流程序员写的,h = "变量1" if a>b else "变量2"
  50. #_content=response.xpath('/html/body').xpath('string(.)').extract()[0];
  51. #_content=response.xpath('/html/body').xpath('string(.)')
  52. #获取类名为book的div中的内容
  53. _content=response.xpath("//div[@class='book']").xpath('string(.)')
  54. apiItem['content']=_content[0].extract() if _content else ""
  55. #作者信息
  56. _author=response.xpath("//pre[@class='authors']").xpath('string(.)')
  57. apiItem['author']=_author[0].extract() if _author else ""
  58. yield apiItem
  59. '''
  60. # 下面的正则会提取页面中所有的后缀名为.aspx,.html .htm的超级链接,然后循环递归,但此方法会忽略掉没有"http://"前缀的网页
  61. pattern=re.compile(r'((((https|http):\/\/)|\/)[0-9a-zA-Z\/\.@-_%]*?\.(aspx|html|htm))')
  62. urls=pattern.findall(response.text)
  63. for url in urls:
  64. #去除重复
  65. findUrl=url[0]
  66. if findUrl in self.URLS:
  67. continue
  68. else:
  69. self.URLS.append(findUrl)
  70. #Request对象需要包含from scrapy.http import Request
  71. #递归获取
  72. yield Request(findUrl,callback=self.parse)
  73. '''
  74. #域名中不能带下划线,否则爬虫不爬取,html标准中域名不能带下划线
  75. #下面的会把a标签中的所有超级链接截取出来。得到的结果为一个selectorlist类型,结果更加准确。
  76. _hrefs=response.xpath('//a/@href')
  77. for href in _hrefs:
  78. #获取a标签中的超级链接
  79. _findurl=href.extract()
  80. #http://api.1473.cn/DevelopInterfaces/1473/common/index.aspx/common/606UploadFiles.aspx/common/600CommonIntroduces.aspx
  81. #结果会出现上面的重复累加的情况,再加一个判断试一试。这样有几率会误报
  82. #if response.url.find(_findurl) != -1:
  83. # continue
  84. #判断超级链接是否包含"http"字符串,如果没有包含,则添加浏览器路径拼凑成完整的url
  85. #if _findurl.find('http') == -1:
  86. # _findurl=response.url+'/'+_findurl
  87. #去除重复数据
  88. if _findurl in self.URLS:
  89. continue
  90. else:
  91. self.URLS.append(_findurl)
  92. #print _findurl;
  93. #Request对象需要包含from scrapy.http import Request
  94. #递归获取,response.urljoin(_findurl)会对没有http的网址进行拼凑。并且response.urljoin(_findurl)这个方法不会出现php_ref_misc.aspx带下划线的网址出错的问题,
  95. #具体报错情况为:ValueError('Missing scheme in request url: %s' % self._url)
  96. yield Request(response.urljoin(_findurl),callback=self.parse)
  97. #yield Request(_findurl,callback=self.parse)
  98. #filename=response.url.split("/")[2]
  99. #with open(filename,'wb') as f:
  100. # f.writable(response.body)