---爬取伯樂在線所有文章---
1,scrapy安裝及目錄結(jié)構(gòu)介紹
- 電腦的基礎配置撩轰,需要的開發(fā)工具
1.python 3.5.3
2.PyCharm 2016.3
3.mysql+navicat for mysql
- 基礎虛擬環(huán)境的搭建和配置
pip install virtualenv
pip install virtualenvwrapper-win
安裝虛擬環(huán)境管理
mkvirtualenv article_spider
創(chuàng)建虛擬環(huán)境
workon articles_spider
直接進入虛擬環(huán)境
deactivate
退出激活狀態(tài)
workon
知道有哪些虛擬環(huán)境
- 命令行創(chuàng)建scrapy項目
pip install -i https://pypi.douban.com/simple/ scrapy
在虛擬環(huán)境下使用豆瓣源安裝scrapy
scrapy startproject articlespider
創(chuàng)建scrapy項目
- scrapy目錄結(jié)構(gòu)
scrapy.cfg
scrapy.cfg:配置文件. scrapy借鑒了django的項目思想
settings.py:關于scrapy的配置
SPIDER_MODULES = ['articlespider.spiders']#存放spiders的路徑
NEWSPIDER_MODULE = 'articlespider.spiders'
pipelines.py:做跟數(shù)據(jù)存儲相關的文件
middlewares.py:自己自定義middlewares,讓scrapy變得更加可控
items.py:定義數(shù)據(jù)保存的格式胯甩,保存我們所爬取到的數(shù)據(jù)
- 創(chuàng)建我們的spider: jobbole.py
workon article_spider
scrapy genspider jobbole blog.jobbole.com
可以看到直接為我們創(chuàng)建好的空項目里已經(jīng)有了模板代碼。如下:
# -*- coding: utf-8 -*-
import scrapy
class JobboleSpider(scrapy.Spider):#繼承scrapy.Spider
name = 'jobbole'
allowed_domains = ['blog.jobbole.com']#域名
start_urls = ['http://blog.jobbole.com/']#爬蟲爬取的起始url
def parse(self, response):#parse函數(shù)里面的邏輯是我們需要寫的東西
pass
- scrapy執(zhí)行流程
在命令行中啟動剛剛創(chuàng)建的spider:
(article_spider) D:\LinuxShare\articlespider>scrapy crawl jobbole
在windows報出錯誤:
ImportError: No module named 'win32api'
(article_spider) D:\LinuxShare\articlespider>pip install -i https://pypi.douban.com/simple pypiwin32
#安裝pypiwin32解決
創(chuàng)建我們的調(diào)試工具類:在項目根目錄里創(chuàng)建main.py作為調(diào)試工具文件
# _*_ coding: utf-8 _*_
from scrapy.cmdline import execute
import sys
import os
#將系統(tǒng)當前目錄設置為項目根目錄
os.path.abspath(__file__)#為當前文件所在絕對路徑-articlespider
os.path.dirname#為文件所在目錄-D:\LinuxShare\
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
#執(zhí)行命令堪嫂,相當于在控制臺cmd輸入改名了
execute(["scrapy", "crawl" , "jobbole"])#執(zhí)行命令scrapy crawl jobbole
settings.py里面的設置要不遵循reboots協(xié)議偎箫,防止scrapy過濾掉不符合reboots協(xié)議的url
# Obey robots.txt rules
ROBOTSTXT_OBEY = False
在jobble.py打上斷點:
def parse(self, response):
pass#打斷點處
可以看到返回的html的response對象:
對象內(nèi)部中的body是整個網(wǎng)頁源文件的內(nèi)容,而且scrapy幫我們做了編碼轉(zhuǎn)換為utf-8格式皆串。
DEFAULT_ENCODING={str}'ascii'
encoding={str}'utf-8'
2,提取伯樂在線內(nèi)容
- xpath的使用
為什么要使用xpath?
1.xpath使用路徑表達式在xml和html中進行導航
2.xpath包含一個標準函數(shù)庫
3.xpath是一個w3c標準
4.xpath速度快于beautifulsoup
xpath節(jié)點的關系:
1.父節(jié)點 2.子節(jié)點 3.同胞節(jié)點 4.先輩節(jié)點 5.后代節(jié)點
xpath語法:
獲取一個網(wǎng)頁上元素的xpath地址如:http://blog.jobbole.com/113722/
re_selector=response.xpath('//*[@id="post-113722"]/div[1]/h1/text()')
#獲取文章的標題
re_selector1=response.xpath('//div[@class="entry-header"]/h1/text()')
id型是比較精準的定位淹办,可以在Chrome源代碼中使用copy xpath直接復制
推薦使用class型,比較方便恶复,不過在書寫class型xpath是要查詢源代碼中是否有重復的class屬性值
在shell腳本中進行調(diào)試
(article_spider) D:\LinuxShare\articlespider>scrapy shell http://blog.jobbole.com/113722/
完整的xpath提取文章具體字段的代碼:
# -*- coding: utf-8 -*-
import scrapy
import re
class JobboleSpider(scrapy.Spider):
name = 'jobbole'
allowed_domains = ['blog.jobbole.com']
start_urls = ['http://blog.jobbole.com/113722/']
def parse(self, response):
#提取文章的具體字段
re_selector=response.xpath('//*[@id="post-113722"]/div[1]/h1/text()')
re_selector1=response.xpath('//div[@class="entry-header"]/h1/text()')
title=response.xpath('//div[@class="entry-header"]/h1/text()').extract_first("")
create_date= response.xpath("http://p[@class='entry-meta-hide-on-mobile']/text()").extract()[0].strip().replace("·","").strip()
praise_nums=response.xpath("http://span[contains(@class,'vote-post-up')]/h10/text()").extract()[0]
fav_nums=response.xpath("http://span[contains(@class,'bookmark-btn')]/text()").extract()[0]
match_re=re.match(".*?(\d+).*",fav_nums)#正則表達式匹配
if match_re:
fav_nums=int(match_re.group(1))
else:
fav_nums=0
comments_nums = response.xpath("http://a[@href='#article-comment']/span/text()").extract()[0]
match_re = re.match(".*?(\d+).*", comments_nums)
if match_re:
comments_nums = int(match_re.group(1))
else:
comments_nums=0
content=response.xpath("http://div[@class='entry']").extract()[0]#取全文內(nèi)容
create_date = response.xpath("http://p[@class='entry-meta-hide-on-mobile']/a/text()").extract()
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("評論")] # 去重“評論”
tags=",".join(tag_list)
- css選擇器的使用
css選擇器用于描述一組元素的樣式怜森,這里不做過多的介紹,通過css選擇器提取文章字段的代碼如下所示:
# -*- coding: utf-8 -*-
import scrapy
import re
class JobboleSpider(scrapy.Spider):
name = 'jobbole'
allowed_domains = ['blog.jobbole.com']
start_urls = ['http://blog.jobbole.com/113722/']
def parse(self, response):
#通過css選擇器提取字段
front_image_url=response.meta.get("front_image_url","")#文章封面圖
title=response.css(".entry-header h1::text").extract()[0]#::text 偽類選擇器
create_date=response.css("p.entry-meta-hide-on-mobile::text").extract()[0].strip().replace("·","").strip()
praise_nums=response.css(".vote-post-up h10::text").extract()[0]
fav_nums=response.css("span.bookmark-btn::text").extract()[0]
match_re = re.match(".*?(\d+).*", fav_nums)
if match_re:
fav_nums = int(match_re.group(1))
else:
fav_nums=0
comments_nums= response.css("a[href='#article-comment'] span::text").extract()[0]
match_re = re.match(".*?(\d+).*", comments_nums)
if match_re:
comments_nums = int(match_re.group(1))
else:
comments_nums=0
content=response.css("div.entry").extract()[0]
tag_list=response.css("p.entry-meta-hide-on-mobile a::text").extract()
tag_list = [element for element in tag_list if not element.strip().endswith("評論")] # 去重“評論”
tags = ",".join(tag_list)
3,編寫spider爬取jobbole的所有文章
- 解析列表頁中所有文章的url并交給scrapy下載進行解析
start_urls = ['http://blog.jobbole.com/all-posts/']
...
post_urls = response.css("#archive .floated-thumb .post-thumb a::attr(href)").extract()
- Request下載網(wǎng)頁
from scrapy.http import Request#把Request里面的url交給scrapy
...
Request(url=post_url,callback=self.parse_detail)
- parse函數(shù)完成url拼接防止出現(xiàn)href元素內(nèi)網(wǎng)址不全的情況
from urllib import parse#url可能出現(xiàn)無域名的情況寂玲,這時候引用函數(shù)parse
...
Request(url=parse.urljoin(response.url,post_url),callback=self.parse_detail)
- yield關鍵字
#使用request下載詳情頁面塔插,下載完成后回調(diào)方法parse_detail()提取文章內(nèi)容中的字段
yield Request(url=parse.urljoin(response.url,post_url),callback=self.parse_detail)
#yield關鍵字用于把Request提取到的內(nèi)容交給scrapy進行下載
- 提取“下一頁”的url
next_urls=response.css(".next.page-numbers::attr(href)").extract()[0]#next 和 page-numbers是兩個class,這樣表示這個節(jié)點有next和page
if next_urls:
yield Request(url=parse.urljoin(response.url,next_urls),callback=self.parse)
#注意callback=self.parse這里傳入parse函數(shù)并沒有進行調(diào)用
- 實現(xiàn)全部文章字段遍歷和解析的代碼如下:
def parse(self, response):
"""
1. 獲取文章列表頁中的文章url并交給scrapy下載后并進行解析
2. 獲取下一頁的url并交給scrapy進行下載, 下載完成后交給parse
"""
# 解析列表頁中的所有文章url并交給scrapy下載后并進行解析
post_urls = response.css("#archive .floated-thumb .post-thumb a::attr(href)").extract()
for post_url in post_urls:
#request下載完成之后拓哟,回調(diào)parse_detail進行文章詳情頁的解析
# Request(url=post_url,callback=self.parse_detail)
print(response.url)
print(post_url)
yield Request(url=parse.urljoin(response.url,post_url),callback=self.parse_detail)
#遇到href沒有域名的解決方案
#response.url + post_url
print(post_url)
# 提取下一頁并交給scrapy進行下載
next_url = response.css(".next.page-numbers::attr(href)").extract_first("")
if next_url:
yield Request(url=parse.urljoin(response.url, post_url), callback=self.parse)
- 全部文章字段解析和下載的邏輯流程圖:
4,scrapy的items整合字段
數(shù)據(jù)爬取的任務就是從非結(jié)構(gòu)的數(shù)據(jù)中提取出結(jié)構(gòu)性的數(shù)據(jù)伶授。
items 可以讓我們自定義返回自己所提取的字段(類似于字典断序,但比字典的功能更齊全),我們可以將實例化的items直接yield糜烹,這樣scrapy就可以幫我們把items路由到pipelines中违诗,方便這些字段數(shù)據(jù)集中在pipelines中的保存,去重等等獲取列表頁封面圖的url,并通過Request傳到response里面疮蹦,在文章詳情頁中可能沒有封面圖的url诸迟,所以要在下載網(wǎng)頁時把這個url獲取到,這里要用到Request里面的meta{}愕乎,meta在這里表示一個字典的樣式阵苇。
yield Request(url=parse.urljoin(response.url,post_url),meta={"front_image_url":image_url},callback=self.parse_detail)
front_image_url = response.meta.get("front_image_url", "")#或取文章封面圖
- url嵌套的方法
post_nodes=response.css("#archive .floated-thumb .post-thumb a")#提取文章列表的url后交給scrapy進行下載并進行解析
for post_node in post_nodes:
image_url=post_node.css("img::attr(src)").extract_first("")#post_nodes下的url中進行進一步的篩選
post_url=post_node.css("::attr(href)").extract_first("")#同image_url
yield Request(url=parse.urljoin(response.url, post_url), meta={"front_image_url": parse.urljoin(response.url, image_url)},
callback=self.parse_detail)
-
urljoin的好處:如果<img src="">里面沒有域名,那就取response.url感论,如果有域名就取post.url
urljoin.PNG 在items.py中編寫我們自定義的item:
class JobBolearticleItem(scrapy.Item):
title = scrapy.Field()
create_date = scrapy.Field()
url = scrapy.Field()
url_object_id = scrapy.Field()
front_image_url = scrapy.Field()
front_image_path = scrapy.Field()
praise_nums = scrapy.Field()
comments_nums = scrapy.Field()
fav_nums = scrapy.Field()
content = scrapy.Field()
tags = scrapy.Field()
- import之后實例化绅项,實例化之后填充:
1. from ArticleSpider.items import JobBolearticleItem
2. article_item = JobBolearticleItem()
3. article_item["title"] = title
article_item["url"] = response.url
article_item["create_date"] = create_date
article_item["front_image_url"] = [front_image_url]
article_item["praise_nums"] = praise_nums
article_item["comments_nums"] = comments_nums
article_item["fav_nums"] = fav_nums
article_item["tags"] = tags
article_item["content"] = content
yield article_item#將填充進來的item傳送到pipelines中
- 下載圖片:scrapy提供了自動下載圖片的機制,在settings.py里面設置好要下載圖片的pipeline比肄,數(shù)字越小表示越優(yōu)先進入快耿。
ITEM_PIPELINES={
'articlespider.pipelines.articleImagePipeline':300,
'scrapy.pipelines.images.ImagesPipeline':1,
}
- 新建文件夾images囊陡,圖片保存的相對路徑
IMAGES_URLS_FIELD = "front_image_url"#下載圖片的地址
project_dir = os.path.abspath(os.path.dirname(__file__))#通過os獲取當前文件所在的相對路徑
IMAGES_STORE = os.path.join(project_dir, 'images')#存放圖片的目錄,圖片的保存路徑
異常處理:ValueError和ImportError 解決辦法:front_image_url設置成數(shù)組格式掀亥,安裝pillow庫撞反。
自定義articleImagePipeline用來存放獲取的封面圖
from scrapy.pipelines.images import ImagesPipeline
...
class articleImagePipeline(ImagesPipeline):#繼承ImagesPipeline,只用來處理封面圖的自定義的pipeline搪花,
def item_completed(self,results,item,info):
pass
-
在函數(shù)item_completed下的result下的字典dict下獲取到圖片保存的地址path
path路徑.PNG 繼承ImagesPipeline并重寫item_completed痢畜,獲取到path
from scrapy.pipelines.images import ImagesPipeline
class articleImagePipeline(ImagesPipeline):
#重寫該方法可從result中獲取到圖片的實際下載地址
def item_completed(self, results, item, info):
for ok, value in results:
image_file_path = value["path"]
item["front_image_path"] = image_file_path
return item
- setting.py也要使用我們所自定義的pipeline,而不是用模塊自帶的
ITEM_PIPELINES = {
'articlespider.pipelines.ArticlespiderPipeline':300,
#'scrapy.pipelines.images.ImagesPipeline':1,
'articlespider.pipelines.articleImagePipeline':1,
}
- 圖片url的md5處理,,新建一個文件夾utils:
import hashlib#md5里面的url需要引進hashlib函數(shù)
#定義一個md5函數(shù)
def get_md5(url):
if isinstance(url,str):
url=url.encode("utf-8")#判斷url是否為unicode鳍侣,如果是丁稀,轉(zhuǎn)成encode
m=hashlib.md5()
m.update(url)
return m.hexdigest()
if __name__=="__main__":
print (get_md5("http://jobbole.com".encode("utf-8")))#python3里面的字符都是unicode格式的,而hashlib不支持unicode倚聚,所以要轉(zhuǎn)成encode
- 在jobbole.py中將md5保存下來
from articlespider.utils.common import get_md5
...
article_item["url_object_id"]=get_md5(response.url)
5线衫,數(shù)據(jù)保存到本地文件及mysql中
-
保存item到json文件中
import codecs使打開文件時避免了一些編碼問題,自定義JsonWithEncodingPipeline實現(xiàn)json文件本地保存
import codecs
...
class JsonWithEncodingPipeline(object):#繼承object
def __init__(self):#初始化的時候打開json文件
self.file=codecs.open('article.json','w',encoding="utf-8")#通過codecs方法寫入article.json
def process_item(self, item, spider):
lines=json.dumps(dict(item),ensure_ascii=False) + "\n"#把item寫入json當中惑折,item要轉(zhuǎn)換成dict才能dumps
self.file.write(lines)#寫入article.json當中
return item
def spider_closed(self,spider):#當出現(xiàn)spider_closed,關閉這個文件的寫入
self.file.close()
settings.py中注冊JsonWithEncodingPipeline:
ITEM_PIPELINES = {
'articlespider.pipelines.JsonWithEncodingPipeline':2,
#'scrapy.pipelines.images.ImagesPipeline':1,
'articlespider.pipelines.articleImagePipeline':1,
}
debug main.py文件發(fā)現(xiàn)生成了article.json文件
- 調(diào)用scrapy提供的json export導出json文件
from scrapy.exporters import JsonItemExporter
...
class JsonExporterPipleline(object):
#調(diào)用scrapy提供的json export導出json文件
def __init__(self):
self.file = open('articleexport.json', 'wb')
self.exporter = JsonItemExporter(self.file, encoding="utf-8", ensure_ascii=False)
self.exporter.start_exporting()
def close_spider(self, spider):
self.exporter.finish_exporting()
self.file.close()
def process_item(self, item, spider):
self.exporter.export_item(item)
return item
在settings.py中注冊JsonExporterPipleline:
ITEM_PIPELINES = {
'articlespider.pipelines.JsonExporterPipleline':2,
#'scrapy.pipelines.images.ImagesPipeline':1,
'articlespider.pipelines.articleImagePipeline':1,
}
debug main.py文件發(fā)現(xiàn)生成了articleexport.json文件
- 數(shù)據(jù)表設計
注意:三個num字段不能設置為空授账,默認值為零;
如果設置url_object_id為主鍵惨驶,則必須在代碼中進行插入操作白热。
- 通過pipeline保存數(shù)據(jù)到mysql
數(shù)據(jù)庫驅(qū)動安裝
pip install -i https://pypi.douban.com/simple/ mysqlclient
pipelines采用同步機制寫入mysql
import MySQLdb
...
class MysqlPipeline(object):
#采用同步的機制寫入mysql
def __init__(self):
self.conn = MySQLdb.connect('127.0.0.1', 'root', 'root', 'articlespider', charset="utf8", use_unicode=True)
self.cursor = self.conn.cursor()
def process_item(self, item, spider):
insert_sql = """
insert into jobbole_article(title, url, create_date, fav_nums,url_object_id)
VALUES (%s, %s, %s, %s,%s)
"""
self.cursor.execute(insert_sql, (item["title"], item["url"], item["create_date"], item["fav_nums"],item["url_object_id"]))
self.conn.commit()
pipelines采用異步機制寫入mysql
因為我們爬取網(wǎng)頁url的速度后期可能會大于數(shù)據(jù)庫存儲的速度,采用twisted框架可以讓我們數(shù)據(jù)庫的插入變成一種異步的操作粗卜。
在settings.py中設置可配置參數(shù):
MYSQL_HOST = "127.0.0.1"
MYSQL_DBNAME = "articlespider"
MYSQL_USER = "root"
MYSQL_PASSWORD = "root"
pipelines異步機制代碼:
from twisted.enterprise import adbapi#adbapi可以將mysqldb里面的一些操作變成異步化的操作
import MySQLdb.cursors
...
class MysqlTwistedPipeline(object):
def __init__(self, dbpool):#接收dbpool
self.dbpool = dbpool
@classmethod
def from_settings(cls,settings):#定義from_settings直接取settings中定義的值
dbparms = dict(#傳入的參數(shù)要和MySQLdb.connect里面的connection下面的參數(shù)一致
host=settings["MYSQL_HOST"],
db=settings["MYSQL_DBNAME"],
user=settings["MYSQL_USER"],
passwd=settings["MYSQL_PASSWORD"],
charset='utf8',
cursorclass=MySQLdb.cursors.DictCursor,
use_unicode=True,
)
dbpool = adbapi.ConnectionPool("MySQLdb", **dbparms)#這是一個連接池屋确,MYSQLdb是adbapi里面的dbapiName,**dbparms是要傳入的參數(shù)
return cls(dbpool)#返回一個實例
def process_item(self, item, spider):
# 使用twisted將mysql插入變成異步執(zhí)行
query = self.dbpool.runInteraction(self.do_insert, item)
query.addErrback(self.handle_error, item, spider) # 處理異常
def handle_error(self, failure, item, spider):
# 處理異步插入的異常
print(failure)
def do_insert(self, cursor,item):
insert_sql = """
insert into jobbole_article(title, url, create_date, fav_nums,url_object_id)
VALUES (%s, %s, %s, %s,%s)
"""
cursor.execute(insert_sql,
(item["title"], item["url"], item["create_date"], item["fav_nums"], item["url_object_id"]))
- scrapy提供的itemloader來提取字段
itemloader提供了一個容器续扔,讓我們配置提取字段的規(guī)則:
add_xpath,add_css,add_value
from scrapy.loader import ItemLoader
...
#通過Item Loader加載item攻臀,scrapy提供的提取字段的配置函數(shù)
front_image_url = response.meta.get("front_image_url", "") # 文章封面圖
item_loader=ArticleItemLoader(item=JobBolearticleItem(),response=response)#這里的ItemLoader要換成自定義的ArticleItemLoader
item_loader.add_css("title", ".entry-header h1::text")
item_loader.add_value("url", response.url)
item_loader.add_value("url_object_id", get_md5(response.url))
item_loader.add_css("create_date", "p.entry-meta-hide-on-mobile::text")
item_loader.add_value("front_image_url", [front_image_url])
item_loader.add_css("praise_nums", ".vote-post-up h10::text")
item_loader.add_css("comments_nums", "a[href='#article-comment'] span::text")
item_loader.add_css("fav_nums", ".bookmark-btn::text")
item_loader.add_css("tags", "p.entry-meta-hide-on-mobile a::text")
item_loader.add_css("content", "div.entry")
article_item = item_loader.load_item()
yield article_item#將填充進來的item傳送到pipelines中
會發(fā)現(xiàn)所有值變成了list,因此需要處理函數(shù)來對這些值進行過濾纱昧。
MapCompose可以傳入函數(shù)對于該字段進行處理刨啸,而且可以傳入多個:
from scrapy.loader.processors import MapCompose
def add_mtianyan(value):
return value+"-mtianyan"
title = scrapy.Field(
input_processor=MapCompose(lambda x:x+"mtianyan",add_mtianyan),
)
自定義ArticleItemLoader來取list里面的第一個值,類似于正則表達式里面的extract_first(""):
from scrapy.loader import ItemLoader#自定義的ArticleItemLoader需要繼承ItemLoader
...
class ArticleItemLoader(ItemLoader):
#自定義itemloader
default_output_processor = TakeFirst()#此函數(shù)用來取數(shù)組中的第一個數(shù)據(jù)识脆,但是是str類型
保存[front_image_url]的list值:
def return_value(value):#front_image_url調(diào)用
return value
...
class JobBolearticleItem(scrapy.Item):
front_image_url=scrapy.Field(
output_processor=MapCompose(return_value)#保證front_image_url里面的參數(shù)格式是list,,配置image pipeline之后设联,front_image_url傳入必須是list形式
)
去掉tags里面的“評論”:
from scrapy.loader.processors import MapCompose, TakeFirst, Join
...
def remove_comment_tags(value):
#去掉tag中提取的評論
if "評論" in value:
return ""
else:
return value
...
class ArticleItemLoader(ItemLoader):
tags=scrapy.Field(
input_processor=MapCompose(remove_comment_tags),#去掉tags中出現(xiàn)的評論
output_processor=Join(",")#使用join把字符串連接起來,原理同最開始的寫法
)
獲取nums:
def get_nums(value):
match_re = re.match(".*?(\d+).*", value)
if match_re:
nums = int(match_re.group(1))
else:
nums = 0
return nums
...
class ArticleItemLoader(ItemLoader):
praise_nums=scrapy.Field(
input_processor=MapCompose(get_nums)
)
comments_nums=scrapy.Field(
input_processor=MapCompose(get_nums)
)
fav_nums=scrapy.Field(
input_processor=MapCompose(get_nums)
)
圖片pipeline里增強if通用性:
class articleImagePipeline(ImagesPipeline):#繼承ImagesPipeline灼捂,只用來處理封面圖的自定義的pipeline离例,
def item_completed(self,results,item,info):#results里面有兩個參數(shù),list里面有tuple和dict纵东,dict里面的path是image保存的文件的路徑
if "front_image_url" in item:#知乎等網(wǎng)站可能沒有front_image_url
for ok, value in results:
image_file_path = value["path"]
item["front_image_path"] = image_file_path
return item
自定義的item帶處理函數(shù)的完整代碼:
class JobBolearticleItem(scrapy.Item):
title=scrapy.Field()
create_date=scrapy.Field(
input_processor=MapCompose(date_convert),
)
url=scrapy.Field()
url_object_id=scrapy.Field()#對url_object_id進行md5處理粘招,讓url變成一個長度固定的,唯一的值
praise_nums=scrapy.Field(
input_processor=MapCompose(get_nums)
)
comments_nums=scrapy.Field(
input_processor=MapCompose(get_nums)
)
fav_nums=scrapy.Field(
input_processor=MapCompose(get_nums)
)
content=scrapy.Field()
tags=scrapy.Field(
input_processor=MapCompose(remove_comment_tags),#去掉tags中出現(xiàn)的評論
output_processor=Join(",")#使用join把字符串連接起來偎球,原理同最開始的寫法
)
front_image_url=scrapy.Field(
output_processor=MapCompose(return_value)#保證front_image_url里面的參數(shù)格式是list,,配置image pipeline之后洒扎,front_image_url傳入必須是list形式
)
front_image_path=scrapy.Field()#方便之后scrapy下載圖片辑甜,提取articleImagePipeline里面的results里面的path
- 以上是爬取伯樂在線部分的代碼,全部代碼在我的GitHub上袍冷,親測可以運行磷醋,有需要的可以拿走哦:https://github.com/sundie1997/articlespider