汽车工程师之家
我们不生产数据,我们只是数据的搬运工Python 最近几年经常在网上和朋友圈看到,一款在物联网,大数据,人工智能,图像识别兴起的时代特别火的编程语言。其实不同的编程语言都是完成图灵的工作,但是不同的语言在实现某些功能上都有自己的特点和规则。经过几番尝试,终于找到入门的机会学习,通过学了一周,算到了Python门口,写一个简单的爬虫,旨在实战一下写到的知识点,记录设计思维和编程过程中一些比较难容,易忘记的技巧,希望给想学习Python 的读者和以后我再写爬虫以借鉴。
最后实现就几十行代码,但是花了好几天时间琢磨和尝试。纯属个人爱好,不喜勿喷!
1.选题汽车工程师之家-发动机电喷控制系统 分论坛,是我作为标定工程师在2011年的开始工作的时候会浏览的网页,忘不了那自学标定的时光。所以,打算通过Python 爬出该分论坛所有的帖子的分类,以及每个分类下的名称列表,同时附带每个帖子的链接。
例如:
汽油发动机 xxxx帖子 链接xxxx
柴油发动机 xxxx帖子 链接xxxx
控制模块ECU xxxx帖子 链接xxxx
2.代码
程序文件链接:http://note.youdao.com/noteshare?id=f4ddb381048c52abb97660dcb46a72b9&sub=00BE98BF5E6E4621B0624D7675B4E311import urllib.request as urimport lxml.etree as leimport re”’http://www.cartech8.com/forum-29311-5.html论坛某个网页网址”’forum_num=’29311’pg=’1’#创建请求request=’http://www.cartech8.com/forum-‘+forum_num+’-‘+pg+’.html’# print(request)#获得网页回传response = ur.urlopen(request).read()# print(response)#html网页存到本地with open(‘club.html’,’wb’) as f: f.write(response)# 定义正则表达式,注意括号 pattern_1 = ‘ class=”last”>… (.*?)</a><label>’# re.findall(【正则表达式】,【被提取的字符串】),返回类型是列表 ret_1 = re.findall(pattern_1, response.decode(‘ISO-8859-1’))[0]
a=float(ret_1)link=[]class_s = []title_s = []for i in range(1,int(a)+1): pg=str(i) request=’http://www.cartech8.com/forum-‘+forum_num+’-‘+pg+’.html’ response = ur.urlopen(request).read() # 定义正则表达式,注意括号 pattern_2 = ‘ <a href=”(.*?)” onclick=”ata’ # re.findall(【正则表达式】,【被提取的字符串】),返回类型是列表 ret_2_s = re.findall(pattern_2, response.decode(‘ISO-8859-1’)) link=link+ret_2_s # xpath 清洗数据 html_x = le.HTML(response) # print(html_x) div_x_s = html_x.xpath(‘//th/a[@onclick=”atarget(this)” and not(@style)]/text()’) # print(div_x_s) class_x_s=html_x.xpath(‘//th/em/a/text()’)
dic=dict(zip(class_x_s,div_x_s))
div_x_ss=html_x.xpath(‘//th’) # 分类和帖子提取 for div_x in div_x_ss: try: category1 = div_x.xpath(‘./a[@onclick=”atarget(this)”]/text()’)[0] try: category2_s = div_x.xpath(‘./em/a/text()’)[0] except: category2_s=[”] class_s.append(category2_s) title_s.append(category1) except: passj=1for j in range(len(title_s)): print(class_s[j],title_s[j],link[j])
3.结果输出形式
不搞复杂了,输入到TXT文件算了C:Users81088Desktop>backuptest_2.py>html.txt
一共是2537个帖子。
4.难点记录
⑴论坛官方的帖子没有分类,怎么样写xpath 语句将官方的帖子舍弃,同时每个分类与帖子对应?
比较两者语句区别:
针对此,写xpath 语句,
//th/a[@onclick=”atarget(this)” and not(@style)]/text()Xpath 得到的帖子结果:
汽油电喷系统供应商投票各种天然气发动机系统原理图前氧后氧传感器可以互换么?喷油器问题INCA在导入A2L及S19文件时报错,有截图inca7.0和MDA7.0怎么破解大家知道吗??联电系统充气模型讲解联电系统的homogeneous模式是个什么模式?国六I型试验PN还不错PM超标原因探讨求INCA7.0的安装文件,哪位兄弟能帮帮忙?SCR系统 PT200高温传感器目前主流的氧传感器是使用哪种类型的?嗨,各位好,我想问问谁家的氧传感器做的比较好呢5根线宽带氧传感器每根线的作用?氧传感器国内外知名厂家有偿收标定技术文档德尔福MT05—电喷摩托车求柴油博世Edc17标定资料A2l和hex等,红包已备好INCA7.0安装软件原来吉利博瑞搭载有环境监测系统,厉害了我的博瑞!如何由缸压推算出放热率关于从事汽车尾气后处理行业(设计生产三元催化器、EGR、DPF等尾气净化产品)的前景标定的自动控制原理柴油机车原地踩油门失火故障整车标定好,还是发动机标定有前途?关于踩油门,急加速发动机转速上升滞后的原因,请大神赐教?整车性能标定请问下各家标定公司用的标定软件以及模型的区别,即将进入武汉菱电有关博世EDC17系统咨询:汽车厂商如何应对国际市场中的不同油品油品传感器汽车三元催化器储量计算排气管材料及厚度一般是多少?马瑞利国内的武汉菱电公司在发动机电控方面做的怎么样?学学INCA软件标定吧分类xpath 语句可以用:
//th/em/a/text()结果如下:
综合发动机标定电子器件发动机标定发动机标定发动机标定控制策略燃烧与排放发动机标定柴油发动机讨论汽油发动机汽油发动机燃烧与排放汽油发动机摩托车柴油发动机发动机标定其它汽油发动机燃烧与排放发动机标定发动机标定讨论汽油发动机汽油发动机汽油发动机柴油发动机发动机标定汽油发动机燃烧与排放燃烧与排放燃烧与排放控制模块ECU汽油发动机
⑵分类和帖子分别是两个单独的list, 如何让他们组合成相对应的字典呢?而且是一个键值对应多个值的字典?
发现个小问题,这个网站有点BT,有一篇帖子,没有分类,就只有那么一篇《各种天然气发动机系统原理图》应该属于下载专区的,不知道不分类怎么发表的。所以上面问题(1)中一个结果是35个,一个是36个。那就没有分类就不显示分类吧。
for div_x in div_x_ss: try: category1 = div_x.xpath(‘./a[@onclick=”atarget(this)”]/text()’)[0] category2_s = div_x.xpath(‘./em/a/text()’) #print(category2_s) data_s.append( dict( category2_s=category2_s, category1=category1 ) ) except: pass # print(data_s) for data in data_s: # print(data.get(‘category2_s’)) print(data.get(‘category2_s’),data.get(‘category1’)) ⑶怎么样读取总共的页码数?
Xpath 好像搞不了,页码总数的特征是 / 71 页,不可返回为可运算值。
切换为re正则式来做吧,总是搞出来了,不过折腾了半天见下面的问题
ret_1 = re.findall(pattern_1, response.decode(‘ISO-8859-1’))[0]print(ret_1)=>71 ⑷解码出错
ret_1 = re.findall(pattern_1, response)
运行出错:TypeError: cannot use a string pattern on a bytes-like object
网上方法修改之后,还是有问题,
ret_1 = re.findall(pattern_1, response.decode(‘utf-8’))UnicodeDecodeError: ‘utf-8’ codec can’t decode byte 0xa1 in position 253: invalid start byte
最终改为如下,解决问题:
ret_1 = re.findall(pattern_1, response.decode(‘ISO-8859-1’))
备注:
1. iso-8859-1以一个字节(1 byte)存储字符。即字符a存储为一个字节,即8位(8 bit)。
2.utf-8变长字节存储字符,最小单位是一个字节。iso-8859-1正好相当于utf-8的一个单位。因此,将以utf-8编码的字节流用iso-8859-1的方式读取后字符乱码但信息不丢失,只需要将字符还原成byte数组(str.getBytes(“ISO-8859-1”)),重新以utf-8读取(new String(byte[], “UTF-8”))即可。
⑸for in range 循环
ret_1 = re.findall(pattern_1, response.decode(‘ISO-8859-1’))[0]print(ret_1)a=float(ret_1)
for i in range(int(a)):range(start, end, step=1)
range会返回一个整数序列,statr为整数序列的起始值,end为整数序列的结束值,在生成的整数序列中,不包含结束值。step为整数序列中递增的步长,默认为1。 ⑹分类-帖子-链接 数据合并打印也是费了老鼻子力气
pattern_2 = ‘<a href=”(.*?)” target=”_blank”>’ # re.findall(【正则表达式】,【被提取的字符串】),返回类型是列表 ret_2 = re.findall(pattern_2, response.decode(‘ISO-8859-1’)) # print(ret_2) link=link+ret_2 for div_x in div_x_ss: try: category1 = div_x.xpath(‘./a[@onclick=”atarget(this)”]/text()’)[0] try: category2_s = div_x.xpath(‘./em/a/text()’)[0] except: category2_s=[”]
class_s.append(category2_s) title_s.append(category1) except: pass for i in range(len(title_s)): print(class_s[i],title_s[i],link[i])
⑺正则表达式也要改,超链接有两种形式存在,坑。。。
发现个数不match
把正则表达式改一下:
pattern_2 = ‘ <a href=”(.*?)” onclick=”ata’
、
总算结束…………..电脑跟我的脑子一样浆糊了,程序员不好做啊……
5.知识笔记,参考文档
Python Xpath 有道云笔记
http://note.youdao.com/noteshare?id=3b4182f3bd4838b40776782b9eb25fee&sub=B8762FC63F69427C95DA0B2748B404D3
Python 数据类型
http://note.youdao.com/noteshare?id=8a2609c6abfeb6031c6bbc201ce7f530&sub=58AD49C90BB5485A81D29392E9A1BA5F
Xpath判断某个属性是否包含或不包含指定的属性或值 https://blog.csdn.net/caorya/article/details/81839928Xpath 详解 https://blog.csdn.net/baidu_32542573/article/details/79675420Python 两个list合并成一个字典https://www.cnblogs.com/tianleblog/p/11590165.htmlpython-try-except:pass的用法 https://blog.csdn.net/MG_ApinG/article/details/82462259Xpath中text(),string(),data()的区别https://www.cnblogs.com/mabingxue/p/11057471.htmljava中byte, iso-8859-1, UTF-8,乱码的根源https://www.cnblogs.com/woshimrf/p/java-utf8-iso-charset.htmlPython3.6笔记之将程序运行结果输出到文件https://blog.csdn.net/young2415/article/details/76595318床长人工智能教程https://www.captainbed.net/ (备注后面学习,新发现的网站)