Python 爬取 北京市政府首都之窗信件列表-[后续补充]
日期:2020.01.23
博客期:131
星期四
【本博客的代码如若要使用,请在下方评论区留言,之后再用(就是跟我说一声)】
//博客总体说明
1、准备工作
2、爬取工作(本期博客)
3、数据处理
4、信息展示
我试着改写了一下爬虫脚本,试着运行了一下,第一次卡在了第27页,因为第27页有那个“投诉”类型是我没有料到的!出于对这个问题的解决,我重新写了代码,新的类和上一个总体类的区别有以下几点:
1、因为要使用js调取下一页的数据,所以就去网站上下载了FireFox的驱动
安装参考博客:https://www.cnblogs.com/nuomin/p/8486963.html
这个是Selenium+WebDriver的活用,这样它能够模拟人对浏览器进行操作(当然可以执行js代码!)
# 引包
from selenium import webdriver # 使用驱动自动打开浏览器并选择页面
profile = webdriver.Firefox()
profile.get('http://www.beijing.gov.cn/hudong/hdjl/com.web.search.mailList.flow') # 浏览器执行js代码
# ----[pageTurning(3)在网页上是下一页的跳转js(不用导js文件或方法)]
profile.execute_script("pageTurning(3);") # 关闭浏览器
profile.__close__()
2、因为要做页面跳转,所以每一次爬完页面地址以后就必须要去执行js代码!
3、因为咨询类的问题可能没有人给予回答,所以对应项应以空格代替(错误抛出)
4、第一个页面读取到文件里需要以"w+"的模式执行写文件,之后则以 “追加”的形式“a+”写文件
先说修改的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 + "\t"
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() # 将信息附加到文件里
def addToFile_s(self, fpath, model,kind):
f = codecs.open(fpath, model, 'utf-8')
f.write(kind+"\t"+self.toString() + "\n")
f.close() # --------------------[基础数据]
# 提问方
asker = ""
# 回答方
responser = ""
# 提问时间
askTime = ""
# 回答时间
responseTime = ""
# 问题标题
title = ""
# 问题支持量
questionSupport = ""
# 回答点赞数
responseSupport = ""
# 回答被踩数
responseUnsupport = ""
# 问题具体内容
questionText = ""
# 回答具体内容
responseText = ""
Bean.py
之后是总体的处理类
# [ 连续网页爬取的对象 ]
class WebPerConnector:
profile = "" isAccess = True # ---[定义构造方法]
def __init__(self):
self.profile = webdriver.Firefox()
self.profile.get('http://www.beijing.gov.cn/hudong/hdjl/com.web.search.mailList.flow') # ---[定义释放方法]
def __close__(self):
self.profile.quit() # 获取 url 的内部 HTML 代码
def getHTMLText(self):
a = self.profile.page_source
return a # 获取页面内的基本链接
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="
else:
if (mor[0] == "投诉"):
url_get_item = "http://www.beijing.gov.cn/hudong/hdjl/com.web.complain.complainDetail.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_s("../testFile/emails.txt",model,mor[0])
self.getChannel() # 获取页面内的基本链接
def getNoFirstChannel(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="
else:
if (mor[0] == "投诉"):
url_get_item = "http://www.beijing.gov.cn/hudong/hdjl/com.web.complain.complainDetail.flow?originalId="
url_get_item = url_get_item + mor[1] dc = DetailConnector(url_get_item)
dc.getBean().addToFile_s("../testFile/emails.txt", "a+",mor[0])
self.getChannel() def getChannel(self):
try:
self.profile.execute_script("pageTurning(3);")
time.sleep(1)
except:
print("-# END #-")
isAccess = False if(self.isAccess):
self.getNoFirstChannel()
else :
self.__close__()
WebPerConnector.py
对应执行代码(这次不算测试)
wpc = WebPerConnector()
wpc.getFirstChanel()
亲测可以执行到第486页,然后页面崩掉,看报错信息应该是溢出了... ...数据量的话是2910条,文件大小 3,553 KB
我将继续对代码进行改造... ...
改造完毕:(完整能够实现爬虫的python集合)
import parsel
from urllib import request
import codecs
from selenium import webdriver
import time # [ 对字符串的特殊处理方法-集合 ]
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 # [ 保存的数据格式 ]
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 + "\t"
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() # 将信息附加到文件里
def addToFile_s(self, fpath, model,kind):
f = codecs.open(fpath, model, 'utf-8')
f.write(kind+"\t"+self.toString() + "\n")
f.close() # --------------------[基础数据]
# 提问方
asker = ""
# 回答方
responser = ""
# 提问时间
askTime = ""
# 回答时间
responseTime = ""
# 问题标题
title = ""
# 问题支持量
questionSupport = ""
# 回答点赞数
responseSupport = ""
# 回答被踩数
responseUnsupport = ""
# 问题具体内容
questionText = ""
# 回答具体内容
responseText = "" # [ 连续网页爬取的对象 ]
class WebPerConnector:
profile = "" isAccess = True # ---[定义构造方法]
def __init__(self):
self.profile = webdriver.Firefox()
self.profile.get('http://www.beijing.gov.cn/hudong/hdjl/com.web.search.mailList.flow') # ---[定义释放方法]
def __close__(self):
self.profile.quit() # 获取 url 的内部 HTML 代码
def getHTMLText(self):
a = self.profile.page_source
return a # 获取页面内的基本链接
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="
else:
if (mor[0] == "投诉"):
url_get_item = "http://www.beijing.gov.cn/hudong/hdjl/com.web.complain.complainDetail.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_s("../testFile/emails.txt",model,mor[0]) # 获取页面内的基本链接
def getNoFirstChannel(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="
else:
if (mor[0] == "投诉"):
url_get_item = "http://www.beijing.gov.cn/hudong/hdjl/com.web.complain.complainDetail.flow?originalId="
url_get_item = url_get_item + mor[1] dc = DetailConnector(url_get_item)
bea = ""
try:
bea = dc.getBean()
bea.addToFile_s("../testFile/emails.txt", "a+", mor[0])
except:
pass # 转移页面 (2-5624)
def turn(self,seat):
seat = seat - 1
self.profile.execute_script("beforeTurning("+str(seat)+");")
time.sleep(1) # [ 信息爬取结点 ]
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("[官方回答]:", "")
if (answer_name.__contains__("<span>")):
answer_name = answer_name.replace("<span>", "")
if (answer_name.__contains__("</span>")):
answer_name = answer_name.replace("</span>", "") # 答复时间
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 wpc = WebPerConnector()
wpc.getFirstChanel()
for i in range(2,5625):
wpc.turn(i)
wpc.getNoFirstChannel()
wpc.__close__()
WebConnector.py
执行结果文件
大小 40,673 KB
数据量 33,746
这爬取过程蛮长的啊!从凌晨2:30开始,一直到7:30多,这是5个小时!
期间爬取任务停了4次:
1、第2565页——进程进行到这里时浏览器卡住了,不动了,这我也不知道就改造了一下代码,继续爬了
2、第3657页——原因同上
3、第3761页——系统说是在文件读写方面,对文件追加的写入已经达到了极限,所以我将当时的数据文件移出,建立了新的空白文件用以储存3761页及以后的数据
4、第4449页——这一页有这样一项数据,名称是“关于亦庄轻轨的小红门站和旧宫东站”(咨询类),然后如果你点开那个链接,你将会收到的是500的网页状态,当时爬虫爬到这里就是因为报错而跳出了程序,如下图:
Python 爬取 北京市政府首都之窗信件列表-[后续补充]的更多相关文章
- Python 爬取 北京市政府首都之窗信件列表-[Scrapy框架](2020年寒假小目标04)
日期:2020.01.22 博客期:130 星期三 [代码说明,如果要使用此页代码,必须在本博客页面评论区给予说明] //博客总体说明 1.准备工作(本期博客) 2.爬取工作 3.数据处理 4.信息展 ...
- Python 爬取 北京市政府首都之窗信件列表-[信息展示]
日期:2020.01.25 博客期:133 星期六 [代码说明,如果要使用此页代码,必须在本博客页面评论区给予说明] //博客总体说明 1.准备工作 2.爬取工作 3.数据处理 4.信息展示(本期博客 ...
- Python 爬取 北京市政府首都之窗信件列表-[数据处理]
日期:2020.01.24 博客期:132 星期五 [代码说明,如果要使用此页代码,必须在本博客页面评论区给予说明] //博客总体说明 1.准备工作 2.爬取工作 3.数据处理(本期博客) 4.信息展 ...
- python爬取北京政府信件信息01
python爬取,找到目标地址,开始研究网页代码格式,于是就开始根据之前学的知识进行爬取,出师不利啊,一开始爬取就出现了个问题,这是之前是没有遇到过的,明明地址没问题,就是显示网页不存在,于是就在百度 ...
- Python爬取招聘信息,并且存储到MySQL数据库中
前面一篇文章主要讲述,如何通过Python爬取招聘信息,且爬取的日期为前一天的,同时将爬取的内容保存到数据库中:这篇文章主要讲述如何将python文件压缩成exe可执行文件,供后面的操作. 这系列文章 ...
- Python 爬取所有51VOA网站的Learn a words文本及mp3音频
Python 爬取所有51VOA网站的Learn a words文本及mp3音频 #!/usr/bin/env python # -*- coding: utf-8 -*- #Python 爬取所有5 ...
- python爬取网站数据
开学前接了一个任务,内容是从网上爬取特定属性的数据.正好之前学了python,练练手. 编码问题 因为涉及到中文,所以必然地涉及到了编码的问题,这一次借这个机会算是彻底搞清楚了. 问题要从文字的编码讲 ...
- python爬取某个网页的图片-如百度贴吧
python爬取某个网页的图片-如百度贴吧 作者:vpoet mail:vpoet_sir@163.com 注:随意copy,不用告诉我 #coding:utf-8 import urllib imp ...
- Python:爬取乌云厂商列表,使用BeautifulSoup解析
在SSS论坛看到有人写的Python爬取乌云厂商,想练一下手,就照着重新写了一遍 原帖:http://bbs.sssie.com/thread-965-1-1.html #coding:utf- im ...
随机推荐
- as中怎么下载更新platforms和build-tools
链接:https://blog.csdn.net/sunbinkang/article/details/78632652
- 如何在app.js 和其他页面中更改globalData的值
它不能用this.setData方法更改值,该方法只能更改data:{}对象(而且在app.js中无法使用该方法),因此用app.globalData.isLogin = true;
- Java 使用代理发送Http请求 (将Http请求代理Https请求)
package com.test.porxy; import java.io.BufferedReader; import java.io.IOException; import java.io.In ...
- STM32F103_外部RAM用作运存---IS62WV51216
https://www.cnblogs.com/lilto/p/9548736.html STM32F103_外部RAM用作运存 概述 SRAM的简介 折腾过电脑的朋友都知道,当电脑运行比较卡的时 ...
- input file multiple 配合springmvc实现多文件上传
.前端页面的样子 <input id="file" name="file" type="file" multiple="mu ...
- 洛谷 P5016 龙虎斗(模拟)
嗯... 题目链接:https://www.luogu.org/problem/P5016 这道题是一道模拟,不要考虑复杂,直接暴力枚举每一个点,看看加上s2之后两个势力的差值,找最小,记录下标. 注 ...
- Redis搭建一主一从及哨兵模式(二)
废话不多说,直接进入正题. 一.主从搭建 进入redis的根目录,拷贝一份redis.conf,最初的一份留作模版: ①cp redis.conf redis.conf.template ②vim ...
- maven安装和使用前的几个点
以前的以前,听说过maven,也有幸安装过,没怎么用过,都是按照网上别人的记录照着做的,感觉好没有意思,现在我想自己弄清楚一些事情.一起来源于配置文件,和在网上多搜索多看,多实践. 我用的包是这个ap ...
- 05-Docker-Container资源限制
目录 05-Docker-Container资源限制 参考 可压缩性 MEM限制 选项说明 压测示例 CPU限制 选项说明 压测示例 05-Docker-Container资源限制 Docker Ve ...
- Django rest framework框架中有哪些组件
认证 权限(授权) 用户访问次数/频率限制 版本 解析器(parser) 序列化 分页 路由系统 视图 渲染器 认证 自定义认证的类 """ from rest_fram ...