日期:2020.01.22

博客期:130

星期三

  【代码说明,如果要使用此页代码,必须在本博客页面评论区给予说明】

  //博客总体说明

  1、准备工作(本期博客)

  2、爬取工作

  3、数据处理

  4、信息展示

  今天来说一说爬取的工作进展,我们的要求是爬取首都之窗的信件类型,那么我们就开始吧!

  首先,先找到网页:http://www.beijing.gov.cn/hudong/hdjl/com.web.search.mailList.flow

  然后找到网页的结构,发现是简单的HTML结构,那我们就可以启动Scrapy框架了。

  前边说了,之前是一直报403 Forbidden的错,原因我已经找到了!因为广大运营网站不可能希望各个程序员都能够轻易爬走自己的数据,那么怎么办呢?诶~他就对每个请求访问的用户进行检查,发现有一类用户什么都没有,就是想访问,网站一看到这种用户心里可真不是滋味,就会断定“你是来爬我的数据的”,你自然就被网站服务器禁掉了!人家有了“政策”,我们程序员就要想对策是吧!诶,我们可以在爬取的时候,模拟添加一个header,让服务器误认为我们是人,我们应该得到数据!

  

  进行改造:(这是截图没有错,到时候我会给你们代码的)

  

  嗯,现在服务器终于肯乖乖听话了!

  先来看我们的基础数据类型:

  

  由此我们可以构造基础的 Bean 类型了(为了方便引入,我就使用Bean当作类名了)

   看代码: 

 # [ 保存的数据格式 ]
class Bean: # 构造方法
def __init__(self,asker,responser,askTime,responseTime,title,questionSupport,responseSupport,responseUnsupport,questionText,responseText):
self.asker = asker
self.responser = responser
self.askTime = askTime
self.responseTime = responseTime
self.title = title
self.questionSupport = questionSupport
self.responseSupport = responseSupport
self.responseUnsupport = responseUnsupport
self.questionText = questionText
self.responseText = responseText # 在控制台输出结果(测试用)
def display(self):
print("提问方:"+self.asker)
print("回答方:"+self.responser)
print("提问时间:" + self.askTime)
print("回答时间:" + self.responseTime)
print("问题标题:" + self.title)
print("问题支持量:" + self.questionSupport)
print("回答点赞数:" + self.responseSupport)
print("回答被踩数:" + self.responseUnsupport)
print("提问具体内容:" + self.questionText)
print("回答具体内容:" + self.responseText) def toString(self):
strs = ""
strs = strs + self.asker;
strs = strs + "\t"
strs = strs + self.responser;
strs = strs + "\t"
strs = strs + self.askTime;
strs = strs + "\t"
strs = strs + self.responseTime;
strs = strs + "\t"
strs = strs + self.title;
strs = strs + self.questionSupport;
strs = strs + "\t"
strs = strs + self.responseSupport;
strs = strs + "\t"
strs = strs + self.responseUnsupport;
strs = strs + "\t"
strs = strs + self.questionText;
strs = strs + "\t"
strs = strs + self.responseText;
return strs # 将信息附加到文件里
def addToFile(self,fpath, model):
f = codecs.open(fpath, model, 'utf-8')
f.write(self.toString()+"\n")
f.close() # --------------------[基础数据]
# 提问方
asker = ""
# 回答方
responser = ""
# 提问时间
askTime = ""
# 回答时间
responseTime = ""
# 问题标题
title = ""
# 问题支持量
questionSupport = ""
# 回答点赞数
responseSupport = ""
# 回答被踩数
responseUnsupport = ""
# 问题具体内容
questionText = ""
# 回答具体内容
responseText = ""

Bean.py

  //-------[代码解析]

  这算是一个中介者,沟通着数据与展示或者数据与文件,这个类相当于是对数据的处理的方法封装

  ... ...

  忘了展示字符串的标签处理封装类了:

 # [ 对字符串的特殊处理方法-集合 ]
class StrSpecialDealer:
@staticmethod
def getReaction(stri):
strs = str(stri).replace(" ","")
strs = strs[strs.find('>')+1:strs.rfind('<')]
strs = strs.replace("\t","")
strs = strs.replace("\r","")
strs = strs.replace("\n","")
return strs

StrSpecialDealer.py

  嗯,之后我们需要想如何根据网页地址来获取html

  比如给定了原网站当中的其中一条比如对应网页:

  需要我们制作一个对应的网站爬取结点类(它的任务是对于已经给定的网页,进行爬取,并封装成我们上述的Bean类型)

  看代码:(省略导包...)

 # [ 信息爬取结点 ]
class DetailConnector:
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36'}
basicURL = "" # ---[定义构造方法]
def __init__(self, url):
self.basicURL = url # 获取 url 的内部 HTML 代码
def getHTMLText(self):
req = request.Request(url=self.basicURL, headers=self.headers)
r = request.urlopen(req).read().decode()
return r # 获取基本数据
def getBean(self):
index_html = self.getHTMLText()
index_sel = parsel.Selector(index_html)
container_div = index_sel.css('div .container')[0]
container_strong = index_sel.css('div strong')[0]
container_retire = index_sel.css('div div div div')[5] #基础数据配置
title = " "
num_supp = " "
question_toBuilder = " "
question_time = " "
support_quert = " "
quText = " "
answer_name = " "
answer_time = " "
answer_text = " "
num_supp = " "
num_unsupp = " " #------------------------------------------------------------------------------------------提问内容
# 获取提问标题
title = str(container_strong.extract())
title = title.replace("<strong>", "")
title = title.replace("</strong>", "") # 获取来信人
container_builder = container_retire.css("div div")
question_toBuilder = str(container_builder.extract()[0])
question_toBuilder = StrSpecialDealer.getReaction(question_toBuilder)
if (question_toBuilder.__contains__("来信人:")):
question_toBuilder = question_toBuilder.replace("来信人:", "") # 获取提问时间
question_time = str(container_builder.extract()[1])
question_time = StrSpecialDealer.getReaction(question_time)
if (question_time.__contains__("时间:")):
question_time = question_time.replace("时间:", "") # 获取网友支持量
support_quert = str(container_builder.extract()[2])
support_quert = support_quert[support_quert.find('>') + 1:support_quert.rfind('<')]
support_quert = StrSpecialDealer.getReaction(support_quert) # 获取问题具体内容
quText = str(index_sel.css('div div div div').extract()[9])
if(quText.__contains__("input")):
quText = str(index_sel.css('div div div div').extract()[10])
quText = quText.replace("<p>", "")
quText = quText.replace("</p>", "")
quText = StrSpecialDealer.getReaction(quText) # ------------------------------------------------------------------------------------------回答内容
try:
# 回答点赞数
num_supp = str(index_sel.css('div a span').extract()[0])
num_supp = StrSpecialDealer.getReaction(num_supp)
# 回答不支持数
num_unsupp = str(index_sel.css('div a span').extract()[1])
num_unsupp = StrSpecialDealer.getReaction(num_unsupp)
# 获取回答方
answer_name = str(container_div.css("div div div div div div div").extract()[1])
answer_name = answer_name.replace("<strong>", "")
answer_name = answer_name.replace("</strong>", "")
answer_name = answer_name.replace("</div>", "")
answer_name = answer_name.replace(" ", "")
answer_name = answer_name.replace("\t", "")
answer_name = answer_name.replace("\r", "")
answer_name = answer_name.replace("\n", "")
answer_name = answer_name[answer_name.find('>') + 1:answer_name.__len__()]
# ---------------------不想带着这个符号就拿开
if (answer_name.__contains__("[官方回答]:")):
answer_name = answer_name.replace("[官方回答]:", "")
# 答复时间
answer_time = str(index_sel.css('div div div div div div div div')[2].extract())
answer_time = StrSpecialDealer.getReaction(answer_time)
if (answer_time.__contains__("答复时间:")):
answer_time = answer_time.replace("答复时间:", "")
# 答复具体内容
answer_text = str(index_sel.css('div div div div div div div')[4].extract())
answer_text = StrSpecialDealer.getReaction(answer_text)
answer_text = answer_text.replace("<p>", "")
answer_text = answer_text.replace("</p>", "")
except:
pass bean = Bean(question_toBuilder, answer_name, question_time, answer_time, title, support_quert, num_supp,
num_unsupp, quText, answer_text) return bean

DetailConnector.py

  此代码对应测试代码

dc = DetailConnector("http://www.beijing.gov.cn/hudong/hdjl/com.web.consult.consultDetail.flow?originalId=AH20012200024")
dc.getBean().display()

  测试结果:

   里面用到了CSS选择器的使用

   CSS选择器的使用方法(参考网页):https://www.w3school.com.cn/cssref/css_selectors.ASP

   但是有了这一部分还是不行,我们需要从原网站找到对应网站的链接地址!

   而且从第123期博客,我们可以知道:对应链接的onclick事件的两个参数分别对应的跳转地址关系,所以我们看:

 # [ 网页爬取的直接对象 ]
class WebConnector: basicURL = "http://www.beijing.gov.cn/hudong/hdjl/com.web.search.mailList.flow"
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36'} # ---[定义构造方法]
def __init__(self):
pass # 获取 url 的内部 HTML 代码
def getHTMLText(self):
req = request.Request(url=self.basicURL, headers=self.headers)
r = request.urlopen(req).read().decode()
return r # 获取页面内的基本链接
def getFirstChanel(self):
index_html = self.getHTMLText()
index_sel = parsel.Selector(index_html)
links = index_sel.css('div #mailul').css("a[onclick]").extract()
inNum = links.__len__()
for seat in range(0, inNum):
# 获取相应的<a>标签
pe = links[seat]
# 找到第一个 < 字符的位置
seat_turol = str(pe).find('>')
# 找到第一个 " 字符的位置
seat_stnvs = str(pe).find('"')
# 去掉空格
pe = str(pe)[seat_stnvs:seat_turol].replace(" ","")
# 获取资源
pe = pe[14:pe.__len__()-2]
pe = pe.replace("'","")
# 整理成 需要关联数据的样式
mor = pe.split(",")
# ---[ 构造网址 ]
url_get_item = "";
# 对第一个数据的判断
if(mor[0]=="咨询"):
url_get_item = "http://www.beijing.gov.cn/hudong/hdjl/com.web.consult.consultDetail.flow?originalId="
else:
if(mor[0]=="建议"):
url_get_item = "http://www.beijing.gov.cn/hudong/hdjl/com.web.suggest.suggesDetail.flow?originalId="
url_get_item = url_get_item + mor[1] model = "a+" if(seat==0):
model = "w+" dc = DetailConnector(url_get_item)
dc.getBean().addToFile("../testFile/emails.txt",model)

WebConnector.py

   此代码对应测试代码:

wc = WebConnector()
wc.getFirstChanel()

    测试结果是将默认得到的第一页的内容爬取到文件email.txt里(分隔符为制表符 "\t" )

  

  但是这还是没有结束,因为这只有默认的6条数据,如何继续爬取剩下的5624-1页的数据呢?

  我目前找到了它传输数据的JSON包(附链接:http://www.beijing.gov.cn/hudong/hdjl/com.web.search.mailList.mailList.biz.ext

  截图如下:

  

  PS:前面那期博客内容应该是不全的,因为爬到第27页才出来一个特殊的页面:(居然还有投诉类型的?!!)

  

  投诉类型对应页面前缀为http://www.beijing.gov.cn/hudong/hdjl/com.web.complain.complainDetail.flow?originalId=

Python 爬取 北京市政府首都之窗信件列表-[Scrapy框架](2020年寒假小目标04)的更多相关文章

  1. Python 爬取 北京市政府首都之窗信件列表-[后续补充]

    日期:2020.01.23 博客期:131 星期四 [本博客的代码如若要使用,请在下方评论区留言,之后再用(就是跟我说一声)] //博客总体说明 1.准备工作 2.爬取工作(本期博客) 3.数据处理 ...

  2. Python 爬取 北京市政府首都之窗信件列表-[信息展示]

    日期:2020.01.25 博客期:133 星期六 [代码说明,如果要使用此页代码,必须在本博客页面评论区给予说明] //博客总体说明 1.准备工作 2.爬取工作 3.数据处理 4.信息展示(本期博客 ...

  3. Python 爬取 北京市政府首都之窗信件列表-[数据处理]

    日期:2020.01.24 博客期:132 星期五 [代码说明,如果要使用此页代码,必须在本博客页面评论区给予说明] //博客总体说明 1.准备工作 2.爬取工作 3.数据处理(本期博客) 4.信息展 ...

  4. Python 爬取 热词并进行分类数据分析-[简单准备] (2020年寒假小目标05)

    日期:2020.01.27 博客期:135 星期一 [本博客的代码如若要使用,请在下方评论区留言,之后再用(就是跟我说一声)] 所有相关跳转: a.[简单准备](本期博客) b.[云图制作+数据导入] ...

  5. Python 爬取的类封装【将来可能会改造,持续更新...】(2020年寒假小目标09)

    日期:2020.02.09 博客期:148 星期日 按照要求,我来制作 Python 对外爬取类的固定部分的封装,以后在用 Python 做爬取的时候,可以直接使用此类并定义一个新函数来处理CSS选择 ...

  6. Python 爬取 热词并进行分类数据分析-[解释修复+热词引用]

    日期:2020.02.02 博客期:141 星期日 [本博客的代码如若要使用,请在下方评论区留言,之后再用(就是跟我说一声)] 所有相关跳转: a.[简单准备] b.[云图制作+数据导入] c.[拓扑 ...

  7. python爬取北京政府信件信息01

    python爬取,找到目标地址,开始研究网页代码格式,于是就开始根据之前学的知识进行爬取,出师不利啊,一开始爬取就出现了个问题,这是之前是没有遇到过的,明明地址没问题,就是显示网页不存在,于是就在百度 ...

  8. Python爬取招聘信息,并且存储到MySQL数据库中

    前面一篇文章主要讲述,如何通过Python爬取招聘信息,且爬取的日期为前一天的,同时将爬取的内容保存到数据库中:这篇文章主要讲述如何将python文件压缩成exe可执行文件,供后面的操作. 这系列文章 ...

  9. Python 爬取所有51VOA网站的Learn a words文本及mp3音频

    Python 爬取所有51VOA网站的Learn a words文本及mp3音频 #!/usr/bin/env python # -*- coding: utf-8 -*- #Python 爬取所有5 ...

随机推荐

  1. Python(二) isinstance

    原文链接: http://www.baike.com/wiki/isinstance&prd=jinshan https://www.liaoxuefeng.com/wiki/00143160 ...

  2. 从0到1了解 CI/CD

    现代软件开发的需求加上部署到不同基础设施的复杂性使得创建应用程序成为一个繁琐的过程.当应用程序出现规模性增长,开发团队人员变得更分散时,快速且不断地生产和发布软件的流程将会变得更加困难.为了解决这些问 ...

  3. html5异步单图片多图片上传两种实现方式 后台.net mvc接收

    Asp.net mvc上传多张图片后台存储 前台页面通过<file name="img">标签数组上传图片,后台根据Request.Files["img&qu ...

  4. 卫哲VS投行女,秋后算账是阿里的企业文化吗?

    编辑 | 于斌 出品 | 于见(mpyujian) 提到马云,大家都会想到淘宝,阿里,也都期待阿里巴巴的马云爸爸能够给我们免单,从而省去我们每天为钱烦恼的后顾之忧.虽然今天要吃的瓜是有关阿里的,但是并 ...

  5. 【转载】MyEclipse6.5 KeyGen

    输入自己的注册名,生成注册码,完成注册 package keyGenerate; import java.io.BufferedReader; import java.io.IOException; ...

  6. Java的反射机制之反向抽烟

    show me the code and take to me,做的出来更要说的明白 GitHub项目JavaHouse同步收录 喜欢就点个赞呗! 你的支持是我分享的动力! 引入 反射是一种不按套路处 ...

  7. 【代码总结】PHP面向对象之接口与多态性应用

    概述: PHP之支持单继承,也就是说每个类智能继承一个父类.当声明的新类继承抽象类实现模板以后就不能再有其他问题,为了解决这个问题,PHP引用了接口 ------------------------- ...

  8. 吴裕雄--天生自然Numpy库学习笔记:NumPy 数学函数

    NumPy 包含大量的各种数学运算的函数,包括三角函数,算术运算的函数,复数处理函数等. NumPy 提供了标准的三角函数:sin().cos().tan(). import numpy as np ...

  9. 吴裕雄 python 神经网络——TensorFlow variables_to_restore函数的使用样例

    import tensorflow as tf v = tf.Variable(0, dtype=tf.float32, name="v") ema = tf.train.Expo ...

  10. Cisco Cat4500系列High CPU故障步骤摘要

    在实际网络环境中,很多时候都会出现设备high CPU的情况,有些时候可能是bug,而某些情况下,也可能是网络中发生了变化,导致了设备出现high CPU情况,这里主要记录一下Cisco Cat450 ...