3.3 spider目录下的sohu.py:编写提取数据的Spider
3.4 pipelines.py:将爬取后的item数据进行存储
Scrapy 是一套用 python 编写的异步爬虫框架,基于 twisted 实现,运行于 linux/windows/macOS 等多种环境,具有速度快、扩展性强、使用简便等特点。
Scrapy 可以在本地运行,也能部署到云端(scrapyd)实现真正的生产级数据采集系统。
可以使用命令行来新建一个爬虫工程,这个工程会自动按照scrapy的结构创建一个工程目录。
1)在e盘下新建一个目录:scrapy_crawler
2)在cmd进入目录:scrapy_crawler,然后执行scrapy startproject tutorial(给工程起名为tutorial),执行后会在scrapy_crawler创建好爬虫的工程,目录名为:tutorial
3)进入 tutorial 目录,执行命令:scrapy genspider sohu www.sohu.com(给爬虫文件起名,并设定种子URL)
以上三步执行完毕,则工程的框架建立完毕。后续需要你自己实现爬虫分析和保存的逻辑。目录结构如下图:
1 BOT_NAME = 'tutorial'
2
3
4
5 SPIDER_MODULES = ['tutorial.spiders']
6
7 NEWSPIDER_MODULE = 'tutorial.spiders'
8
9
10
11 ROBOTSTXT_OBEY = False # 若抓不到东西,就设置为True
12
13
14 # 取消下述注释行
15 ITEM_PIPELINES = {
16
17 'tutorial.pipelines.TutorialPipeline': 300,
18
19 }
# CONCURRENT_REQUESTS_PER_DOMAIN = 16 # 每个域名,同时并发的请求次数限制
# CONCURRENT_REQUESTS_PER_IP = 16 # 每个IP,同时并发的请求次数限制
# CONCURRENT_REQUESTS = 32 # 框架最大的并发请求数量,针对多个域名和多个ip的一个并发请求上限
1 # Define here the models for your scraped items
2
3 #
4
5 # See documentation in:
6
7 # https://docs.scrapy.org/en/latest/topics/items.html
8
9
10 import scrapy
11
12
13 class TutorialItem(scrapy.Item):
14
15 # define the fields for your item here like:
16
17 # name = scrapy.Field()
18
19 URL = scrapy.Field() # 存放当前网页地址
20
21 TITLE = scrapy.Field() # 存放当前网页title,格式类似于:
拿到每个网页的页面源码
拿到网页源码中的url
把网页源码中要的4个数据都存到一个类似字典格式的字符串
把抓取的结果发给pipelines做持久化
把新获取的url通过递归的方式,进行抓取
1 import scrapy
2 import re,os
3 from tutorial.items import TutorialItem
4 from scrapy import Request
5
6
7 class SohuSpider(scrapy.Spider):
8
9 name = 'sohu' # 项目名称
10 # allowed_domains = ['www.sohu.com'] # 如果指定爬虫作用范围,则作用于首页之后的页面
11 start_urls = ['http://www.sohu.com/'] # 开始url
12
13 def parse(self, response):
14 # response:网页源码对象
15 # 从源码对象中获取/html下的所有标签内容,拿到了所有网页的源码
16 all_urls = re.findall('href="(.*?)"',response.xpath("/html").extract_first())
17 for url in all_urls:
18 # 每生成这个对象,就可以存储一组4个数据
19 item = TutorialItem()
20 if re.findall("(\.jpg)|(\.jpeg)|(\.gif)|(\.ico)|(\.png)|(\.js)|(\.css)$",url.strip()):
21 pass # 去掉无效链接
22 elif url.strip().startswith("http") or url.strip().startswith("//"):
23 temp_url = url.strip() if url.strip().startswith('http') else 'http:' + url.strip() # 三目运算符获取完整网址
24 item = self.get_all(item,response)
25 # 判断item中存在正文且不为空,页面一级标题不为空
26 if 'TEXT' in item and item['TEXT'] != '' and item['TITLE'] != '':
27 yield item # 发送到管道
28 print('发送<' + temp_url + '>到下载器') # 提示
29 yield Request(temp_url,callback=self.parse) # 递归调用,实现了不断使用新的url进行下载
30
31 # 自定义封装的方法:从网页中提取4个要爬取的内容放到类似字典item的里面
32 def get_all(self,item,response):
33 # 获取当前页面的网址、title、一级标题、正文内容
34 item['URL'] = response.url.strip()
35 item['TITLE'] = response.xpath('/html/head/title/text()').extract()[0].strip()
36 contain_h1 = response.xpath('//h1/text()').extract() # 获取当前网页所有一级标题
37 contain= contain_h1[0] if len(contain_h1) !=0 else "" # 获取第一个一级标题
38 item["H1"] = contain.strip()
39 main_text = []
40 # 遍历网页中所有p标签和br标签的内容
41 for tag in ['p','br']:
42 sub_text = self.get_content(response,tag)
43 main_text.extend(sub_text)
44 # 对正文内容去重并判断不为空
45 main_text = list(set(main_text))
46 if len(main_text) != 0:
47 item['TEXT'] = '\n'.join(main_text)
48 return item
49
50 def get_content(self,response,tag):
51 # 判断只有大于100个文字的内容才保留
52 main_text = []
53 contexts = response.xpath('//'+tag+'/text()').extract()
54 for text in contexts:
55 if len(text.strip()) > 100:
56 main_text.append(text.strip())
57 return main_text
1 # Define your item pipelines here
2
3 #
4
5 # Don't forget to add your pipeline to the ITEM_PIPELINES setting
6
7 # See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
8
9 import json
10
11
12 class TutorialPipeline(object):
13
14 def __init__(self):
15 # 存爬取数据的文件句柄
16 self.filename = open("content.txt",'w',encoding="utf-8")
17 # 集合对象,用于去重爬取数据
18 self.contain = set()
19
20 # 数据怎么存
21 def process_item(self, item, spider):
22 # item:爬取来的数据
23 # 抓取后的数据,包含中文的话,可以直接看到正文。等价于text= str(item)
24 text = json.dumps(dict(item),ensure_ascii=False) + '\n'
25 # 把json串转换为字典
26 text_dict = eval(text)
27 # 用字典去取数据
28 if text_dict['URL'] not in self.contain: # 抓取到新网页,并写入文件
29 # 判断url是否被抓取过,如果没有被抓取过,就存到文件里面
30 for _,targetName in text_dict.items():
31 # 实现存储数据的逻辑
32 # 网页正文包含“人”才会保存,
33 # “人”是我们想抓取页面的核心关键词,可以换成其它关键词
34 if "人" in targetName:
35 # 有的话,把这个字典写到文件里面
36 self.write_to_txt(text_dict)
37 # 避免重复写入
38 break
39 # 每次记录文件后把网页url写入集合,重复的url会自动过滤掉
40 self.contain.add(text_dict['URL'])
41 # 表示item处理完了
42 return item
43
44
45 # 爬虫关掉时,把文件关掉
46 def close_spider(self,spider):
47 self.filename.close()
48
49 # 具体把字典写入到文件的方法
50 def write_to_txt(self,text_dict):
51
52 # 把抓取到的内容写入文件中
53 for key,value in text_dict.items():
54 self.filename.write(key+"内容:\n"+value+'\n')
55 self.filename.write(50*'='+'\n')
Item 在 Spider 中被收集之后,它将会被传递到 Item Pipeline,一些组件会按照一定的顺序执行对 Item 的处理。
每个 Item Pipeline 组件(有时称之为“Item Pipeline”)是实现了简单方法的 python 类。他们接收到 Item 并通过它执行一些行为,同时也决定此 Item 是否继续通过 Pipeline,或是被丢弃而不再进行处理。
Item Pipeline 的一些典型应用:
每个 item pipiline 组件是一个独立的 python 类,同时必须实现以下方法:
每个item pipeline组件都需要调用该方法,这个方法必须返回一个 Item(或任何继承类)对象, 或是抛出 DropItem 异常,被丢弃的 item 将不会被之后的 pipeline 组件所处理。
当 spider 被开启时,这个方法被调用。
当 spider 被关闭时,这个方法被调用。
方式一 指定json文件输出:scrapy crawl sohu -o items.json
方式二 根据pipelines.py定义输出:scrapy crawl sohu
例:E:\tutorial无限制爬取\tutorial>scrapy crawl sohu
手机扫一扫
移动阅读更方便
你可能感兴趣的文章