1.創(chuàng)建爬蟲項(xiàng)目
scrapy startproject jobboleproject
2.新建爬蟲文件
scrapy genspider jobbole jobbole.com
3.item.py文件
class JobboleItem(scrapy.Item):
# define the fields for your item here like:
#標(biāo)題
title = scrapy.Field()
#創(chuàng)建時(shí)間
create_date = scrapy.Field()
#文章地址
url = scrapy.Field()
#id
url_object_id = scrapy.Field()
#文章圖片
front_image_url = scrapy.Field()
#文章圖片地址
front_image_path = scrapy.Field()
# 點(diǎn)贊數(shù)
praise_nums = scrapy.Field()
#收藏?cái)?shù)
bookmark_nums = scrapy.Field()
# 評論數(shù)
comment_nums = scrapy.Field()
#文章內(nèi)容
content = scrapy.Field()
#標(biāo)簽
tags = scrapy.Field()
4.打開 jobboleproject/spider目錄里的 jobbole.py,默認(rèn)增加了下列代碼:
# -*- coding: utf-8 -*-
import scrapy
class JobboleSpider(scrapy.Spider):
name = 'jobbole'
allowed_domains = ['jobbole.com']
start_urls = ['http://blog.jobbole.com/all-posts/']
def parse(self, response):
pass
5.將start_urls(設(shè)置起始url)的值修改為需要爬取的第一個(gè)url
start_urls = ("http://blog.jobbole.com/all-posts/",)
在parse方法中做數(shù)據(jù)的提取
from jobboleproject.items import JobboleprojectItem
6.獲取圖片和文章詳情的鏈接
def parse(self, response):
# css選擇器獲取當(dāng)前列表頁面的所有的節(jié)點(diǎn)
post_nodes = response.css("#archive .floated-thumb .post-thumb a")
# 如果不是完整的域名 需要拼接完整 response.url + post_url
# 獲取到的URL可能不是一個(gè)域名,也可能是具體的文章需要使用parse函數(shù)from urllib import parse
for post_node in post_nodes:
image_url = post_node.css("img::attr(src)").extract_first("")
post_url = post_node.css("::attr(href)").extract_first("")
full_url = response.urljoin(post_url)
#meta參數(shù)對應(yīng)的是一個(gè)字典,用來傳遞數(shù)據(jù)
yield scrapy.Request(url=full_url, meta={"front_image_url": image_url},
callback=self.parse_detail)
7.然后將我們得到的數(shù)據(jù)封裝到一個(gè) JobboleItem 對象中骂束,可以保存每個(gè)文章的屬性:
def parse_detail(self,response):
# print(response)
# 使用xpath語法或者css語法提取網(wǎng)頁的相關(guān)信息
# extract() 串行化并將匹配到的節(jié)點(diǎn)返回一個(gè)unicode字符串列表
item = JobboleprojectItem()
#標(biāo)題
item['title'] = response.xpath('//div[@class="entry-header"]/h1/text()').extract_frist("")
#發(fā)布日期
item['create_date'] = response.xpath("http://p[@class='entry-meta-hide-on-mobile']/text()").extract_first("").strip().replace("·","").strip()
#文章地址詳情地址
item['url'] = response.url
# http://blog.jobbole.com/113949/
#文章的id
item['url_object_id'] = re.match(".*?(\d+).*", url).group(1)
# 文章圖片
item['front_image_url'] = response.meta.get("front_image_url","")
# 點(diǎn)贊數(shù)
item['praise_nums'] = response.xpath("http://span[contains(@class,'vote-post-up')]/h10/text()").extract_first("")
# 收藏?cái)?shù)
bookmark_nums = response.xpath("http://span[contains(@class,'bookmark-btn')]/text()").extract_first("")
match_bookmark_nums = re.match(".*?(\d+).*",bookmark_nums)
if match_bookmark_nums:
item['bookmark_nums'] = int(match_bookmark_nums.group(1))
else:
item['bookmark_nums'] = 0
# 評論數(shù)
comment_nums = response.xpath("http://a[@href='#article-comment']/span/text()").extract_first("")
match_comment_nums = re.match(".*?(\d+).*",comment_nums)
if match_comment_nums:
item['comment_nums'] = int(match_comment_nums.group(1))
else:
item['comment_nums'] = 0
# 文章內(nèi)容
item['content'] = response.xpath("http://div[@class='entry']").extract_first("")
# 過濾評論標(biāo)簽
tag_list = response.xpath("http://p[@class='entry-meta-hide-on-mobile']//a/text()").extract()
tag_list = [element for element in tag_list if not element.strip().endswith("評論")]
# 標(biāo)簽
item['tags'] = ",".join(tag_list)
print(item)
# return返回?cái)?shù)據(jù),不經(jīng)過pipelines
# return item
# yield將獲取的數(shù)據(jù)交給pipelines
# yield item
8. jobbole.py文件
name = "" :這個(gè)爬蟲的識別名稱,必須是唯一的顶考,在不同的爬蟲必須定義不同的名字。
allow_domains = [] 是搜索的域名范圍妖泄,也就是爬蟲的約束區(qū)域驹沿,規(guī)定爬蟲只爬取這個(gè)域名下的網(wǎng)頁,不存在的URL會(huì)被忽略蹈胡。
start_urls = () :爬取的URL元祖/列表渊季。爬蟲從這里開始抓取數(shù)據(jù),所以罚渐,第一次下載的數(shù)據(jù)將會(huì)從這些urls開始却汉。其他子URL將會(huì)從這些起始URL中繼承性生成。
parse(self, response) :解析的方法搅轿,每個(gè)初始URL完成下載后將被調(diào)用病涨,調(diào)用的時(shí)候傳入從每一個(gè)URL傳回的Response對象來作為唯一參數(shù),主要作用如下:
負(fù)責(zé)解析返回的網(wǎng)頁數(shù)據(jù)(response.body)璧坟,提取結(jié)構(gòu)化數(shù)據(jù)(生成item)
生成需要下一頁的URL請求既穆。
9.根據(jù)目標(biāo)網(wǎng)站分析需要提取的數(shù)據(jù),在item.py文件中添加字段
打開jobboleproject文件下的item.py文件
Item 定義結(jié)構(gòu)化數(shù)據(jù)字段雀鹃,用來保存爬取到的數(shù)據(jù)幻工,有點(diǎn)像Python中的dict,但是提供了一些額外的保護(hù)減少錯(cuò)誤黎茎。
可以通過創(chuàng)建一個(gè) scrapy.Item 類囊颅, 并且定義類型為 scrapy.Field的類屬性來定義一個(gè)Item(可以理解成類似于ORM的映射關(guān)系)。
接下來傅瞻,創(chuàng)建一個(gè)JobboleprojectItem 類踢代,和構(gòu)建item模型(model)。
10.關(guān)于yeild函數(shù)介紹:
簡單地講嗅骄,yield 的作用就是把一個(gè)函數(shù)變成一個(gè) generator(生成器)胳挎,帶有 yield 的函數(shù)不再是一個(gè)普通函數(shù),Python 解釋器會(huì)將其視為一個(gè) generator溺森,帶有yeild的函數(shù)遇到y(tǒng)eild的時(shí)候就返回一個(gè)迭代值慕爬,下次迭代時(shí)窑眯, 代碼從 yield 的下一條語句繼續(xù)執(zhí)行,而函數(shù)的本地變量看起來和上次中斷執(zhí)行前是完全一樣的医窿,于是函數(shù)繼續(xù)執(zhí)行磅甩, 直到再次遇到 yield。