Python爬虫Csdn系列II

本文介绍了一种利用Python爬虫技术抓取优快云博客中指定用户所有文章链接的方法,包括处理分页和不同视图模式的挑战。
部署运行你感兴趣的模型镜像

Python爬虫Csdn系列II



By 白熊花田(http://blog.youkuaiyun.com/whiterbear) 转载需注明出处,谢谢。


说明:

在上一篇文章中,我们已经知道了只要将程序伪装成浏览器就能访问csdn网页。在这篇文章中,我们将设法获取某个csdn用户的所有文章的链接。

分析:

打开一个某一个的csdn用户的的专栏,可以选择目录视图(如:http://blog.youkuaiyun.com/whiterbear?viewmode=contents)和摘要视图(比如:http://blog.youkuaiyun.com/whiterbear?viewmode=list)。两个视图都可以显示用户的文章列表。

注意:这里我们选择摘要视图,不要选择目录视图,文章最后会解释为什么。

打开摘要视图查看网页源代码,我们发现,在id为’article_list’的div中,每一个子div都代表着一篇文章,如图:



每一个子div中都包含一篇文章的标题,链接,阅读次数,是否为原创,评论数等信息,我们只需要取出标题和链接就够了。如何取出不难,学过正则表达式应该都会。我们再使用个数组将界面中所有的文章名及其链接保存即可。

这里需要注意的是,如果博客有分页怎么办,我们还需要获取分页的下一页中的文章的链接?

我尝试了两种方法,第一种方法是设定一个article_list字典,字典成员为‘下一页链接和是否已经被访问标识键值对’,初始放入首页链接,每处理一个界面时将该链接的值设为访问,之后查找下一页的链接,如果其不在字典里,就将其加入并设访问标识为0。

比如初始字典为article_list={‘/pongba/article/list/1’:False},在处理/pongba/article/list/1这个界面时设值为True,此时又发现了/pongba/article/list/2和/pongba/article/list/3。此时,我们判断字典(has_key())中是没有这两个键的,就加入,并设其值为False。之后遍历(keys())字典,如果有值为0的链接,则访问该链接,重复。

第二种方法:在分页的html代码中给出了分页的页数,我们提取出页数pagenum,结合/pongba/article/list/num,num为页数,值为[1,pagenum]。通过这个链接即可取出该作者的所有文章了。

我代码中采用了第二种方法,第一种方法试了,也可以。


代码介绍:

CsdnArticle类(article.py),封装成一篇文章必须的东西,便于保存和访问一个文章的属性。

我重写了__str__()方法,便于输入。

#-*- coding:utf-8 -*-
class CsdnArticle(object):
	def __init__(self):
		#作者
		self.author = ''
		#博客文章名
		self.title = ''
		#博客链接
		self.href = ''
		#博客内容
		self.body = ''
	#字符串化
	def __str__(self):
		return self.author + '\t' + self.title + '\t' + self.href + '\t' + self.body

CsdnCrawler类。封装了爬取csdn博客所有链接的操作。

#-*- coding:utf-8 -*-
import sys
import urllib
import urllib2
import re
from bs4 import BeautifulSoup
from article import CsdnArticle

reload(sys)
sys.setdefaultencoding('utf-8')

class CsdnCrawler(object):
	#默认访问我的博客
	def __init__(self, author = 'whiterbear'):
		self.author = author
		self.domain = 'http://blog.youkuaiyun.com/'
		self.headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36'}
		#存储文章对象数组
		self.articles = []
	
	#给定url,得到所有的文章lists
	def getArticleLists(self, url= None):
		req = urllib2.Request(url, headers=self.headers)
		response = urllib2.urlopen(req)

		soup = BeautifulSoup(''.join(response.read()))
		listitem =  soup.find(id='article_list').find_all(attrs={'class':r'list_item article_item'})
		#链接的正则表达式,可以匹配链接
		href_regex = r'href="(.*?)"'
		for i,item in enumerate(listitem):
			enitem = item.find(attrs={'class':'link_title'}).contents[0].contents[0]
			href = re.search(href_regex,str(item.find(attrs={'class':'link_title'}).contents[0])).group(1)
			#我们将获取的一篇文章信息封装成一个对象,然后存入数组中
			art = CsdnArticle()
			art.author = self.author
			art.title = enitem.lstrip()
			art.href = (self.domain + href[1:]).lstrip()
			self.articles.append(art)


	def getPageLists(self, url= None):
		url = 'http://blog.youkuaiyun.com/%s?viewmode=list'%self.author
		req = urllib2.Request(url, headers=self.headers)
		response = urllib2.urlopen(req)

		soup = BeautifulSoup(''.join(response.read()))
		num_regex = '[1-9]\d*'
		pagelist = soup.find(id='papelist')
		self.getArticleLists(url)
		
		#如果该作者博客多,有分页的话
		if pagelist:
			pagenum = int(re.findall(num_regex, pagelist.contents[1].contents[0])[1])
			for i in range(2, pagenum + 1):
				self.getArticleLists(self.domain + self.author + '/article/list/%s'%i)
		

	def mytest(self):
		for i,url in enumerate(self.articles):
			print i,url

def main():
	#可以将pongba换成你的博客名,也可以不填,为空,这样默认是访问我的博客
	csdn = CsdnCrawler(author='pongba')#'pongba'
	csdn.getPageLists()
	csdn.mytest()

if __name__ == '__main__':
	main()<span style="font-family:Verdana;font-size:18px;">
</span>

结果:



输出了126条数据。

 

选择摘要视图的解释:当某用户文章多有分页时,访问目录视图界面中的下一页链接时会跳转到摘要视图的下一页链接中。我这么说你可能不太明白,举个例子吧。

我使用刘未鹏学长(我崇拜的)的博客为例子吧,地址:http://blog.youkuaiyun.com/pongba。他的文章很多,有分页。选择他界面中的目录视图后,翻到分页链接出。如下图:

其中的分页链接值为:



可以看出下一页的链接为:http://blog.youkuaiyun.com +/pongba/article/list/2.

当我们在浏览器输入这个网址回车后是出现这个结果的:



可以看到第一篇文章为“斯托克代尔悖论与底线思考法”

然而,当我们使用程序打开的结果却是:



而这个结果却和摘要视图的第二页结果一样:


所以,如果你试图用程序使用http://blog.youkuaiyun.com/pongba/article/list/2这个链接访问,得到的结果却并不是目录视图的结果。我没能理解为什么,纠结了好久程序为什么出错了,后来换成摘要视图了。

 

未完待续。


您可能感兴趣的与本文相关的镜像

Python3.11

Python3.11

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

<think>好的,用户想用Python编写爬虫来抓取优快云的数据。首先,我需要回忆一下相关的知识和之前提供的引用内容。根据引用[3],使用Scrapy框架可以爬取优快云个人主页的文章列表,并且已经实现了自动翻页,保存为JSON文件。所以Scrapy可能是一个好的选择,不过用户可能想要更基础的实现,比如使用requests和BeautifulSoup。 用户可能对Scrapy不熟悉,或者想先尝试简单的方法。我需要先确认是否需要登录或者处理反爬机制。优快云可能会有反爬措施,比如检查User-Agent,或者需要登录才能访问某些页面。所以第一步应该设置请求头,模拟浏览器访问,避免被拒绝。 接下来,分析目标网页结构。假设用户想爬取个人主页的文章列表,比如https://blog.csdn.net/用户名/article/list/1。需要查看页面结构,找到文章标题、链接、发布时间等信息的HTML标签。可能需要用开发者工具查看元素,找到对应的CSS选择器或XPath。 然后,处理分页。文章列表通常分页显示,需要循环请求每一页,直到没有更多页面。可以通过检查“下一页”按钮的链接是否存在,或者根据页码递增直到获取不到内容。 另外,引用[2]提到requests库的post和get方法,但这里应该是GET请求获取页面内容。需要正确解析响应内容,提取所需数据。 还要注意频率控制,避免过快请求导致IP被封。可以添加延时,比如time.sleep。 最后,保存数据,可能用JSON或CSV格式。根据引用[3],Scrapy保存为JSON,但使用普通脚本的话,可以用json模块处理。 可能的步骤是: 1. 导入requests和BeautifulSoup库。 2. 设置请求头,包括User-Agent。 3. 发送GET请求获取页面内容。 4. 解析HTML,提取文章信息。 5. 处理分页,循环请求所有页面。 6. 保存数据到文件。 需要注意的是,优快云的robots.txt是否允许爬取,以及法律合规性。用户需遵守网站规定,避免侵犯版权。 现在,整理这些步骤,给出示例代码,并提醒注意事项。同时,根据用户提供的引用,引用[3]提到Scrapy的实现,可以补充说明如果使用Scrapy会更高效,但示例中使用基础方法。 可能的问题:如何处理动态加载的内容?如果文章列表是AJAX加载的,可能需要分析接口,使用requests直接调用API。但假设目标页面是静态的,可以直接解析HTML。 综上,分步骤解释,给出代码示例,并生成相关问题。</think>### 分步实现优快云网页爬虫 #### 1. 准备工作 安装所需库: ```bash pip install requests beautifulsoup4 ``` #### 2. 设置请求头与目标URL ```python import requests from bs4 import BeautifulSoup import time headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" } base_url = "https://blog.csdn.net/用户名/article/list/{}" ``` #### 3. 定义解析函数 ```python def parse_articles(html): soup = BeautifulSoup(html, 'html.parser') articles = [] for item in soup.select('.article-list .article-item-box'): title = item.select_one('a').text.strip() link = item.select_one('a')['href'] date = item.select_one('.date').text.strip() articles.append({"title": title, "link": link, "date": date}) return articles ``` #### 4. 实现自动翻页 ```python def crawl_csdn_articles(max_page=5): all_articles = [] page = 1 while page <= max_page: url = base_url.format(page) response = requests.get(url, headers=headers) if response.status_code == 200: articles = parse_articles(response.text) if not articles: # 无内容时停止 break all_articles.extend(articles) print(f"已抓取第{page}页,共{len(articles)}篇文章") page += 1 time.sleep(1) # 降低请求频率 else: print(f"请求失败,状态码:{response.status_code}") break return all_articles ``` #### 5. 保存数据 ```python import json articles = crawl_csdn_articles() with open('csdn_articles.json', 'w', encoding='utf-8') as f: json.dump(articles, f, ensure_ascii=False, indent=2) ``` #### 注意事项 - **反爬机制**:需添加`Cookie`头部(需登录时) - **动态内容**:若遇动态加载,需改用`selenium` - **法律合规**:遵守`robots.txt`协议 [^1]: 引用自示例中的快速排序说明 [^2]: 参考requests库的POST方法说明 [^3]: Scrapy框架实现优快云爬虫的案例
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值