本文旨在通过爬取一系列博客网站技术文章的实践,介绍一下scrapy这个python语言中强大的整站爬虫框架的使用。各位童鞋可不要用来干坏事哦,这些技术博客平台也是为了让我们大家更方便的交流、学习、提高的,大家千万要珍惜哦(-_-)。

本文目录:

0、开发环境

本文环境:
Win7 64位
Python 版本:3.6.5
pip 版本:18.1
scrapy 版本:1.5
pymysql 版本:0.9.2
Visual Code 版本: 1.28.2
Mysql 5.7 (不会安装的自行百度,这里就不岔话题了)

至于初始化Visual Code(后续文中统一简称:vscode)的Python编程环境,请参考博文:Python3从零开始爬取今日头条的新闻【一、开发环境搭建】

建议通过Anaconda3 来搭建python开发环境,省心。

【注】:文中源码有关XPath解析页面内容提取文章元素的解读,本文不再啰嗦重复了,可以参考前面的博文:

Python3从零开始爬取今日头条的新闻【一、开发环境搭建】

Python3从零开始爬取今日头条的新闻【二、首页热点新闻抓取】(2.1.3节有介绍XPath使用)

1、目标介绍

今天的目标网站主要分为两类:

  • 一类是页面通过Ajax异步请求的方式获取翻页文章列表

    比如强大的csdn博客、oschina开源中国就是属于第一类通过Ajax异步加载的方式获取更多内容的

  • 另一类是直接通过界面的上一页、下一页、跳转到第几页的方式直接加载下一页的文章列表

    比如cnblog博客园、51cto、iteye、itpub、jobbole伯乐在线等几个是直接通过页面导航翻页的。

下面让我们来一个一个分析、实现爬取技术文章保存到本地。

2、爬取目标

2.1、csdn博客

2.1.1 如何判断是否为Ajax方式异步获取的?

有很多种方式,比如,我们打开火狐浏览器(其它浏览器也一样),按F12打开浏览器的调试模式,选中【网络】,点击【XHR】来过滤异步请求,

然后输入csdn的网址:https://www.csdn.net/,我们看到列表有很多异步的请求,别慌,我们找一下很容易发现其中一个返回json格式的传输数据大小28KB的是我们的目标,点开这个请求发现右边返回的确实是文章列表:

我们通过关键字articles过滤一下这个请求,再往下滑动发现又发了同样的请求,不过参数不一样:

分析下这几个网址:

https://www.csdn.net/api/articles?type=more&category=home&shown_offset=1541633731306080

https://www.csdn.net/api/articles?type=more&category=home&shown_offset=1541579172175664

https://www.csdn.net/api/articles?type=more&category=home&shown_offset=1541572185652051

发现其中不一样的就是最后一个shown_offset参数值,这个看起来像时间戳,但是是什么时间戳呢?当前系统时间?上次返回数据的最后一个时间戳?让我们看下响应里面的数据:

分析了下可以知道,第二个请求的这个时间戳,正是第一个请求返回数据的最后一个里面的这个值,我们再分析后面几个请求发现都是符合这个规律的,OK了,那接下来就是写爬虫去获取数据了。

2.1.2 爬虫实现

打开vscode终端定位到工程目录,例如d:/tmp/csdnnews

输入:

scrapy startproject csdnnews

提示成功后,进入到csdnnews目录

cd csdnnews

然后输入以下命令创建爬虫:

scrapy genspider csdnspider www.csdn.net

其中csdnspider 是爬虫类的名字,www.csdn.net 是我们要爬虫允许的域名地址

此时目录如下(db目录是后面加的数据库操作工具类的文件夹)

这里面我们要改几个地方来实现我们的功能。

2.1.2.1 修改spider接口实现

主要修改的内容有:

url:开始爬虫的首页

allow_domians:允许爬虫的网站域名

def parse(self, response):这里处理爬虫返回的网页内容,抓取数据

第一次的url中要拼接一个16位的时间戳,类中提供了方法,后续的这个offset都是根据上一次返回的数据最后一个里面的offset来赋值即可。

这个spider类的主要内容如下:

class tbmmSpider(Spider):
# url = "https://www.csdn.net/api/articles?type=more&category=home&shown_offset="
url = 'https://www.csdn.net/api/articles?type=more&category=newarticles&shown_offset='
name = "csdnspider"
allow_domians = ["www.csdn.net"] def get_time_stamp16(self):
# 生成16时间戳 eg:1540281250399895 -ln
datetime_now = datetime.datetime.now() # 10位,时间点相当于从1.1开始的当年时间编号
date_stamp = str(int(time.mktime(datetime_now.timetuple()))) # 6位,微秒
data_microsecond = str("%06d"%datetime_now.microsecond) date_stamp = date_stamp+data_microsecond
return int(date_stamp) def start_requests(self):
curl = self.url + str(self.get_time_stamp16())
yield Request(curl, headers=self.headers) def parse(self, response):
datas = json.dumps(response.text, ensure_ascii= False, indent=4, separators=(',', ': ')) json_data = json.loads(datas)
json_data = json_data.replace('null', '\"\"').replace(u'None', u'\"\"').replace(u'false', 'False').replace(u'true', 'True') dict = eval(json_data)
articles = dict['articles'] if articles and len (articles) > 0:
for article in articles:
item = CsdnnewsItem()
item['avatar'] = article['avatar']
item['title'] = article['title']
item['category'] = article['category']
item['category_id'] = article['category_id']
item['channel'] = article['channel']
item['show_datetime'] = article['created_at']
item['cur_id'] = article['id']
item['user_name'] = article['user_name']
item['nickname'] = article['nickname']
item['user_url'] = article['user_url']
item['showtime'] = article['shown_time']
item['source_from'] = 'csdn'
item['summary'] = article['summary']
item['tag'] = article['tag']
item['type'] = article['type']
item['detail_url'] = article['url']
item['views_count'] = article['views']
item['comments_count'] = article['comments']
shown_offset = article['shown_offset']
yield item #如果datas存在数据则对下一页进行采集
time.sleep(0.5)
next_url = self.url + str(shown_offset)
yield Request(next_url, headers=self.headers)

2.1.2.2 修改items.py文件

声明接收抓取内容的item类属性

内容如下:


class CsdnnewsItem(scrapy.Item):
# define the fields for your item here like: # 头像
avatar = scrapy.Field() # 标题
title = scrapy.Field() # 分类文本
category = scrapy.Field() # 分类id
category_id = scrapy.Field() # 渠道
channel = scrapy.Field() # 创建时间
created_time = scrapy.Field() # 当前id
cur_id = scrapy.Field() # 用户名
user_name = scrapy.Field() # 作者昵称
nickname = scrapy.Field() # 用户详情url
user_url = scrapy.Field() # 展示时间
showtime = scrapy.Field() # 展示时间,比如2018年8月、19小时前、2天前
show_datetime = scrapy.Field() # 来源
source_from = scrapy.Field() # 摘要
summary = scrapy.Field() # 标签(多个标签以|分割)
tag = scrapy.Field() # 类型(blog、news、article)
type = scrapy.Field() # 详情url
detail_url = scrapy.Field() # 阅读数量
views_count = scrapy.Field() # 评论数量
comments_count = scrapy.Field()

2.1.2.3 修改pipeline.py文件

实现保存数据到mysql数据库

class CsdnnewsPipeline(object):
def __init__(self):
self.db = DBHelper() def process_item(self, item, spider):
self.db.insert(item) return item def close_spider(self, spider):

2.1.2.4 修改settings.py文件

声明pymysql数据库连接信息等


BOT_NAME = 'csdnnews' SPIDER_MODULES = ['csdnnews.spiders']
NEWSPIDER_MODULE = 'csdnnews.spiders' #mysql-连接配置
MYSQL_HOST = '127.0.0.1'
MYSQL_DBNAME = 'voanews'
MYSQL_USER = 'news'
MYSQL_PASSWD ='123456'
MYSQL_PORT = 3306 # 下面这个要打开,否则无法通过pipe管道存储到数据库
ITEM_PIPELINES = {
'csdnnews.pipelines.CsdnnewsPipeline': 300,
}

2.1.2.5 修改dbhelper.py文件

实现保存到数据库

# -*- coding: utf-8 -*-
import pymysql
from twisted.enterprise import adbapi
from scrapy.utils.project import get_project_settings #导入seetings配置 class DBHelper(): def __init__(self):
settings = get_project_settings() #获取settings配置,设置需要的信息 dbparams = dict(
host=settings['MYSQL_HOST'], #读取settings中的配置
db=settings['MYSQL_DBNAME'],
user=settings['MYSQL_USER'],
passwd=settings['MYSQL_PASSWD'],
charset='utf8', #编码要加上,否则可能出现中文乱码问题
cursorclass=pymysql.cursors.DictCursor,
use_unicode=False,
)
#**表示将字典扩展为关键字参数,相当于host=xxx,db=yyy....
dbpool = adbapi.ConnectionPool('pymysql', **dbparams)
self.__dbpool = dbpool def connect(self):
return self.__dbpool #插入数据
def insert(self, item):
#这里定义要插入的字段 sql = "insert into news(avatar, title, category, category_id, channel,show_datetime,\
cur_id, user_name, nickname, user_url, showtime, source_from, summary, tag, type, detail_url, views_count, comments_count)\
values(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
#调用插入的方法
query = self.__dbpool.runInteraction(self._conditional_insert, sql, item)
#调用异常处理方法
query.addErrback(self._handle_error)
return item #写入数据库中
def _conditional_insert(self, canshu, sql, item): #取出要存入的数据,这里item就是爬虫代码爬下来存入items内的数据
params = (item['avatar'], item['title'], item['category'], item['category_id'], item['channel'],
item['show_datetime'], item['cur_id'], item['user_name'], item['nickname'], item['user_url'],
item['showtime'], item['source_from'], item['summary'], item['tag'], item['type'], item['detail_url'], item['views_count'], item['comments_count'])
canshu.execute(sql, params) #错误处理方法
def _handle_error(self, failue):
print('--------------database operation exception!!-----------------')
print(failue) def __del__(self):
try:
self.__dbpool.close()
except Exception as ex:
print(ex)

2.1.3 启动爬虫

在启动前,先初始化mysql的表结构,源码中db目录有个init.sql文件,执行后会创建一个存储爬取内容的表结构,同时要把setting中配置的用户名,在mysql中创建相应的用户以及授权给刚才新建的表。不清楚的可以评论回复,这里不岔话题了。

我们在刚才的spider目录的同级路径,输入以下命令即可启动爬虫:

scrapy crawl csdnspider

2.1.4 源码下载

本节结束,爬取csdn博文的源码下载:点我去下载完整源码


2.2、cnblog博客园

2.2.1、页面分析

我们打开博客园的java分类,地址是:https://www.cnblogs.com/cate/java/

可以看到这个网站跟前面的csdn不一样的是,这个的文章列表内容是直接在源码里面的,这种是最容易爬取的,我们在页面右键查看源码内容如下:

刚好对应了页面的前两篇文章:

下面让我们来看下页面的文章列表布局:

所有的文章都是在一个id值为post_listdiv里面,每一个文章布局都是包裹在一个class属性值为post_itemdiv布局里面。

我们再看下底部的翻页跳转导航内容:

翻页导航布局是在一个class属性值为pagerdiv里面,每一个a标签表示一页导航地址。

找到页面的规律后,接下来让我们编写爬虫实现文章的提取。

2.2.2、爬虫实现

2.2.2.1、创建项目

打开vscode终端定位到工程目录,例如d:/tmp/cnblog

输入:

scrapy startproject cnblog

提示成功后,进入到cnblog目录

cd cnblog

然后输入以下命令创建爬虫:

scrapy genspider -t crawl cnblogspider www.cnblogs.com

其中cnblogspider 是爬虫类的名字,www.cnblogs.com 是我们要爬虫允许的域名地址

此时目录如下(db目录是后面加的数据库操作工具类的文件夹)。

这里跟前面一节实现爬取csdn博文的爬虫不一样的是,在创建爬虫的时候,加了参数-t crawl,就是以crawl模板来创建一个继承自CrawlSpiderspider

2.2.2.2、spider实现

spider的内容如下:

其中start_urls 是代表要爬取的首页列表,这里选择了java、python、linux等分类;

parse_item是我们处理数据的回调,这里解析页面提取文章各元素;

rules是告诉爬虫应该如何提取翻页导航,这里是以xpath方式定位翻页导航元素,根据2.2.2.1节里面的页面分析很容易理解。


class CnblogspiderSpider(CrawlSpider):
name = 'cnblogspider'
allowed_domains = ['www.cnblogs.com']
start_urls = [
'https://www.cnblogs.com/cate/java/',
'https://www.cnblogs.com/cate/python/',
'https://www.cnblogs.com/cate/job/',
'https://www.cnblogs.com/cate/algorithm/',
'https://www.cnblogs.com/cate/linux/',
'https://www.cnblogs.com/cate/mysql/',
'https://www.cnblogs.com/cate/cpp/',
'https://www.cnblogs.com/cate/go/'
] rules = (
Rule(LinkExtractor(restrict_xpaths=('//div[@id="pager_bottom"]/div[@id="paging_block"]/div[@class="pager"]/a', )), callback='parse_item', follow=True),
) def parse_item(self, response):
for article in response.xpath('//div[@id="post_list"]/div[@class="post_item"]'):
item = CnblogItem()
try: item['title'] = article.xpath('./div[@class="post_item_body"]/h3/a[@class="titlelnk"]/text()').extract_first()
item['summary'] = article.xpath('./div[@class="post_item_body"]/p[@class="post_item_summary"]/text()').extract_first()
item['detail_url'] = article.xpath('./div[@class="post_item_body"]/h3/a[@class="titlelnk"]/@href').extract_first()
item['logo_url'] = article.xpath('./div[@class="post_item_body"]/p[@class="post_item_summary"]/a/img/@src').extract_first() item['source_from'] = '博客园'
item['show_datetime'] = article.xpath('./div[@class="post_item_body"]/p/div[@class="post_item_foot"]/text()').extract_first()
item['user_name'] = article.xpath('./div[@class="post_item_body"]/p/div[@class="post_item_foot"]/a/text()').extract_first()
item['nickname'] = article.xpath('./div[@class="post_item_body"]/p/div[@class="post_item_foot"]/a/text()').extract_first()
item['user_url'] = article.xpath('./div[@class="post_item_body"]/p[@class="post_item_summary"]/a/@href').extract_first()
item['cur_id'] = '' item['views_count'] = article.xpath('./div[@class="post_item_body"]/div[@class="post_item_foot"]/span[@class="article_view"]/a/text()').extract_first()
item['views_count'] = re.findall("\((\d*?)\)", item['views_count'])[0]
item['comments_count'] = article.xpath('./div[@class="post_item_body"]/div[@class="post_item_foot"]/span[@class="article_comment"]/a/text()').extract_first()
item['comments_count'] = re.findall("\((\d*?)\)", item['comments_count'])[0]
print(item['views_count'])
print(item['comments_count'])
except Exception as ex:
print(ex) yield item

2.2.2.3、items实现

跟前面2.1节爬取csdn的一样,定义了一样的元素,只不过不同的博客文章,所能提取的字段不一样,只是这里定义的一部分而已。这里就不重复贴代码了。

2.2.2.4、pipeline、settings、dbhelper的实现

这几个都跟2.1节爬取csdn的差不多,只是在dblhelper里面存储的字段不一样而已,具体直接看源码吧。

2.2.3、启动爬虫

如果已经按照2.1爬取csdn的章节里面初始化过mysql数据库了,这一步可以省略。

在启动前,先初始化mysql的表结构,源码中db目录有个init.sql文件,执行后会创建一个存储爬取内容的表结构,同时要把setting中配置的用户名,在mysql中创建相应的用户以及授权给刚才新建的表。不清楚的可以评论回复,这里不岔话题了。

我们在刚才的spider目录的同级路径,输入以下命令即可启动爬虫:

scrapy crawl cnblogspider

2.2.4、源码下载

本节结束,爬取cnblog博客园文章的源码下载:点我去下载完整源码


2.3、51cto博客

2.3.1 页面分析

我们打开技术类的推荐分类:http://blog.51cto.com/artcommend,在页面右键查看源码,可以发现文章列表标题在源码中,这种跟前面2.2节的博客园网站的爬取一样的。

2.3.2、启动爬虫

如果已经按照2.1爬取csdn的章节里面初始化过mysql数据库了,这一步可以省略。

在启动前,先初始化mysql的表结构,源码中db目录有个init.sql文件,执行后会创建一个存储爬取内容的表结构,同时要把setting中配置的用户名,在mysql中创建相应的用户以及授权给刚才新建的表。不清楚的可以评论回复,这里不岔话题了。

我们在刚才的spider目录的同级路径,输入以下命令即可启动爬虫:

scrapy crawl ctospider

2.3.3、源码下载

本节结束,爬取51CTO博客文章的源码下载:点我去下载完整源码


2.4、jobbole伯乐在线

2.4.1 页面分析

我们打开伯乐在线的全部文章页面:http://blog.jobbole.com/all-posts/

可以看到底部有分页导航,是不是很爽…克制一点,以学习为目的,不要耍流氓哈,不要干坏事。



创建工程、创建爬虫、编写spider等就不重复了,跟前面的一样一样的,直接看源码会更直接。

2.4.2、启动爬虫

如果已经按照2.1爬取csdn的章节里面初始化过mysql数据库了,这一步可以省略。

在启动前,先初始化mysql的表结构,源码中db目录有个init.sql文件,执行后会创建一个存储爬取内容的表结构,同时要把setting中配置的用户名,在mysql中创建相应的用户以及授权给刚才新建的表。不清楚的可以评论回复,这里不岔话题了。

我们在刚才的spider目录的同级路径,输入以下命令即可启动爬虫:

scrapy crawl jobbolespider

2.4.3、源码下载

本节结束,爬取伯乐在线博客文章的源码下载:点我去下载完整源码


2.5、itpub博客(待续)

2.5.1、页面分析

我们打开itpub的linux专题:http://blog.itpub.net/linux/



我们右键查看源码,可以看到文章内容就在源码中,只不过这个网站的翻页导航不是跟前面的一样有直接的第1页、第2页、下一页的形式,而是在底部有个“点击加载更多”的布局,其实也是一个a标签,跟其它的分页导航没有本质的区别。

创建工程、创建爬虫、编写spider等就不重复了,跟前面的一样一样的,直接看源码会更直接。

2.5.2、启动爬虫

如果已经按照2.1爬取csdn的章节里面初始化过mysql数据库了,这一步可以省略。

在启动前,先初始化mysql的表结构,源码中db目录有个init.sql文件,执行后会创建一个存储爬取内容的表结构,同时要把setting中配置的用户名,在mysql中创建相应的用户以及授权给刚才新建的表。不清楚的可以评论回复,这里不岔话题了。

我们在刚才的spider目录的同级路径,输入以下命令即可启动爬虫:

scrapy crawl itpubspider

2.5.3、源码下载

本节结束,爬取ITPUB博客文章的源码下载:点我去下载完整源码


2.6、oschina开源中国博客

2.6.1、页面分析

开源中国的博客就比较有意思,他的翻页比较隐藏,但是还是可以分析得到的。我们打开编程语言的首页,并且按F12打开调试模式查看Ajax过滤异步请求:



可以看到这里是有异步请求获取内容的,并且从过滤的Ajax请求的内容一看便知,在当前分类(比如截图中的编程语言分类是classification=428609)定了的前提下,p=2就是表示获取第二页的数据了,type=ajax表示以异步的方式返回文章列表。

再让我们看下源码,在当前页面右键查看源码,如下图:可以看到它的内容在源码里面的:

但是它页面上又看不到上一页、下一页、或者第1页,第2页之类的分页导航的布局。从下图可以看到,其实是有的,只不过它的布局元素都设置了显示属性为隐藏的:style="display: none",所以我们看不到。

这样我们就知道在crawl爬虫中如何获取爬虫所需下一页的布局元素了。

那还有个问题:oschina开源中国这个网站的博客页面,跟前面的几个可以通过页面翻页导航自动爬取同系列的博客页面不一样的是,这里没有告诉我们它的最后一页是多少,如何判断呢?

我们这里采取一个策略:如果当前这次请求,没有返回任何博客文章内容了,就认为到最后一页了。

2.6.2、爬虫实现

ok,前面分析过页面结构、翻页导航定位、判断最后一页的策略了,这里就具体实现爬虫模块。

这里我们把爬虫访问的首页定为p=1,链接就是前面2.6.1分析的Ajax异步请求里面的内容,只是把p=2改为p=1就是访问第一页了。

下一页的定位规则也很容易理解,通过XPath定位到2.6.1分析的那个隐藏的翻页的a标签即可。

start_urls = ['https://www.oschina.net/blog/widgets/_blog_index_recommend_list?classification=0&type=ajax&p=1']

rules = (
Rule(LinkExtractor(restrict_xpaths=('//p[@class="pagination"]/a[contains(@class, "pagination__next")]', )), callback='parse_item', follow=True),
)

解析文字列表的方法如下:这个直接看代码就行了,主要是根据XPath提取我们需要的字段,如果对XPath不熟悉,可以参考我的另一篇文章有详细介绍使用示例:

Python3从零开始爬取今日头条的新闻【二、首页热点新闻抓取】

2.1.3节有介绍。

def parse_item(self, response):
for article in response.xpath('//div/div[contains(@class, "blog-item")]'):
item = OschinaItem()
try: item['title'] = article.xpath('./div[@class="content"]/a[@class="header"]/@title').extract_first()
item['summary'] = article.xpath('./div[@class="content"]/div[@class="description"]/p/text()').extract_first()
item['detail_url'] = article.xpath('./div[@class="content"]/a[@class="header"]/@href').extract_first()
item['source_from'] = '开源中国'
item['show_datetime'] = article.xpath('./div[@class="content"]/div[@class="extra"]/div/div[2]/text()').extract_first()
item['user_name'] = article.xpath('./div[@class="content"]/div[@class="extra"]/div/div[1]/a/text()').extract_first()
item['nickname'] = article.xpath('./div[@class="content"]/div[@class="extra"]/div/div[1]/a/text()').extract_first()
item['user_url'] = article.xpath('./div[@class="content"]/div[@class="extra"]/div/div[1]/a/@href').extract_first()
item['cur_id'] = article.xpath('./@data-id').extract_first() item['views_count'] = article.xpath('./div[@class="content"]/div[@class="extra"]/div/div[3]/text()').extract_first()
view_count_str = str(item['views_count']) # 因为页面上的浏览数,这个网站返回的是2k,100之类的,要统一转为整型存储到数据库
if view_count_str.find('K') > -1:
view_count_str = view_count_str.lstrip().rstrip()
item['views_count'] = int(float(view_count_str.replace('K',''))*1000.0)
if view_count_str.find('w') > -1:
item['views_count'] = str(float(view_count_str.replace('w',''))*10000.0) item['comments_count'] = article.xpath('./div[@class="content"]/div[@class="extra"]/div/div[4]/a/text()').extract_first() except Exception as ex:
print(ex) yield item

OK,主要的就上面这个代码,其它的跟前面章节的都大同小异,直接看源码即可。

2.6.3、启动爬虫

如果已经按照2.1爬取csdn的章节里面初始化过mysql数据库了,这一步可以省略。

在启动前,先初始化mysql的表结构,源码中db目录有个init.sql文件,执行后会创建一个存储爬取内容的表结构,同时要把setting中配置的用户名,在mysql中创建相应的用户以及授权给刚才新建的表。不清楚的可以评论回复,这里不岔话题了。

我们在spider目录的同级路径,输入以下命令即可启动爬虫:

scrapy crawl oschinaspider

2.6.4、源码下载

本节结束,爬取OSChina开源中国博客文章的源码下载:点我去下载完整源码


全部内容完毕,这里只是总结下自己最近学习scrapy爬虫的几个实践,通过这几个实践,一般的类似需求应该都可以搞定,当然这里没有涉及到反爬虫厉害的站点的处理,比如浏览器header伪装、ip代理、爬虫时间间隔等,后续有机会再实践下。

本文内容如有错误,恳请斧正,如有更好的技术,欢迎指点一二,谢谢。


3、参考资料

[1]: XPath语法参考
[2]: 廖雪峰老师的Python3 在线学习手册

[3]: Python3官方文档

[4]: 菜鸟学堂-Python3在线学习

[5]: scrapy官方文档

[6]: scrapy中文网

一文搞定scrapy爬取众多知名技术博客文章保存到本地数据库,包含:cnblog、csdn、51cto、itpub、jobbole、oschina等的更多相关文章

  1. scrapy爬取校花网男神图片保存到本地

    爬虫四部曲,本人按自己的步骤来写,可能有很多漏洞,望各位大神指点指点 1.创建项目 scrapy startproject xiaohuawang scrapy.cfg: 项目的配置文件xiaohua ...

  2. Python的scrapy之爬取链家网房价信息并保存到本地

    因为有在北京租房的打算,于是上网浏览了一下链家网站的房价,想将他们爬取下来,并保存到本地. 先看链家网的源码..房价信息 都保存在 ul 下的li 里面 ​ 爬虫结构: ​ 其中封装了一个数据库处理模 ...

  3. scrapy 爬取知乎问题、答案 ,并异步写入数据库(mysql)

      python版本  python2.7 爬取知乎流程: 一 .分析 在访问知乎首页的时候(https://www.zhihu.com),在没有登录的情况下,会进行重定向到(https://www. ...

  4. python 爬取w3shcool的JQuery的课程并且保存到本地

    最近在忙于找工作,闲暇之余,也找点爬虫项目练练手,写写代码,知道自己是个菜鸟,但是要多加练习,书山有路勤为径.各位爷有测试坑可以给我介绍个啊,自动化,功能,接口都可以做. 首先呢,我们明确需求,很多同 ...

  5. requests库爬取豆瓣热门国产电视剧数据并保存到本地

    首先要做的就是去豆瓣网找对应的接口,这里就不赘述了,谷歌浏览器抓包即可,然后要做的就是分析返回的json数据的结构: https://movie.douban.com/j/search_subject ...

  6. 爬取王垠的博客并生成pdf

    尚未完善,有待改进 #!/usr/bin/env python3 # -*- coding: utf-8 -*- __author__ = 'jiangwenwen' import pdfkit im ...

  7. 爬虫---lxml爬取博客文章

    上一篇大概写了下lxml的用法,今天我们通过案例来实践,爬取我的博客博客并保存在本地 爬取博客园博客 爬取思路: 1.首先找到需要爬取的博客园地址 2.解析博客园地址 # coding:utf-8 i ...

  8. Scrapy - 第一个爬虫和我的博客

    第一个爬虫 这里我用官方文档的第一个例子:爬取http://quotes.toscrape.com来作为我的首个scrapy爬虫,我没有找到scrapy 1.5的中文文档,后续内容有部分是我按照官方文 ...

  9. [Python学习] 简单网络爬虫抓取博客文章及思想介绍

            前面一直强调Python运用到网络爬虫方面很有效,这篇文章也是结合学习的Python视频知识及我研究生数据挖掘方向的知识.从而简介下Python是怎样爬去网络数据的,文章知识很easy ...

随机推荐

  1. java同一个类不同方法间的同步

    对象的方法中一旦加入synchronized修饰,则任何时刻只能有一个线程访问synchronized修饰的方法.假设有个数据对象拥有写方法与读方法,多线程环境中要想保证数据的安全,需对该对象的读写方 ...

  2. 利用ADSL拨号上网方式如何搭建服务器

    序:搭建服务器需要两个条件硬件服务器和固定公网IP,随便一台个人电脑都可以作为硬件服务器,就剩下一个问题,如何获得一个固定公网IP. 第一章 扫盲:ADSL拨号上网方式,本地IP与公网IP的区别 一. ...

  3. Windows下安装Eric5时出现的“Sorry, please install QtHelp.”问题解决办法

    解决Windows下安装Eric5时出现的“Sorry, please install QtHelp.”问题   PyQt4在Windows中使用了DirectX作为加速,不过,PyQt4没有使用最新 ...

  4. Web 前端开发环境

    创建 Web 前端开发环境 Web 前端开发涉及多种工具,这里将常用工具的安装和配置进行说明,提供了详细的说明,为后继的开发创建一个坚实的基础. 本文介绍的工具有:NodeJS, NPM, Bower ...

  5. Restful、Jersey和JAX-RS

     一:MVC与SpringMVC MVC:是一种思想,是一种设计模式 SpringMVC:是一个框架,实现了MVC这种思想. 之前:写JSP页面,比较繁琐.eg:在页面显示用户列表,我们会在JSP页面 ...

  6. python内存回收的问题

    python实际上,对于占用很大内存的对象,并不会马上释放. 举例,a=range(10000*10000),会发现内存飙升一个多G,del a 或者a=[]都不能将内存降下来.. del 可以删除多 ...

  7. 深入源码理解ThreadLocal和ThreadLocalMap

    一.ThreadLoacl的理解: 官方的讲: ThreadLocal是一个本地线程副本变量工具类,主要用于将私有线程和该线程存放的副本对象做一个映射,各个线程之间的变量互不干扰 通俗的讲: Thre ...

  8. 单链表查找第i个节点

    #include<stdio.h> #include<string.h> #include<stdlib.h> typedef struct Node { char ...

  9. 【图像处理基础】LBP特征

    前言 其中dsptian的博客不仅给出了LBP的实现,还计算了LBPH,计算LBP过程中有点小瑕疵,评论中有给出修改方法.除了使用power还可以使用bitxor函数实现. lbpcode = bit ...

  10. POJ-1191-棋盘分割(动态规划)

    棋盘分割 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 13593 Accepted: 4846 Description 将一个 ...