Scrapy抓取jobbole数据
1、python版本3.6.1
2、python编辑器:JetBrains PyCharm
2、安装virtualenvwrapper-win
pip3 install virtualenvwrapper-win
3、创建项目
mkvirtualenv spider_article
pip install C:\Users\CR\Downloads\Twisted-17.5.0-cp36-cp36m-win_amd64.whl
pip install pypiwin32
pip install -i https://pypi.douban.com/simple/ scrapy
pip install mysqlclient
pip install pillow
4、现在项目存放位置:
1、打开cmd
2、workon spider_article
3、scrapy startproject ArticleSpider
4、cd ArticleSpider
5、scrapy genspider jobbole blog.jobbole.com
5、ArticleSpider文件夹下面创建调试文件
from scrapy.cmdline import execute import sys
import os sys.path.append(os.path.dirname(os.path.abspath(__file__)))
execute(["scrapy","crawl","jobbole"])
6、主要代码
jobbole.py文件内容
import scrapy
import re
import datetime
from scrapy.http import Request
from urllib import parse #python2中import urlparse
from scrapy.loader import ItemLoader from ArticleSpider.items import JobBoleArticleItem,ArticleItemLoader from ArticleSpider.utils.common import get_md5 class JobboleSpider(scrapy.Spider):
name = 'jobbole'
allowed_domains = ['blog.jobbole.com']
start_urls = ['http://blog.jobbole.com/all-posts/'] def parse(self, response): '''
1、获取文章列表页面中的文章url并交给scrapy下载后解析
2、获取下一页的url并交给scrapy进行下载,下载完成后交给parse
:param response:
:return:
'''
#extract 一旦执行就会返回一个数组
post_nodes = response.css("#archive .floated-thumb .post-thumb a")
for post_node in post_nodes:
image_url = post_node.css("img::attr(src)").extract_first("")
#取出当前文章的域名
#Request(url=post_url,callback=self.parse_detail)
post_url = post_node.css("::attr(href)").extract_first("")
#parse.urljoin post_url如果没有域名就从response中提取域名防进行;如果post_url有域名,response就不会起作用
yield Request(url=parse.urljoin(response.url,post_url),meta={"front_image_url":image_url}, callback=self.parse_detail) #提取下一页并交给scrapy进行下载
next_urls = response.css(".next.page-numbers::attr(href)").extract_first("")
if next_urls:
yield Request(url=parse.urljoin(response.url, post_url), callback=self.parse) def parse_detail(self,response):
'''
获取文章的具体字段
:param response:
:return:
'''
front_image_url = response.meta.get("front_image_url", "") #文章封面图
item_loader = ArticleItemLoader(item=JobBoleArticleItem(),response=response)
item_loader.add_css("title",".entry-header h1::text")
item_loader.add_value("url", response.url)
item_loader.add_value("front_image_url",[front_image_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_css("praise_nums", ".vote-post-up h10::text")
item_loader.add_css("comment_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
2、items.py文件
import datetime
import re import scrapy
from scrapy.loader import ItemLoader
from scrapy.loader.processors import MapCompose,TakeFirst,Join class ArticlespiderItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
pass def date_convert(vlaue):
try:
create_date = datetime.datetime.strptime(vlaue,"%Y/%m/%d").date()
except Exception as e:
create_date = datetime.datetime.now().date()
return create_date def get_nums(value):
match_re = re.match(".*?(\d+).*", value)
if match_re:
nums = int(match_re.group(1))
else:
nums = 0
return nums def remove_comment_tags(value):
#去掉tag中提取的评论
if "评论" in value:
return ""
else:
return value def return_value(value):
return value class ArticleItemLoader(ItemLoader):
#自定义ItemLoader
default_output_processor = TakeFirst() class JobBoleArticleItem(scrapy.Item):
title = scrapy.Field()
# title = scrapy.Field(
# input_processor = MapCompose(lambda x:x+'-jobbole')
# )
create_date = scrapy.Field(
input_processor = MapCompose(date_convert),
#output_processor = TakeFirst(),#只取第一个
)
url = scrapy.Field()
url_object_id = scrapy.Field()
front_image_url = scrapy.Field()
front_image_path = scrapy.Field(
input_processor=MapCompose(return_value)
)
praise_nums = scrapy.Field(
input_processor = MapCompose(get_nums)
)
comment_nums = scrapy.Field(
input_processor = MapCompose(get_nums)
)
fav_nums = scrapy.Field(
input_processor = MapCompose(get_nums)
)
tags = scrapy.Field(
input_processor=MapCompose(remove_comment_tags),
output_processor=Join(",")
)
content = scrapy.Field()
3、piplines.py文件
import codecs
import json from scrapy.pipelines.images import ImagesPipeline
from scrapy.exporters import JsonItemExporter
from twisted.enterprise import adbapi #adbapi可以将MySQLdb的一些操作变成异步化的操作 import MySQLdb
import MySQLdb.cursors class ArticlespiderPipeline(object):
def process_item(self, item, spider):
return item class JsonWithEncodingPipeline(object):
#自定义json文件的导出
def __init__(self):
self.file = codecs.open('article.json','w',encoding="utf-8") def process_item(self, item, spider):
lines = json.dumps(dict(item),ensure_ascii=False) + '\n'
self.file.write(lines)
return item def spider_closed(self,spider):
self.file.close() class MysqlPipeline(object):
def __init__(self):
self.conn = MySQLdb.connect("localhost","root","","article_spider",charset="utf8",use_unicode=True)
self.cursor = self.conn.cursor() def process_item(self, item, spider):
inset_sql = '''
INSERT INTO article (title,url,create_date,fav_nums)
VALUES (%s,%s,%s,%s)
'''
self.cursor.execute(inset_sql,(item['title'],item['url'],item['create_date'],item['fav_nums']))
self.conn.commit() class MysqlTwistedPipeline(object):
def __init__(self,dbpool):
self.dbpool = dbpool @classmethod
def from_settings(cls,settings):
dbparms = dict (
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) return cls(dbpool) def process_item(self, item, spider):
'''
使用Twisted将mysql插入变成异步执行
:param item:
:param spider:
:return:
'''
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):
#执行具体的插入
inset_sql = '''
INSERT INTO article (title,url,create_date,fav_nums)
VALUES (%s,%s,%s,%s)
'''
cursor.execute(inset_sql, (item['title'], item['url'], item['create_date'], item['fav_nums'])) class JsonExporterPipleline(object):
#调用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 class ArticleImagePipline(ImagesPipeline):
def item_completed(self, results, item, info):
if "front_image_path" in item:
for ok,value in results:
image_file_path = value["path"]
item["front_image_path"] = image_file_path return item
4、创建公共函数(位置存放ArticleSpider/utils/common.py)
import hashlib def get_md5(url):
if isinstance(url,str):
url = url.encode("utf-8")
m = hashlib.md5()
m.update(url)
return m.hexdigest() if __name__ == '__main__':
print(get_md5("http://jobbole.com"))
5、配置settings文件
import os ITEM_PIPELINES = {
'scrapy.pipelines.images.ImagesPipeline':1,#图片下载
'ArticleSpider.pipelines.MysqlTwistedPipeline': 3,
}
IMAGES_URLS_FIELD = 'front_image_url'
project_dir = os.path.abspath(os.path.dirname(__file__))
IMAGES_STORE = os.path.join(project_dir,"images") #指定图片存储路径 MYSQL_HOST = 'localhost'
MYSQL_DBNAME = 'article_spider'
MYSQL_USER = 'root'
MYSQL_PASSWORD = ''
Scrapy抓取jobbole数据的更多相关文章
- scrapy 抓取拉勾网数据
其实很简单,却因为一些小问题,折腾不少时间,简要记录一下,以备后需. >> scrapy startproject lagou >> cd lagou >> scr ...
- pythonのscrapy抓取网站数据
(1)安装Scrapy环境 步骤请参考:https://blog.csdn.net/c406495762/article/details/60156205 需要注意的是,安装的时候需要根据自己的pyt ...
- 分布式爬虫:使用Scrapy抓取数据
分布式爬虫:使用Scrapy抓取数据 Scrapy是Python开发的一个快速,高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据.Scrapy用途广泛,可以用于数据挖掘. ...
- scrapy递归抓取网页数据
scrapy spider的parse方法能够返回两种值:BaseItem.或者Request.通过Request能够实现递归抓取. 假设要抓取的数据在当前页,能够直接解析返回item(代码中带**凝 ...
- 通过Scrapy抓取QQ空间
毕业设计题目就是用Scrapy抓取QQ空间的数据,最近毕业设计弄完了,来总结以下: 首先是模拟登录的问题: 由于Tencent对模拟登录比较讨厌,各个防备,而本人能力有限,所以做的最简单的,手动登录后 ...
- python scrapy 抓取脚本之家文章(scrapy 入门使用简介)
老早之前就听说过python的scrapy.这是一个分布式爬虫的框架,可以让你轻松写出高性能的分布式异步爬虫.使用框架的最大好处当然就是不同重复造轮子了,因为有很多东西框架当中都有了,直接拿过来使用就 ...
- scrapy抓取淘宝女郎
scrapy抓取淘宝女郎 准备工作 首先在淘宝女郎的首页这里查看,当然想要爬取更多的话,当然这里要查看翻页的url,不过这操蛋的地方就是这里的翻页是使用javascript加载的,这个就有点尴尬了,找 ...
- 【爬虫】利用Scrapy抓取京东商品、豆瓣电影、技术问题
1.scrapy基本了解 Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架.可以应用在包括数据挖掘, 信息处理或存储历史数据等一系列的程序中.其最初是为了页面抓取(更确切来说,网络抓 ...
- Tweepy1——抓取Twitter数据
sklearn实战-乳腺癌细胞数据挖掘 https://study.163.com/course/introduction.htm?courseId=1005269003&utm_campai ...
随机推荐
- Linux内核设计与实现 总结笔记(第十五章)进程地址空间
一.地址空间 进程地址空间由进程可寻址的虚拟内存组成,内核允许进程使用这种虚拟内存中的地址. 每个进程都有一个32位或64位的平坦地址空间,空间的具体大小取决于体系结构.“平坦”指的是地址空间范围是一 ...
- (容量超大)or(容量及价值)超大背包问题 ( 折半枚举 || 改变 dp 意义 )
题意 : 以下两个问题的物品都只能取有且只有一次 ① 给你 N 个物品,所有物品的价值总和不会超过 5000, 单个物品的价格就可达 10^10 ,背包容量为 B ② 给你 N (N ≤ 40 ) 个 ...
- Activiti创建表(三)
创建Mysql 创建 mysql 数据库 activiti(名字任意):CREATE DATABASE activiti DEFAULT CHARACTER SET utf8; pom.xml < ...
- CF 696 A Lorenzo Von Matterhorn(二叉树,map)
原题链接:http://codeforces.com/contest/696/problem/A 原题描述: Lorenzo Von Matterhorn Barney lives in NYC. ...
- consul安装
原文地址: https://www.cnblogs.com/cuishuai/p/8194345.html #比较详细/有集群方式 https://www.cnblogs.com/youcong/p/ ...
- JavaScript公共库event-stream被植入恶意代码
[安全预警]JavaScript公共库event-stream被植入恶意代码 2018年11月27日,阿里云云盾应急响应中心监测到JavaScript公共库event-stream被植入恶意代码,该恶 ...
- Oracle JET(二)Oracle JET使用
Oracle JET 开发分为 Web 应用程序开发和移动应用程序开发(WebApp). Oracle JET Web 应用程序开发入门: 使用方法三种: 使用 Oracle JET Yeoman 生 ...
- React Native商城项目实战12 - 首页头部内容
1.HomeTopView为首页头部内容,HomeTopListView为HomeTopView子视图. 2.HomeTopView.js /** * 首页头部内容 */ import React, ...
- vue引入静态js文件
由于一些演示,需要对编码名称等可快速进行修改,需要页面方便配置.由于build后的vue项目基本已经看不出原样,因此需要创建一个文件,并在打包的时候不会进行编译. vue-cli 2.0的作法是在st ...
- ThreadPoolExecutor 源码分析
ThreadPoolExecutor 线程池核心实现类 线程池的生命周期 RUNNING: 接受新任务,同时处理工作队列中的任务 SHUTDOWN: 不接受新任务,但是能处理工作队列中的任务 STOP ...