使用Scrapy抓取网站需要四个步骤:
- 创建Scrapy项目
- 定义Item容器
- 编写爬虫
- 存储内容
1.创建项目
C:\Users\fly_dragon\Desktop>scrapy startproject Dmoz
New Scrapy project 'Dmoz', using template directory 'c:\d_disk\anaconda3\lib\site-packages\scrapy\templates\project', created in:
C:\Users\fly_dragon\Desktop\Dmoz
You can start your first spider with:
cd Dmoz
scrapy genspider example example.com
C:\Users\fly_dragon\Desktop>
该命令将会创建包含下列内容的scrapyspider目录:
scrapyspider/
scrapy.cfg
scrapyspider/
__init__.py
items.py
pipelines.py
settings.py
spiders/
__init__.py
...
这些文件分别是
-
scrapy.cfg: 项目的配置文件。
-
scrapyspider/: 该项目的python模块。之后您将在此加入代码。
-
scrapyspider/items.py: 项目中的item文件。
-
scrapyspider/pipelines.py: 项目中的pipelines文件。
-
scrapyspider/settings.py: 项目的设置文件。
-
scrapyspider/spiders/: 放置spider代码的目录。
2.Item容器
Item是保存爬取到的数据的容器,其使用方法和py字典类似,并且提供了额外保护机制来避免拼写错误导致的未定义字段错误。
# -*- coding: utf-8 -*-
# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html
import scrapy
class DmozItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
title = scrapy.Field()
link = scrapy.Field()
desc = scrapy.Field()
3.编写爬虫
编写爬虫类Spider,Spider是用户编写用于从网上爬取数据的类。
其包含了一个用于可以下载的初始URL,然后是如何跟进网页中的链接以及如何分析页面的内容,还有提取生成Item的方法。
# dmoz_spider.py
import scrapy
class DmozSpider(scrapy.Spider):
name = "dmoz1" # 不能重复,是爬虫的名字
allowed_domains = ['dmoz-odp.org']
start_urls = [
'https://dmoz-odp.org/Games/Puzzles/',
'https://dmoz-odp.org/Games/Puzzles/Brain_Teasers/'
]
def parse(self, response):
fileName = response.url.split("/")[-2]
# 保存html文件到目录下
with open(fileName, 'wb') as f:
f.write(response.body)
4.寻找、存储内容
在Scrapy中使用基于XPath和CSS的表达式机制:
Scrapy Selectors
有4个基本方法:
- xpath():
- css():
- extract():
- re:
XPath
XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言。
XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力。起初XPath的提出的初衷是将其作为一个通用的、介于XPointer与XSL间的语法模型。但是XPath很快的被开发者采用来当作小型查询语言。
实际操作
C:\Users\fly_dragon\Desktop\Dmoz>scrapy shell "https://dmoz-odp.org/Games/Puzzles/"
进入scrapy shell
[s] Available Scrapy objects:
[s] scrapy scrapy module (contains scrapy.Request, scrapy.Selector, etc)
[s] crawler <scrapy.crawler.Crawler object at 0x000001F091DB55F8>
[s] item {}
[s] request <GET https://dmoz-odp.org/Games/Puzzles/>
[s] response <200 https://dmoz-odp.org/Games/Puzzles/>
[s] settings <scrapy.settings.Settings object at 0x000001F093105828>
[s] spider <DmozSpider 'dmoz1' at 0x1f093442748>
[s] Useful shortcuts:
[s] fetch(url[, redirect=True]) Fetch URL and update local objects (by default, redirects are followed)
[s] fetch(req) Fetch a scrapy.Request and update local objects
[s] shelp() Shell help (print this help)
[s] view(response) View response in a browser
举例:response.body是网页源代码,response.headers是网页头。
Xpath简介
接下来就是大浪淘沙,这里使用XPath:
/html/head/title: 选择html文档中的<head>标签内的<title>元素。
/html/head/title/text(): 选择html文档中的<head>标签内的<title>元素的文字。
//td: 选择所有的<td>元素
//div[@class = "mine"]: 选择所有具有class = "mine"属性的div元素。
这里resopnse.xpath() == resopnse.selector.xpath()
response.xpath('//title') # '//'表示选出网页中所有该标签的元素
In [3]: response.xpath('//title')
Out[3]: [<Selector xpath='//title' data='<title>DMOZ - Games: Puzzles</title>'>]
In [4]: response.xpath('//title').extract()
Out[4]: ['<title>DMOZ - Games: Puzzles</title>']
In [5]: response.xpath('//title/text()').extract() # 得到字符串(text())
Out[5]: ['DMOZ - Games: Puzzles']
In [24]: sites = response.xpath('//div[@class="title-and-desc"]')
In [15]: for site in sites:
...: title = site.xpath('a/div/text()').extract()
...: link = site.xpath('a/@href').extract()
...: desc = site.xpath('div/text()').extract()
...: print("数据:", title, link, desc)
...:
In [5]: exit() # 退出shell
查找需要的元素
这里我真的踩了好久的坑,xpath直接审查元素复制是:
//*[@id="site-list-content"]/div/div
这样会把很多其它的东西查找进去,必须进行修改:
sites = response.xpath('//div[@class="title-and-desc"]')
这个才是真正查找到的
修改DmozSpider爬虫类
使用Item存储爬取的信息,需要导入Dmoz.items
# dmoz_spider.py
import scrapy
from Dmoz.items import DmozItem
class DmozSpider(scrapy.Spider):
name = "dmoz1" # 不能重复,是爬虫的名字
allowed_domains = ['dmoz-odp.org']
start_urls = [
'https://dmoz-odp.org/Games/Puzzles/',
'https://dmoz-odp.org/Games/Puzzles/Brain_Teasers/'
]
def parse(self, response):
sites = response.xpath('//div[@class="title-and-desc"]')
items = []
for site in sites:
item = DmozItem() # 初始化一个DmozItem字典
item['title'] = site.xpath('a/div/text()').extract()[0]
item['link'] = site.xpath('a/@href').extract()[0]
item['desc'] = site.xpath('div/text()').extract()[0]
item['desc'] = item['desc'].strip("\r\n\t ") # 移除首尾\r\n\t 字符
items.append(item)
return items
保存信息
cmd下,这里保存成json文件。
C:\Users\fly_dragon\Desktop\Dmoz>scrapy crawl dmoz1 -o items.json -t json