Python学习报告(二)

Python爬虫实战

一、写在前面

在学习了一天的Python基础语法之后,本着“学中干,干中学”的思想,我开始了菜鸡的爬虫生活

爬虫网站

感谢图吧给我这次练手机会
https://poi.mapbar.com/beijing/
选择图吧的原因如下:

  • 没有反爬机制
  • 整体结构清晰统一,可重复爬取
  • 贾老师要求的(嘿嘿)

目的&思路

目的:获取北京市旅游、酒店、交通等类别的具体信息及商家个人页链接
思路:先从北京市页面爬取各个类别下的所有的分类名和链接,然后循环访问每一类,爬取所有商家信息,最后整合成json格式文件(jl也可)
工具:Requests获取数据,lxml分析数据

依赖库

  • lxml
  • requests
  • json

二、具体流程

各大版块分类抓取

抓取方法请看Xpath定位

url = "https://poi.mapbar.com/beijing/"
response = requests.get(url)
txt = response.text
html = etree.HTML(txt)
result = html.xpath('//div[@class="isortRow"]/h3/text()')
result2 = list(filter(lambda x:x!='\r\n\t\t\t\t',result))
with open('./各大板块.txt','w',encoding='utf-8') as fp:
	for i in result2:
        fp.write(i)

先是从总的网页读取每一个板块的名称,因为读取出来的文字带有’\r\n\t\t\t’,于是利用filter过滤一下
这里有个问题,就是没有文字的仅是’\r\n\t\t\t’的内容被过滤了,但是文字+’\r\n\t\t\t’的怎么也处理不了,尝试了replace无果,于是手动改了,这也是为什么最后代码会有本地读取的原因(是我太菜了)

各个版块下具体分类名及链接地址抓取

for i in range(0,10):
    urlresult = html.xpath('/html/body/div[2]/div[3]/div['+str(i+1)+']/a/@href')
    nameresult = html.xpath('/html/body/div[2]/div[3]/div['+str(i+1)+']/a/text()')

因为网站分为两个div存放的位置,于是我具体读取的时候就分成两块读:0-10与0-8

网站信息抓取

接下来就根据每一个具体类别和链接,一遍一遍爬就好了

#以读取超市为例
url = "https://poi.mapbar.com/beijing/520"
response = requests.get(url)
txt = response.text
html = etree.HTML(txt)
result1 = html.xpath('//div[@class="sortC"]/dl/dd/a/text()')
result2 = html.xpath('//div[@class="sortC"]/dl/dd/a/@href')

信息存储

为了方便阅读,用了json格式存放,如果需要了解更多可以看下方心得体会

 with open('./标准化.json', 'a', encoding='utf-8') as fp:
            json.dump({'板块名称': list5[i + 10*m], 
            '具体分类': nameresult[j], 
            '链接地址': urlresult[j],
            '名称': result1, 
            '相关链接': result2},
            fp,ensure_ascii=False)
            fp.write('\n')

三、心得体会

xpath定位

这里要讲一下xpath地址的抓取,因为没有什么基础,只要想要那个元素,但是不知道如何定位就是一个很大的问题
进入目标网站-右键-检查
你就可以看到里面的元素,然后根据选中的范围一层一层的找到你想要的元素
元素定位

目标元素位置-右键-copy-xpath
这样做你可以获得它的绝对路径,但是一般来说我们用不着那么清晰
这个时候就要知道xpath好用的一点
路径读取
先给出Xpath的表示式

表达式描述
/从根节点选取
//从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置
.选取当前节点
选取当前节点的父节点
@选取属性。

我们可以看到超市里面第一个AEON的元素有<div class=“sortC”>
我们就可以根据这个进行定位

result1 = html.xpath('//div[@class="sortC"]/dl/dd/a/text()')
result2 = html.xpath('//div[@class="sortC"]/dl/dd/a/@href')

虽然最后的标签是a,但是a是一个对象,想要获取它的文字信息,一定要用a/text(),如果是获取他的超链接地址用a/@href

动态分页处理

在爬虫的时候,发现了一个问题,如下:
在这里插入图片描述
(公司企业-其他公司企业)
本来想着用xpath去定位,结果发现是一个JS动态生成的。在贾老师的帮助下知道了分页的机制:

  1. 如果访问的是无分页的网站,链接显示为:https://poi.mapbar.com/beijing/xxx/
  2. 如果访问的是动态分页的网站,链接显示为:
    https://poi.mapbar.com/beijing/xxx_1/
    根据分页不同更改数字即可
  3. 实际上访问https://poi.mapbar.com/beijing/xxx_1/ 实际就是在访问无分页情况下的https://poi.mapbar.com/beijing/xxx/

于是对于每一个链接的访问,都改成xxx_1的访问方式,在访问成功后,尝试性访问xxx_2,如果访问成功,则继续读取写入该类别;如果返回404就放弃,开始访问下一个类别

url = url[:len(url)-1]+"_1/"
t=1
while True:
	 url = url[:len(url)-2]+str(t)+"/"
     response = requests.get(url)  
     if requests.get(url).status_code==404:
     	break

访问限制

因为爬取的数据量较大(最后合格的文档是60MB),本身访问请求次数较多,并且加上测试动态分页的情况,访问次数又会加倍,很容易被目标网站限(dang)制(chang)访(zhua)问(huo)
在这里插入图片描述
我先尝试了time.sleep,在测试0.3s,0.5s,1s都失败之后,我选择了分成两块爬取。本来想着中间sleep十分钟就可以了,结果继续被限制…
最后我将整个爬虫分成两个板块,不设置sleep,两次爬虫中间间隔3小时,get√

json储存格式

原本存放json的代码是这样的:

 with open('./标准化.json', 'a', encoding='utf-8') as fp:
	json.dump({'板块名称': list5[i + 10*m], 
			   '具体分类': nameresult[j],
			   '链接地址': urlresult[j],
			   '名称': result1,
			   '相关链接': result2}, fp)

结果发现有乱码,并且难以阅读
于是变成了这样

        with open('./标准化.json', 'a', encoding='utf-8') as fp:
            json.dump({'板块名称': list5[i + 10*m], 
            '具体分类': nameresult[j],
             '链接地址': urlresult[j], 
             '名称': result1, 
             '相关链接': result2},
             fp,ensure_ascii=False)
            fp.write('\n')

写入的每一行代表一个具体的设施信息,利用ensure_ascii=False来解决了问题

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值