python之路[25] - 爬虫 - 迁
传统方式是使用requests请求接口,然后用HTMLParser解析网页,使用scrapy框架可以快速的爬取页面内容
请求流程
1 访问首页后就能获取cookies,然后通过这个cookies再请求登录接口,
2 服务器记录这个cookies标记为已登录状态,
3 比较坑的是,有可能会产生很多cookies有些是站长助手创建的,这个问题困扰我很久,完全可以忽视. 当然也有可能是反爬的功能
import sys reload(sys) sys.setdefaultencoding('utf-8') #有些网页是中文的,所以必须加个默认字符集,不然会有错误 def queryData(): r = requestPost( url = "http://hzcs.qsng.cn/hz-bsp/hz/apply-front.action", headers = { "Content-Type" : 'application/json', "user-agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36", } ) cookies = r.cookies['JSESSIONID'] # 获取cookie r = requestPost( url = "http://hzcs.qsng.cn/hz-bsp/hz/login-front!login.action", # 登录接口 data = {"username":"tt", "password":"yy", "memberId":"", "area":0}, cookies={"JSESSIONID":cookies}, headers={ "user-agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36", "Host":"hzcs.qsng.cn", "Origin":"http://hzcs.qsng.cn", "Referer":"http://hzcs.qsng.cn/hz-bsp/hz/apply-front.action", "Upgrade-Insecure-Requests": "1", "Content-Length": "65", "Content-Type" : 'application/x-www-form-urlencoded', }, ) r = requestPost( url = "http://hzcs.qsng.cn/hz-bsp/hz/apply-front!list.action", # 获取列表接口 data = {"query":"", "area":5, "term":0, "spelld":"", "weekDay":"", "beginHour":"", "beginMini":"", "endHour":"", "endMini":"", }, cookies={"JSESSIONID":cookies}, headers={ "user-agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36", "Host":"hzcs.qsng.cn", "Origin":"http://hzcs.qsng.cn", "Referer":"http://hzcs.qsng.cn/hz-bsp/hz/apply-front.action", "Upgrade-Insecure-Requests": "1", "Content-Length": "65", "Content-Type" : 'application/x-www-form-urlencoded', }, ) return r
HTMLParser
获取到原始页面后,这个网页是需要爬下来的页面: 首页|专业|班级名|总费用|区域|班级状态|报名
<table width="100%" border="0" cellspacing="1" cellpadding="0" class="tb"> <tr> <td width="8%" align="center" bgcolor="#c8e0bf">专业</td> <td width="8%" align="center" bgcolor="#c8e0bf">班级名</td> <td width="28%" bgcolor="#c8e0bf">班级信息</td> <td width="10%" align="center" bgcolor="#c8e0bf">总费用</td> <td width="9%" align="center" bgcolor="#c8e0bf">区域</td> <td width="10%" align="center" bgcolor="#c8e0bf">班级状态</td> <td width="10%" align="center" bgcolor="#c8e0bf">报名</td> </tr> <tr> <td align="center" bgcolor="#FFFFFF">绘画涂鸦亲子</td> <td align="center" bgcolor="#FFFFFF"><a href="apply-front!clazzView.action?clazzId=549DB75B36CC4007BB19C07F39D8BC5F&area=5" class="r12"/>B1D08-1</a></td> <td bgcolor="#FFFFFF">年级或年龄要求: <br>学员出生介于:2015-03-01 ~ 2015-08-31</br>性别要求: 不限 程度:启蒙课次:15<br/> 学期:春季2019-02-24开班<br/> 上课时间、地点:<pre>周日 08:30-09:30 滨江分中心303</pre>班级类型: 普通班级招生性质: 招新生 <br/> (<a href="apply-front!clazzView.action?clazzId=549DB75B36CC4007BB19C07F39D8BC5F&area=5" class="r12">点击查看详情</a>) </td> <td align="center" bgcolor="#FFFFFF">900.0</td> <td align="center" bgcolor="#FFFFFF"><font color="red">滨江分中心</font></td> <td align="center" bgcolor="#FFFFFF">名额已满</td> <td align="center" bgcolor="#FFFFFF"> <a href="apply-front!netApply.action?clazzId=549DB75B36CC4007BB19C07F39D8BC5F&area=5" /> <font color="red">点击报名</font></a> <br/> </td> </tr>
class MyHTMLParser(HTMLParser): def __init__(self): HTMLParser.__init__(self) # 初始化一个父类,注意HTMLParser是经典类 self.items = [] self.content = [] self.in_td = False def _get_attr(self,attrs,attrname): # 定义一个解析属性函数,html标签中的属性和属性值在htmlparser解析器中是个tuple类型,返回属性名对应的属性值 for attr in attrs: if attr[0] == attrname: return attr[1] return None def handle_starttag(self, tag, attrs): # 重写handle_starttag函数,该函数在查找到标签头自动调用,attrs包含该标签tag中所有的属性和属性值,类型是个列表,其中的元素都是tuple类型(属性名,属性值) if tag == 'td' and self._get_attr(attrs,'align') == "center": self.in_td = True def handle_endtag(self, tag): # 重写handle_endtag函数,该函数在查找到标签 if tag == 'td' and self.in_td: self.in_td = False def handle_data(self, data): # 重写handle_data函数,该函数在查找到标签中的内容自动调用,利用正则表达式进行了匹配,如果匹配成功,匹配出来的再做文本处理 if self.in_td : data = data.replace("\r\n","").replace(" ","").replace("\t","") if len(data)>0: if data.find(u"报名".encode('utf-8'))>-1: self.content.append(data) item = "|".join(self.content) self.items.append(item) self.content = [] else: self.content.append(data)
爬虫框架scrapy
import codecs from scrapy.spiders import Spider from scrapy.selector import Selector from scrapy.http import Request,FormRequest class mySpider(Spider): name = "hzcs" allowed_domains = "hzcs.qsng.cn" header = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0', 'Referer':"http://hzcs.qsng.cn/", } #设置浏览器用户代理 def start_requests(self): """第一次请求一下登录页面,设置开启cookie使其得到cookie,设置回调函数""" return [Request('http://hzcs.qsng.cn/hz-bsp/hz/apply-front.action',headers=self.header,meta={'cookiejar':1},callback=self.parse)] def parse(self, response): # 响应Cookies Cookie1 = response.headers.getlist('Set-Cookie') #查看一下响应Cookie,也就是第一次访问注册页面时后台写入浏览器的Cookie print('response Cookies:',Cookie1) data = {"username":"33010820150505093X", "password":"15305713256", "memberId":"", "area":0} print "login...." return [ FormRequest.from_response(response, url="http://hzcs.qsng.cn/hz-bsp/hz/login-front!login.action", meta={"cookiejar":response.meta['cookiejar']}, headers=self.header, formdata=data, callback=self.next, )] def next(self,response): Cookie2 = response.requests.headers.getlist('Set-Cookie') print("response Cookies2:", Cookie2) yield Request('http://hzcs.qsng.cn/hz-bsp/hz/apply-front!list.action',meta={'cookiejar':True},callback=self.next2) def next2(self,response): # 请求Cookie Cookie3 = response.request.headers.getlist('Cookie') print('查看需要登录才可以访问的页面携带Cookies:',Cookie3) leir = response.xpath('//div[@class="tu"]/a/text()').extract() #得到个人中心页面 print('最终内容',leir) leir2 = response.xpath('//div[@class="set-tags"]/a/text()').extract() # 得到个人中心页面 print(leir2)
单次执行 scrapy runspider scrapy_test.py