Quantcast
Channel: CodeSection,代码区,Python开发技术文章_教程 - CodeSec
Viewing all articles
Browse latest Browse all 9596

scrapy爬虫学习【一】之wooyun白帽子精华榜

$
0
0
1.分析 wooyun白帽子一共两千多名,白帽子信息的链接如下: wooyun白帽子 它分为精华榜,人气榜以及贡献榜;三个榜单数据是一样的,只是排名顺序不一样。这里选取 精华榜 作为数据来源。 精华榜的链接为 http://wooyun.org/whitehats/do/1/page/n 可提取信息为 注册日期 , 昵称 , 等级 , 精华漏洞数 , 精华比例 , wooyun主页 手动爬取 手动爬去需要将url全部写在start_urls里面,一共104页因此一共104个链接 自动爬取 start_urls里面只有一个链接,其它链接由程序自动获取 2.程序设计 2.1手动爬取 在items.py中定义Item容器
class WooyunRankItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() ''' 以下信息分别为 注册日期 woyun昵称 精华漏洞数 精华比例 wooyun个人主页 ''' register_date = scrapy.Field() nick_name= scrapy.Field() rank_level= scrapy.Field() essence_count = scrapy.Field() essence_ratio = scrapy.Field() homepage= scrapy.Field() 爬虫编写
#!/usr/bin/python# -*- coding:utf-8 -*- from scrapy.spidersimport Spider from scrapy.selectorimport Selector from wooyun_rank.itemsimport WooyunRankItem class WooyunSpider(Spider): ''' 爬取wooyun漏洞精华榜单 ''' name = "wooyunrank" #爬取速度为1s download_delay = 5 allowed_domains = ["wooyun.org"] start_urls = list() for pagein xrange(1,100): start_urls.append("http://wooyun.org/whitehats/do/1/page/"+str(page)) def parse(self,response): sel = Selector(response) item = WooyunRankItem() infos = sel.xpath("/html/body/div[5]/table/tbody/tr") for infoin infos: ''' extract()提取出来的是列表,列表数据是unicode的编码 这里是一元数组,所以可以直接取第一个元素。 针对多元数组,则应该对内容进行重组 也可以按照如下方法首先就就行编码 urls = [url.encode('utf-8') for url in urls] python支持 print [url for url in urls]这样的语法 ''' item["register_date"] = info.xpath("th[1]/text()").extract()[0] item["rank_level"]= info.xpath("th[2]/text()").extract()[0] item["essence_count"] = info.xpath("th[3]/text()").extract()[0] item["essence_ratio"] = info.xpath("th[4]/text()").extract()[0] item["nick_name"]= info.xpath("td/a/text()").extract()[0] yield item pipelines.py编写(一)
import os import csv class WooyunRankPipeline(object): ''' process the item returned from the spider ''' def process_item(self, item, spider): if not os.path.exists("wooyunrank.csv"): with open("wooyunrank.csv","wb") as f: dict_writer = csv.DictWriter(f) dict_writer.writerow("register_date","nick_name","rank_level","essence_count","essence_ratio") f.close() with open("wooyunrank.csv","ab") as f: dict_writer = csv.DictWriter(f) dict_writer.writerow(item) f.close() return item 但是,上面这段代码会有一个明显的问题,那就是 资源争夺 ,导致文件无法打开! 虽然,上面的代码就算不产生资源争夺也是错误的!但是,这不是重点 。下面是改进的代码!
import os import csv class WooyunRankPipeline(object): ''' process the item returned from the spider ''' def __init__(self): file_obj = open("wooyunrank.csv","wb") fieldnames = ["register_date","nick_name","rank_level","essence_count","essence_ratio"] self.dict_writer = csv.DictWriter(file_obj,fieldnames=fieldnames) self.dict_writer.writeheader() def process_item(self,item,spider): self.dict_writer.writerow(item) return item 2.2自动爬取 spider.py的编写
#!/usr/bin/python# -*- coding:utf-8 -*- import sys from scrapy.spiderimport Spider from scrapy.selectorimport Selector from wooyunrankauto.itemsimport WooyunrankautoItem from scrapy.contrib.spidersimport CrawlSpider,Rule from scrapy.contrib.linkextractorsimport LinkExtractor class WooyunSpider(CrawlSpider): ''' 爬取wooyun漏洞精华榜单 ''' name = "wooyunrankauto" # 爬取速度为1s download_delay = 1 allowed_domains = ["wooyun.org"] start_urls = [ "http://wooyun.org/whitehats/do/1/page/1" ] rules=[ Rule(LinkExtractor(allow=("/whitehats/do/1/page/\d+")),follow=True,callback='parse_item') ] # def __init__(self): # reload(sys) # if sys.getdefaultencoding()!="utf-8": # sys.setdefaultencoding("utf-8") def parse_item(self,response): sel = Selector(response) item = WooyunrankautoItem() infos = sel.xpath("/html/body/div[5]/table/tbody/tr") for infoin infos: ''' extract()提取出来的是列表,列表数据是unicode的编码 这里是一元数组,所以可以直接取第一个元素。 针对多元数组,则应该对内容进行重组 也可以按照如下方法首先就就行编码 urls = [url.encode('utf-8') for url in urls] python支持 print [url for url in urls]这样的语法 ''' item["register_date"] = info.xpath("th[1]/text()").extract()[0] item["rank_level"]= info.xpath("th[2]/text()").extract()[0] item["essence_count"] = info.xpath("th[3]/text()").extract()[0] item["essence_ratio"] = info.xpath("th[4]/text()").extract()[0] item["nick_name"]= info.xpath("td/a/text()").extract()[0] return item # yield item 这里会出现一个问题,如果使用 return item 很明显, 只会出现每个页面只有一条个人信息返回,但是会将所有的页面都爬去一次 。 如果使用 yield item , 页面的所有信息都会被抓取,但是只会爬去几个页面!!! 这里的解决方法,可以将获取到的 itme["xxx"] 整个数组传递过去,在 pipelines.py 中进行数据处理! 3.待解决问题 在写入文件的时候,如何每次都打开文件会导致 资源争夺 ;如果持续打开文件不关闭,会导致 资源占用 。有没有折中的方法 上述的自动爬取问题暂时并没有解决方法! 猜测是爬取与跟进页面属于同一表达式? 4.注意事项 编写完pipeline后,为了启动它必须修改setting.py中ITEM_PIPLINES的配置 设置download_delay减轻服务器负载,防止被ban 如果需要对文件的编码进行处理,请在pipelines.py中进行 。最好不要重写构造函数!在自己不了解的情况下!!!

参考文献1

参考文献2

Viewing all articles
Browse latest Browse all 9596

Trending Articles