这种网页怎么爬取网页乱码

  注:如果代码中有冗余,错误或者不规范,欢迎指正。
Java简单实现:爬取网页并且保存
  对于网络,我一直处于好奇的态度。以前一直想着写个爬虫,但是一拖再拖,懒得实现,感觉这是一个很麻烦的事情,出现个小错误,就要调试很多时间,太浪费时间。
  后来一想,既然早早给自己下了保证,就先实现它吧,从简单开始,慢慢增加功能,有时间就实现一个,并且随时优化代码。
  下面是我简单实现爬取指定网页,并且保存的简单实现,其实有几种方式可以实现,这里慢慢添加该功能的几种实现方式。
UrlConnection爬取实现
import java.io.BufferedR
import java.io.FileOutputS
import java.io.FileW
import java.io.IOE
import java.io.InputS
import java.io.InputStreamR
import java.io.OutputStreamW
import java.net.MalformedURLE
import java.net.URL;
import java.net.URLC
public class Spider {
public static void main(String[] args) {
String filepath = "d:/124.html";
String url_str = "http://www.hao123.com/";
URL url = null;
url = new URL(url_str);
} catch (MalformedURLException e) {
e.printStackTrace();
String charset = "utf-8";
int sec_cont = 1000;
URLConnection url_con = url.openConnection();
url_con.setDoOutput(true);
url_con.setReadTimeout(10 * sec_cont);
url_con.setRequestProperty("User-Agent", "Mozilla/4.0 ( MSIE 7.0; Windows NT 5.1)");
InputStream htm_in = url_con.getInputStream();
String htm_str = InputStream2String(htm_in,charset);
saveHtml(filepath,htm_str);
} catch (IOException e) {
e.printStackTrace();
* Method: saveHtml
* Description: save String to file
* @param filepath
* file path which need to be saved
* @param str
* string saved
public static void saveHtml(String filepath, String str){
/*@SuppressWarnings("resource")
FileWriter fw = new FileWriter(filepath);
fw.write(str);
fw.flush();*/
OutputStreamWriter outs = new OutputStreamWriter(new FileOutputStream(filepath, true), "utf-8");
outs.write(str);
System.out.print(str);
outs.close();
} catch (IOException e) {
System.out.println("Error at save html...");
e.printStackTrace();
* Method: InputStream2String
* Description: make InputStream to String
* @param in_st
* inputstream which need to be converted
* @param charset
* encoder of value
* @throws IOException
* if an error occurred
public static String InputStream2String(InputStream in_st,String charset) throws IOException{
BufferedReader buff = new BufferedReader(new InputStreamReader(in_st, charset));
StringBuffer res = new StringBuffer();
String line = "";
while((line = buff.readLine()) != null){
res.append(line);
return res.toString();
实现过程中,爬取的网页的中文乱码问题,是个比较麻烦的事情。
HttpClient爬取实现
HttpClient实现爬取网页时,遇到了很多问题。其一,就是存在两个版本的HttpClient,一个是sun内置的,另一个是apache开源的一个项目,似乎sun内置用的不太多,我也就没有实现,而是采用了apache开源项目(以后说的HttpClient都是指apache的开源版本);其二,在使用HttpClient时,最新的版本已经不同于以前的版本,从HttpClient4.x版本后,导入的包就已经不一样了,从网上找的很多部分都是HttpClient3.x版本的,所以如果使用最新的版本,还是看帮助文件为好。
我用的是Eclipse,需要配置环境导入引用包。
首先,下载HttpClient,地址是:,我是用的事HttpClient4.2版本。
然后,解压缩,找到了/lib文件夹下的commons-codec-1.6.jar,commons-logging-1.1.1.jar,httpclient-4.2.5.jar,httpcore-4.2.4.jar(版本号根据下载的版本有所不同,还有其他的jar文件,我这里暂时用不到,所以先导入必须的);
最后,将上面的jar文件,加入classpath中,即右击工程文件 =& Bulid Path =& Configure Build Path =& Add External Jar..,然后添加上面的包就可以了。
&还用一种方法就是讲上面的包,直接复制到工程文件夹下的lib文件夹中。
下面是实现代码:
import java.io.BufferedR
import java.io.FileOutputS
import java.io.IOE
import java.io.InputS
import java.io.InputStreamR
import java.io.OutputStreamW
import org.apache.http.HttpE
import org.apache.http.HttpR
import org.apache.http.client.*;
import org.apache.http.client.methods.HttpG
import org.apache.http.impl.client.DefaultHttpC
public class SpiderHttpClient {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
String url_str = "http://www.hao123.com";
String charset = "utf-8";
String filepath = "d:/125.html";
HttpClient hc = new DefaultHttpClient();
HttpGet hg = new HttpGet(url_str);
HttpResponse response = hc.execute(hg);
HttpEntity entity = response.getEntity();
InputStream htm_in = null;
if(entity != null){
System.out.println(entity.getContentLength());
htm_in = entity.getContent();
String htm_str = InputStream2String(htm_in,charset);
saveHtml(filepath,htm_str);
* Method: saveHtml
* Description: save String to file
* @param filepath
* file path which need to be saved
* @param str
* string saved
public static void saveHtml(String filepath, String str){
/*@SuppressWarnings("resource")
FileWriter fw = new FileWriter(filepath);
fw.write(str);
fw.flush();*/
OutputStreamWriter outs = new OutputStreamWriter(new FileOutputStream(filepath, true), "utf-8");
outs.write(str);
outs.close();
} catch (IOException e) {
System.out.println("Error at save html...");
e.printStackTrace();
* Method: InputStream2String
* Description: make InputStream to String
* @param in_st
* inputstream which need to be converted
* @param charset
* encoder of value
* @throws IOException
* if an error occurred
public static String InputStream2String(InputStream in_st,String charset) throws IOException{
BufferedReader buff = new BufferedReader(new InputStreamReader(in_st, charset));
StringBuffer res = new StringBuffer();
String line = "";
while((line = buff.readLine()) != null){
res.append(line);
return res.toString();
&题外话:如果想下载Apache开源项目的源码或者二进制码,可以进入链接:
阅读(...) 评论()
Copyright at 2012 yangwenlong功能的可行性:从http协议到tcp协议,相信大家做过计算机网络的FTP大实验对protocol 这个术语有了更加深刻的了解了。所以我们只要遵循相应的协议,获取一个网页上的内容就是很容易的了, 所谓的DOS(denial-of-service)攻击也不过是这样么,我们如果有用户名和密码,他不让我们登录才不科学呢。知道了这点,突然心潮澎湃,只要他是个网页注定要对我们打开大门,但是能光能入门还不行,还得知道人家的规矩,不然人家还是会拒客的,就像到餐馆吃饭,他得让你进去,不让你进去就是侵犯人权,闹大了还的上美国法院或许都能得到天价赔偿,但是你如果在门口张牙舞爪,不符合规矩,保安叔叔还是会请您回避的~所以下面我们还得老老实实看如何遵循服务器的要求进行爬取网页。
首先, 如果这个网页不需要登录,把你的url拷贝到服务器上就能加载下来网页,那样就比较简单了。使用python 一句话:
  content = urllib2.urlopen(url).read()
content就是我们要访问的网页了。
如果需要登录呢?也很简单把表单填好就可以了。这次有些复杂,不过还是可以写成一句话:
urllib2.urlopen(urllib2.Request(url, urllib.urlencode(params))).read()
其中params是你要提交的表单数据。
哈哈,太简单了,赶紧启动个python gui去爬info.tsinghua.edu.cn吧, 忙碌一番发现,搞不定啊,进不去,哭泣。。。。。。。。。。。。
只见info大喝一声,info重地,岂容尔等小儿放肆!
遭遇当头一喝的我们赶紧检查我们的过程出现了什么问题?怎么才能登录info呢?还是看看我们通过浏览器登录的时候出现了都上缴了什么买路钱吧。
果然info还是留了一手,在你的提交表单中多了2项,x,y, x,y有什么用处,没发现,人就这么着了,你怎么滴吧。
ok,发现了这个小问题知道怎么搞了吧,把你的参数多加一项啊。改好之后,怀着忐忑的心情,应该是这样了吧,然后。。。唉,下载下来的不是你登录后的页面,还是登录之前的页面。
好吧,还有什么问题呢?Cookie。这是防止非法登录的另一个手段。这个问题好复杂啊,所以一句话搞不定了,好吧,牺牲一下,3句话搞定吧。
spider = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookielib.LWPCookieJar()))urllib2.install_opener(spider)content = spider.open(urllib2.Request(url, params)).read()
获得了网页代码之后怎么解析网页呢?推荐一个利器中的利器&&pyquery.使用python封装了一遍jquery的所有操作。好吧,我服了,写一个网页并解析一共用了不到10行代码。。。这真实我们程序猿的福音啊!
-----------------------------
School of Software, Tsinghua.
Mails: u-wang11@mails.tsinghua.edu.cn
阅读(...) 评论()《Python3网络爬虫开发实战》抽奖赠书活动正在进行中!详情请戳!欢迎参与!非常感谢!
> Python爬虫实战一之爬取糗事百科段子
大家好,前面入门已经说了那么多基础知识了,下面我们做几个实战项目来挑战一下吧。那么这次为大家带来,Python爬取糗事百科的小段子的例子。
首先,糗事百科大家都听说过吧?糗友们发的搞笑的段子一抓一大把,这次我们尝试一下用爬虫把他们抓取下来。
糗事百科在前一段时间进行了改版,导致之前的代码没法用了,会导致无法输出和CPU占用过高的情况,是因为正则表达式没有匹配到的缘故。
现在,博主已经对程序进行了重新修改,代码亲测可用,包括截图和说明,之前一直在忙所以没有及时更新,望大家海涵!
更新时间:
糗事百科又又又又改版了,博主已经没心再去一次次匹配它了,如果大家遇到长时间运行不出结果也不报错的情况,请大家参考最新的评论,热心小伙伴提供的正则来修改下吧~
更新时间:
1.抓取糗事百科热门段子
2.过滤带有图片的段子
3.实现每按一次回车显示一个段子的发布时间,发布人,段子内容,点赞数。
糗事百科是不需要登录的,所以也没必要用到Cookie,另外糗事百科有的段子是附图的,我们把图抓下来图片不便于显示,那么我们就尝试过滤掉有图的段子吧。
好,现在我们尝试抓取一下糗事百科的热门段子吧,每按下一次回车我们显示一个段子。
1.确定URL并抓取页面代码
首先我们确定好页面的URL是 http://www.qiushibaike.com/hot/page/1,其中最后一个数字1代表页数,我们可以传入不同的值来获得某一页的段子内容。
我们初步构建如下的代码来打印页面代码内容试试看,先构造最基本的页面抓取方式,看看会不会成功
# -*- coding:utf-8 -*-
import urllib
import urllib2
url = 'http://www.qiushibaike.com/hot/page/' + str(page)
request = urllib2.Request(url)
response = urllib2.urlopen(request)
print response.read()
except urllib2.URLError, e:
if hasattr(e,"code"):
print e.code
if hasattr(e,"reason"):
print e.reason
12345678910111213141516
# -*- coding:utf-8 -*-import urllibimport urllib2&&page = 1url = 'http://www.qiushibaike.com/hot/page/' + str(page)try:&&&&request = urllib2.Request(url)&&&&response = urllib2.urlopen(request)&&&&print response.read()except urllib2.URLError, e:&&&&if hasattr(e,"code"):&&&&&&&&print e.code&&&&if hasattr(e,"reason"):&&&&&&&&print e.reason
运行程序,哦不,它竟然报错了,真是时运不济,命途多舛啊
line 373, in _read_status
raise BadStatusLine(line)
httplib.BadStatusLine: ''
line 373, in _read_status raise BadStatusLine(line)httplib.BadStatusLine: ''
好吧,应该是headers验证的问题,我们加上一个headers验证试试看吧,将代码修改如下
# -*- coding:utf-8 -*-
import urllib
import urllib2
url = 'http://www.qiushibaike.com/hot/page/' + str(page)
user_agent = 'Mozilla/4.0 ( MSIE 5.5; Windows NT)'
headers = { 'User-Agent' : user_agent }
request = urllib2.Request(url,headers = headers)
response = urllib2.urlopen(request)
print response.read()
except urllib2.URLError, e:
if hasattr(e,"code"):
print e.code
if hasattr(e,"reason"):
print e.reason
1234567891011121314151617
# -*- coding:utf-8 -*-import urllibimport urllib2&page = 1url = 'http://www.qiushibaike.com/hot/page/' + str(page)user_agent = 'Mozilla/4.0 ( MSIE 5.5; Windows NT)'headers = { 'User-Agent' : user_agent }try:&&&&request = urllib2.Request(url,headers = headers)&&&&response = urllib2.urlopen(request)&&&&print response.read()except urllib2.URLError, e:&&&&if hasattr(e,"code"):&&&&&&&&print e.code&&&&if hasattr(e,"reason"):&&&&&&&&print e.reason
嘿嘿,这次运行终于正常了,打印出了第一页的HTML代码,大家可以运行下代码试试看。在这里运行结果太长就不贴了。
2.提取某一页的所有段子
好,获取了HTML代码之后,我们开始分析怎样获取某一页的所有段子。
首先我们审查元素看一下,按浏览器的F12,截图如下
我们可以看到,每一个段子都是&div class=”article block untagged mb15″ id=”…”&…&/div&包裹的内容。
现在我们想获取发布人,发布日期,段子内容,以及点赞的个数。不过另外注意的是,段子有些是带图片的,如果我们想在控制台显示图片是不现实的,所以我们直接把带有图片的段子给它剔除掉,只保存仅含文本的段子。
所以我们加入如下正则表达式来匹配一下,用到的方法是 re.findall 是找寻所有匹配的内容。方法的用法详情可以看前面说的正则表达式的介绍。
好,我们的正则表达式匹配语句书写如下,在原来的基础上追加如下代码
content = response.read().decode('utf-8')
pattern = re.compile('&div.*?author"&.*?&a.*?&img.*?&(.*?)&/a&.*?&div.*?'+
'content"&(.*?)&!--(.*?)--&.*?&/div&(.*?)&div class="stats.*?class="number"&(.*?)&/i&',re.S)
items = re.findall(pattern,content)
for item in items:
print item[0],item[1],item[2],item[3],item[4]
content = response.read().decode('utf-8')pattern = re.compile('&div.*?author"&.*?&a.*?&img.*?&(.*?)&/a&.*?&div.*?'+&&&&&&&&&&&&&&&&&&&&&&&& 'content"&(.*?)&!--(.*?)--&.*?&/div&(.*?)&div class="stats.*?class="number"&(.*?)&/i&',re.S)items = re.findall(pattern,content)for item in items:&&&&print item[0],item[1],item[2],item[3],item[4]
现在正则表达式在这里稍作说明
1).*? 是一个固定的搭配,.和*代表可以匹配任意无限多个字符,加上?表示使用非贪婪模式进行匹配,也就是我们会尽可能短地做匹配,以后我们还会大量用到 .*? 的搭配。
2)(.*?)代表一个分组,在这个正则表达式中我们匹配了五个分组,在后面的遍历item中,item[0]就代表第一个(.*?)所指代的内容,item[1]就代表第二个(.*?)所指代的内容,以此类推。
3)re.S 标志代表在匹配时为点任意匹配模式,点 . 也可以代表换行符。
这样我们就获取了发布人,发布时间,发布内容,附加图片以及点赞数。
在这里注意一下,我们要获取的内容如果是带有图片,直接输出出来比较繁琐,所以这里我们只获取不带图片的段子就好了。
所以,在这里我们就需要对带图片的段子进行过滤。
我们可以发现,带有图片的段子会带有类似下面的代码,而不带图片的则没有,所以,我们的正则表达式的item[3]就是获取了下面的内容,如果不带图片,item[3]获取的内容便是空。
&div class="thumb"&
&a href="/article/?list=hot&s=4794990" target="_blank"&
&img src="http://pic.qiushibaike.com/system/pictures/287/medium/app.jpg" alt="但他们依然乐观"&
&div class="thumb"&&&a href="/article/?list=hot&s=4794990" target="_blank"&&img src="http://pic.qiushibaike.com/system/pictures/287/medium/app.jpg" alt="但他们依然乐观"&&/a&&&/div&
所以我们只需要判断item[3]中是否含有img标签就可以了。
好,我们再把上述代码中的for循环改为下面的样子
for item in items:
haveImg = re.search("img",item[3])
if not haveImg:
print item[0],item[1],item[2],item[4]
for item in items:&&&&&&&&haveImg = re.search("img",item[3])&&&&&&&&if not haveImg:&&&&&&&&&&&&print item[0],item[1],item[2],item[4]
现在,整体的代码如下
# -*- coding:utf-8 -*-
import urllib
import urllib2
url = 'http://www.qiushibaike.com/hot/page/' + str(page)
user_agent = 'Mozilla/4.0 ( MSIE 5.5; Windows NT)'
headers = { 'User-Agent' : user_agent }
request = urllib2.Request(url,headers = headers)
response = urllib2.urlopen(request)
content = response.read().decode('utf-8')
pattern = re.compile('&div.*?author"&.*?&a.*?&img.*?&(.*?)&/a&.*?&div.*?'+
'content"&(.*?)&!--(.*?)--&.*?&/div&(.*?)&div class="stats.*?class="number"&(.*?)&/i&',re.S)
items = re.findall(pattern,content)
for item in items:
haveImg = re.search("img",item[3])
if not haveImg:
print item[0],item[1],item[2],item[4]
except urllib2.URLError, e:
if hasattr(e,"code"):
print e.code
if hasattr(e,"reason"):
print e.reason
12345678910111213141516171819202122232425
# -*- coding:utf-8 -*-import urllibimport urllib2import re&page = 1url = 'http://www.qiushibaike.com/hot/page/' + str(page)user_agent = 'Mozilla/4.0 ( MSIE 5.5; Windows NT)'headers = { 'User-Agent' : user_agent }try:&&&&request = urllib2.Request(url,headers = headers)&&&&response = urllib2.urlopen(request)&&&&content = response.read().decode('utf-8')&&&&pattern = re.compile('&div.*?author"&.*?&a.*?&img.*?&(.*?)&/a&.*?&div.*?'+&&&&&&&&&&&&&&&&&&&&&&&& 'content"&(.*?)&!--(.*?)--&.*?&/div&(.*?)&div class="stats.*?class="number"&(.*?)&/i&',re.S)&&&&items = re.findall(pattern,content)&&&&for item in items:&&&&&&&&haveImg = re.search("img",item[3])&&&&&&&&if not haveImg:&&&&&&&&&&&&print item[0],item[1],item[2],item[4]except urllib2.URLError, e:&&&&if hasattr(e,"code"):&&&&&&&&print e.code&&&&if hasattr(e,"reason"):&&&&&&&&print e.reason
运行一下看下效果
恩,带有图片的段子已经被剔除啦。是不是很开森?
3.完善交互,设计面向对象模式
好啦,现在最核心的部分我们已经完成啦,剩下的就是修一下边边角角的东西,我们想达到的目的是:
按下回车,读取一个段子,显示出段子的发布人,发布日期,内容以及点赞个数。
另外我们需要设计面向对象模式,引入类和方法,将代码做一下优化和封装,最后,我们的代码如下所示
__author__ = 'CQC'
# -*- coding:utf-8 -*-
import urllib
import urllib2
import thread
import time
#糗事百科爬虫类
class QSBK:
#初始化方法,定义一些变量
def __init__(self):
self.pageIndex = 1
self.user_agent = 'Mozilla/4.0 ( MSIE 5.5; Windows NT)'
#初始化headers
self.headers = { 'User-Agent' : self.user_agent }
#存放段子的变量,每一个元素是每一页的段子们
self.stories = []
#存放程序是否继续运行的变量
self.enable = False
#传入某一页的索引获得页面代码
def getPage(self,pageIndex):
url = 'http://www.qiushibaike.com/hot/page/' + str(pageIndex)
#构建请求的request
request = urllib2.Request(url,headers = self.headers)
#利用urlopen获取页面代码
response = urllib2.urlopen(request)
#将页面转化为UTF-8编码
pageCode = response.read().decode('utf-8')
return pageCode
except urllib2.URLError, e:
if hasattr(e,"reason"):
print u"连接糗事百科失败,错误原因",e.reason
return None
#传入某一页代码,返回本页不带图片的段子列表
def getPageItems(self,pageIndex):
pageCode = self.getPage(pageIndex)
if not pageCode:
print "页面加载失败...."
return None
pattern = re.compile('&div.*?author"&.*?&a.*?&img.*?&(.*?)&/a&.*?&div.*?'+
'content"&(.*?)&!--(.*?)--&.*?&/div&(.*?)&div class="stats.*?class="number"&(.*?)&/i&',re.S)
items = re.findall(pattern,pageCode)
#用来存储每页的段子们
pageStories = []
#遍历正则表达式匹配的信息
for item in items:
#是否含有图片
haveImg = re.search("img",item[3])
#如果不含有图片,把它加入list中
if not haveImg:
replaceBR = re.compile('&br/&')
text = re.sub(replaceBR,"\n",item[1])
#item[0]是一个段子的发布者,item[1]是内容,item[2]是发布时间,item[4]是点赞数
pageStories.append([item[0].strip(),text.strip(),item[2].strip(),item[4].strip()])
return pageStories
#加载并提取页面的内容,加入到列表中
def loadPage(self):
#如果当前未看的页数少于2页,则加载新一页
if self.enable == True:
if len(self.stories) & 2:
#获取新一页
pageStories = self.getPageItems(self.pageIndex)
#将该页的段子存放到全局list中
if pageStories:
self.stories.append(pageStories)
#获取完之后页码索引加一,表示下次读取下一页
self.pageIndex += 1
#调用该方法,每次敲回车打印输出一个段子
def getOneStory(self,pageStories,page):
#遍历一页的段子
for story in pageStories:
#等待用户输入
input = raw_input()
#每当输入回车一次,判断一下是否要加载新页面
self.loadPage()
#如果输入Q则程序结束
if input == "Q":
self.enable = False
print u"第%d页\t发布人:%s\t发布时间:%s\t赞:%s\n%s" %(page,story[0],story[2],story[3],story[1])
def start(self):
print u"正在读取糗事百科,按回车查看新段子,Q退出"
#使变量为True,程序可以正常运行
self.enable = True
#先加载一页内容
self.loadPage()
#局部变量,控制当前读到了第几页
nowPage = 0
while self.enable:
if len(self.stories)&0:
#从全局list中获取一页的段子
pageStories = self.stories[0]
#当前读到的页数加一
nowPage += 1
#将全局list中第一个元素删除,因为已经取出
del self.stories[0]
#输出该页的段子
self.getOneStory(pageStories,nowPage)
spider = QSBK()
spider.start()
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
__author__ = 'CQC'# -*- coding:utf-8 -*-import urllibimport urllib2import reimport threadimport time&#糗事百科爬虫类class QSBK:&&&&&#初始化方法,定义一些变量&&&&def __init__(self):&&&&&&&&self.pageIndex = 1&&&&&&&&self.user_agent = 'Mozilla/4.0 ( MSIE 5.5; Windows NT)'&&&&&&&&#初始化headers&&&&&&&&self.headers = { 'User-Agent' : self.user_agent }&&&&&&&&#存放段子的变量,每一个元素是每一页的段子们&&&&&&&&self.stories = []&&&&&&&&#存放程序是否继续运行的变量&&&&&&&&self.enable = False&&&&#传入某一页的索引获得页面代码&&&&def getPage(self,pageIndex):&&&&&&&&try:&&&&&&&&&&&&url = 'http://www.qiushibaike.com/hot/page/' + str(pageIndex)&&&&&&&&&&&&#构建请求的request&&&&&&&&&&&&request = urllib2.Request(url,headers = self.headers)&&&&&&&&&&&&#利用urlopen获取页面代码&&&&&&&&&&&&response = urllib2.urlopen(request)&&&&&&&&&&&&#将页面转化为UTF-8编码&&&&&&&&&&&&pageCode = response.read().decode('utf-8')&&&&&&&&&&&&return pageCode&&&&&&&&&except urllib2.URLError, e:&&&&&&&&&&&&if hasattr(e,"reason"):&&&&&&&&&&&&&&&&print u"连接糗事百科失败,错误原因",e.reason&&&&&&&&&&&&&&&&return None&&&&&&#传入某一页代码,返回本页不带图片的段子列表&&&&def getPageItems(self,pageIndex):&&&&&&&&pageCode = self.getPage(pageIndex)&&&&&&&&if not pageCode:&&&&&&&&&&&&print "页面加载失败...."&&&&&&&&&&&&return None&&&&&&&&pattern = re.compile('&div.*?author"&.*?&a.*?&img.*?&(.*?)&/a&.*?&div.*?'+&&&&&&&&&&&&&&&&&&&&&&&& 'content"&(.*?)&!--(.*?)--&.*?&/div&(.*?)&div class="stats.*?class="number"&(.*?)&/i&',re.S)&&&&&&&&items = re.findall(pattern,pageCode)&&&&&&&&#用来存储每页的段子们&&&&&&&&pageStories = []&&&&&&&&#遍历正则表达式匹配的信息&&&&&&&&for item in items:&&&&&&&&&&&&#是否含有图片&&&&&&&&&&&&haveImg = re.search("img",item[3])&&&&&&&&&&&&#如果不含有图片,把它加入list中&&&&&&&&&&&&if not haveImg:&&&&&&&&&&&&&&&&replaceBR = re.compile('&br/&')&&&&&&&&&&&&&&&&text = re.sub(replaceBR,"\n",item[1])&&&&&&&&&&&&&&&&#item[0]是一个段子的发布者,item[1]是内容,item[2]是发布时间,item[4]是点赞数&&&&&&&&&&&&&&&&pageStories.append([item[0].strip(),text.strip(),item[2].strip(),item[4].strip()])&&&&&&&&return pageStories&&&&&#加载并提取页面的内容,加入到列表中&&&&def loadPage(self):&&&&&&&&#如果当前未看的页数少于2页,则加载新一页&&&&&&&&if self.enable == True:&&&&&&&&&&&&if len(self.stories) & 2:&&&&&&&&&&&&&&&&#获取新一页&&&&&&&&&&&&&&&&pageStories = self.getPageItems(self.pageIndex)&&&&&&&&&&&&&&&&#将该页的段子存放到全局list中&&&&&&&&&&&&&&&&if pageStories:&&&&&&&&&&&&&&&&&&&&self.stories.append(pageStories)&&&&&&&&&&&&&&&&&&&&#获取完之后页码索引加一,表示下次读取下一页&&&&&&&&&&&&&&&&&&&&self.pageIndex += 1&&&&&&&&#调用该方法,每次敲回车打印输出一个段子&&&&def getOneStory(self,pageStories,page):&&&&&&&&#遍历一页的段子&&&&&&&&for story in pageStories:&&&&&&&&&&&&#等待用户输入&&&&&&&&&&&&input = raw_input()&&&&&&&&&&&&#每当输入回车一次,判断一下是否要加载新页面&&&&&&&&&&&&self.loadPage()&&&&&&&&&&&&#如果输入Q则程序结束&&&&&&&&&&&&if input == "Q":&&&&&&&&&&&&&&&&self.enable = False&&&&&&&&&&&&&&&&return&&&&&&&&&&&&print u"第%d页\t发布人:%s\t发布时间:%s\t赞:%s\n%s" %(page,story[0],story[2],story[3],story[1])&&&&&&&&#开始方法&&&&def start(self):&&&&&&&&print u"正在读取糗事百科,按回车查看新段子,Q退出"&&&&&&&&#使变量为True,程序可以正常运行&&&&&&&&self.enable = True&&&&&&&&#先加载一页内容&&&&&&&&self.loadPage()&&&&&&&&#局部变量,控制当前读到了第几页&&&&&&&&nowPage = 0&&&&&&&&while self.enable:&&&&&&&&&&&&if len(self.stories)&0:&&&&&&&&&&&&&&&&#从全局list中获取一页的段子&&&&&&&&&&&&&&&&pageStories = self.stories[0]&&&&&&&&&&&&&&&&#当前读到的页数加一&&&&&&&&&&&&&&&&nowPage += 1&&&&&&&&&&&&&&&&#将全局list中第一个元素删除,因为已经取出&&&&&&&&&&&&&&&&del self.stories[0]&&&&&&&&&&&&&&&&#输出该页的段子&&&&&&&&&&&&&&&&self.getOneStory(pageStories,nowPage)&&spider = QSBK()spider.start()
好啦,大家来测试一下吧,点一下回车会输出一个段子,包括发布人,发布时间,段子内容以及点赞数,是不是感觉爽爆了!
我们第一个爬虫实战项目介绍到这里,欢迎大家继续关注,小伙伴们加油!
转载请注明: &
or分享 (0)
想学更多爬虫知识?《Python3网络爬虫开发实战》这本书也许更适合你~
or立即购买
我的个人微信公众号
扫码或搜索:进击的Coder
进击的Coder
微信公众号
扫一扫关注
想结交更多的朋友吗?
来进击的Coder瞧瞧吧
进击的Coder
进击的Coder灌水太多?
这里是纯粹的技术领地
激进的Coder
您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请狠狠点击下面的

我要回帖

更多关于 数据爬取技术 的文章

 

随机推荐