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数据的更多相关文章

  1. scrapy 抓取拉勾网数据

    其实很简单,却因为一些小问题,折腾不少时间,简要记录一下,以备后需. >> scrapy startproject lagou >> cd lagou >> scr ...

  2. pythonのscrapy抓取网站数据

    (1)安装Scrapy环境 步骤请参考:https://blog.csdn.net/c406495762/article/details/60156205 需要注意的是,安装的时候需要根据自己的pyt ...

  3. 分布式爬虫:使用Scrapy抓取数据

    分布式爬虫:使用Scrapy抓取数据 Scrapy是Python开发的一个快速,高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据.Scrapy用途广泛,可以用于数据挖掘. ...

  4. scrapy递归抓取网页数据

    scrapy spider的parse方法能够返回两种值:BaseItem.或者Request.通过Request能够实现递归抓取. 假设要抓取的数据在当前页,能够直接解析返回item(代码中带**凝 ...

  5. 通过Scrapy抓取QQ空间

    毕业设计题目就是用Scrapy抓取QQ空间的数据,最近毕业设计弄完了,来总结以下: 首先是模拟登录的问题: 由于Tencent对模拟登录比较讨厌,各个防备,而本人能力有限,所以做的最简单的,手动登录后 ...

  6. python scrapy 抓取脚本之家文章(scrapy 入门使用简介)

    老早之前就听说过python的scrapy.这是一个分布式爬虫的框架,可以让你轻松写出高性能的分布式异步爬虫.使用框架的最大好处当然就是不同重复造轮子了,因为有很多东西框架当中都有了,直接拿过来使用就 ...

  7. scrapy抓取淘宝女郎

    scrapy抓取淘宝女郎 准备工作 首先在淘宝女郎的首页这里查看,当然想要爬取更多的话,当然这里要查看翻页的url,不过这操蛋的地方就是这里的翻页是使用javascript加载的,这个就有点尴尬了,找 ...

  8. 【爬虫】利用Scrapy抓取京东商品、豆瓣电影、技术问题

    1.scrapy基本了解 Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架.可以应用在包括数据挖掘, 信息处理或存储历史数据等一系列的程序中.其最初是为了页面抓取(更确切来说,网络抓 ...

  9. Tweepy1——抓取Twitter数据

    sklearn实战-乳腺癌细胞数据挖掘 https://study.163.com/course/introduction.htm?courseId=1005269003&utm_campai ...

随机推荐

  1. SQL Server性能调优--优化建议(二)

    序言 优化建议 库表的合理设计对项目后期的响应时间和吞吐量起到至关重要的地位,它直接影响到了业务所需处理的sql语句的复杂程度,为提高数据库的性能,更多的把逻辑主外键.级联删除.减少check约束.给 ...

  2. Software-Defined Networking: A Comprehensive Survey

    文章名称:Software-Defined Networking: A Comprehensive Survey 文章来源:Proceedings of the IEEE ( Volume: 103  ...

  3. SpringCloud 教程 (一) 消息总线(Spring Cloud Bus)

    Spring Cloud Bus 将分布式的节点用轻量的消息代理连接起来.它可以用于广播配置文件的更改或者服务之间的通讯,也可以用于监控.本文要讲述的是用Spring Cloud Bus实现通知微服务 ...

  4. Quadratic equation

    Quadratic equation 牛客多校九B 给定 $(x+y)\%mod=b$ $(x*y)\%mod=c$ 求 $x,y$ 二次剩余 求$((x-y)^{2})\%mod = (b\time ...

  5. Linux下JDK1.7升级1.8版本

    先下载 jdk-8u45-linux-x64.rpm 然后上传到  /usr/local/src  去.当然其他目录也可以.这里是默认位置 给所有用户添加可执行权限 #chmod +x jdk-8u4 ...

  6. 手把手教你学Vue-3(路由)

    1.路由的作用 1.当我们有多个页面的时候 ,我们需要使用路由,将组件(components)映射到路由(routes),然后告诉 vue-router 在哪里渲染它们. 简单的路由 const ro ...

  7. progress组件(进度条)

    progress组件:进度条 progress组件的属性: percent:类型:number 设置百分比 (0~100) show-info:类型:布尔 在进度条右侧显示百分比 border-rad ...

  8. ffmpeg 文件推流 rtsp和rtmp

    // rtsp推流  /opt/srs/srs2 ./objs/ffmpeg/bin/ffmpeg -re -i /root/mp4/1.mp4 -vcodec copy -codec copy -f ...

  9. 【洛谷T2695 桶哥的问题——吃桶】

    这是我们团队的一个题目(就是一个_rqy说很好写的题QwQ) 题目背景 @桶哥 这个题目的思路很玄学(性感_rqy在线讲解) 60 Pts 对于前面的六十分,好像很好拿,单纯的打一个模拟 唯一需要注意 ...

  10. WinForm实现最小化右下角

    首先,要在窗体里面加入这么两个控件,左边的是托盘控件,右边的是菜单控件. 然后设置窗体的FormClosing事件: if (e.CloseReason == CloseReason.UserClos ...