设为首页收藏本站

Crossin的编程教室

 找回密码
 立即加入
查看: 17070|回复: 16
打印 上一主题 下一主题

新人求教,两个正则匹配问题,爬网页不会找内容。。

[复制链接]

1

主题

0

好友

45

积分

新手上路

Rank: 1

跳转到指定楼层
楼主
发表于 2017-8-15 18:14:57 |只看该作者 |倒序浏览
本帖最后由 vocaliu 于 2017-8-15 18:25 编辑

刚学,基础基本没有,直接四处看爬虫希望能边玩边学。

1,四处拼代码弄的爬虫爬妹子图网站,虽然现在能用了,但是里面有个正则搞不定,导致实现的很丑。
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Sun Aug 13 00:47:22 2017
  4. @author: vocaliu
  5. @version:Anaconda python3.6
  6. """
  7. import urllib
  8. import urllib.request
  9. import re
  10. import os
  11. from multiprocessing import Pool

  12. def download_page(url):
  13.     head = { 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.89 Safari/537.36',  
  14.              'Referer': 'http://www.meizitu.com',  
  15.              }                                         #伪装浏览器登陆
  16.     request = urllib.request.Request(url,headers=head) #构建请求
  17.     response = urllib.request.urlopen(request,timeout=10)
  18.     data = response.read()                             #获得服务器响应并读取链接内容(网页、图片或其他)
  19.     return data                                        #返回值就是链接中的具体内容
  20.         
  21. def imgdownload_num(startnum,stopnum):
  22.     for szwz in range(startnum,stopnum):               #这个数字不断变化来抓不同链接
  23.         url = url0 + str(szwz) + '.html'               #合并网址
  24.         os.mkdir('F:\pic\{}'.format(szwz))             #新建与网址一样的文件夹
  25.         wronglink = 0
  26.         try:
  27.             html = download_page(url)                  #在这里做一轮try except,防止遇到错误的抓取页面导致的报错
  28.             regx = r'http://[\S]*\.jpg'                #通过正则配对,得到页面中的jpg图片链接
  29.             pattern = re.compile(regx)                 #re.compile() 可以把正则表达式编译成一个正则表达式对象.
  30.             img_link = re.findall(pattern,repr(html))  #repr()类似str,用处不一样。
  31.         except:
  32.             wronglink += 1
  33.             print('发现第{}个错误的抓取网址'.format(wronglink))#设置时会有一些指向404页面的网址
  34.             break
  35.         num = 1
  36.         wrongpiclink = 0
  37.         for img in img_link:
  38.             try:
  39.                 image = download_page(img)             #将每个img_link链接中的图片都读取出来,并保存成下面的本地链接
  40.                 if len(image) > 45000:                 #大小不到45k的图跳过
  41.                     with open('F:\pic\{}\{}.jpg'.format(szwz,num),'wb') as fp:
  42.                         fp.write(image)
  43.                         print('pic{}-{} downloaded'.format(szwz,num))
  44.                         num += 1
  45.                 else:
  46.                     continue
  47.             except:
  48.                 wrongpiclink += 1
  49.                 print('发现第{}个错误的图片链接'.format(wrongpiclink))#源文件里有一些指向404页面的图片
  50.     return

  51. url0 = 'http://www.meizitu.com/a/'
  52. #开始多进程爬
  53. if __name__ == '__main__':
  54.     print('Parent process %s.' % os.getpid())
  55.     p = Pool(8)
  56.     for i in range(8):
  57.         p.apply_async(imgdownload_num, args=(i*8+1,i*8+9))
  58.     p.close()
  59.     p.join()
  60.     print('All subprocesses done.')
复制代码
正则匹配那儿忘了抄的谁的了,抓的是图里所有的jpg文件,然后只能自己再加个len()>45k来删掉文件大小较小的缩略图。
  1. regx = r'http://[\S]*\.jpg'
复制代码
实际上网站的图是两种,

  1. 无效缩略图      src="http://mm.howkuai.com/wp-content/uploads/2017a/05/08/limg.jpg" alt
  2. 需要抓的图  src="http://mm.howkuai.com/wp-content/uploads/2017a/06/13/01.jpg" />

复制代码
感觉本该很简单,但是我真不会写。。。

2,爬另一个网页,要抓文字内容不会抓,目标是抓文字然后整理数据库分析,在这个过程中熟悉python的操作。不过代码完成度几乎为0就不贴了。
网页上要抓的内容在一个table里,希望能抓到张三丰这三个字,所有的网页对应位置的标签内容都是一样的,感觉应该也好写,但是不会。。。

  1. 姓&nbsp;&nbsp;&nbsp; 名:</font></td><td height="26" width="757"><font size="4" color="#000080">&nbsp;张三丰              </font></td></tr>
复制代码
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

沙发
发表于 2017-8-15 22:18:30 |只看该作者
没基础能拼成这样,我也是蛮佩服的
课程里有正则相关的课程,你翻一下。
建议把基础课程看下,花不了多少时间。你这样一上来就东拼西凑,最后未必省时间
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

1

主题

0

好友

45

积分

新手上路

Rank: 1

板凳
发表于 2017-8-15 23:58:34 |只看该作者
crossin先生 发表于 2017-8-15 22:18
没基础能拼成这样,我也是蛮佩服的
课程里有正则相关的课程,你翻一下。
建议把基础课程看下,花不了多少时 ...

其实是快速扫过你的教程一轮再去找爬虫的,不过没耐下心来打基础。我试试。
这会儿仔细把你教程里的5篇re内容过了一下,干脆在这个帖子下面记录一下进展吧。看看过会儿能不能把我要的两种正则贴出来。
先是学习记录
  1. # -*- coding: utf-8 -*-
  2. '''
  3. Created on Tue Aug 15 23:00:39 2017
  4. @author: vocaliu
  5. @version: Anaconda python3.6
  6. 学习crossincode的re部分:
  7. 1, re.findall(pattern,text)输出符合的结果组成list []
  8. 2,\b转义符的使用,代表单词两端
  9. 3,[]代表其中任意匹配均可
  10. 4,str前的r用于消除转义符
  11. 5,
  12. “.”  换行之外的任意字符(0-1个)
  13. “*”  代表前面字符的任意数量重复
  14. “\S” 空白之外的任意字符(0-1个)
  15. “?”  .* 和 .*? 的区别,一长一短
  16. 6,.*? 和 \S*
  17. 7,
  18. \d = [0123456789]= =[0-9] -> [a-zA-Z] : 任意长度数字\d* or [0-9]*
  19. *号任意数量可以取到0,+号从1开始:    非0的任意长度数字\d+ or [0-9]+
  20. 使用{n}从任意数量变为固定数量n:     \d{11} or [0-9]{11} 代表11位数字
  21. 电话号码的匹配: 1\d{10} or 1[0-9]{10}
  22. {n}  {n,}  {n,m}  的区别。  其中 ?={0,1}
  23. 8,
  24. \w - 匹配字母或数字或下划线或汉字(3.x版本可以匹配汉字,但2.x版本不可以)
  25. \s - 匹配任意的空白符
  26. ^ - 匹配字符串的开始
  27. $ - 匹配字符串的结束         注意与\b的异同
  28. \W - 匹配任意不是字母,数字,下划线,汉字的字符
  29. \D - 匹配任意非数字的字符
  30. \B - 匹配不是单词开头或结束的位置
  31. [^abcd]  除abcd以外的任意字符
  32. '''

  33. '''
  34. 例题1
  35. import re
  36. text = "Hi, I am Shirley Hilton. I am his wife."
  37. text2 = "site sea sue sweet see case sse ssee loses"
  38. pattern1 = r"\bs.*?e\b"
  39. pattern2 = r"\bs\S*e\b"  #.*? 和 \S*的区别
  40. m = re.findall(pattern2, text2)
  41. if m:
  42.     print (m)
  43. else:
  44.     print ('not match')
  45. '''

  46. '''
  47. 例题2
  48. '''
  49. import re
  50. text = ['(021)88776543','010-55667890','02584453362','0571 66345673']
  51. pattern = r"\(?[0-9]+[\)\-\s]?[0-9]+"            # ()-等字符都需要转义
  52. pattern2 = r"\(?0\d{2,3}[) -]?\d{7,8}"           # 更准确的匹配:首位0,考虑数字的数量。注意数字的两种写法以及空格的匹配区别
  53. pattern3 = r"\(0\d{2,3}\)\d{7,8}|0\d{2,3}[ -]?\d{7,8}"  #使用|匹配有或者没有()的两种情况
  54. m = []
  55. for i in range(0,4):
  56.     m.append(re.findall(pattern, text[i]))
  57.     if m[i]:
  58.         print (m[i])
  59.     else:
  60.         print ('not match')
  61. print(m)
复制代码
回复

使用道具 举报

1

主题

0

好友

45

积分

新手上路

Rank: 1

地板
发表于 2017-8-16 00:36:30 |只看该作者
本帖最后由 vocaliu 于 2017-8-16 10:45 编辑

果然很简单。。。
  1. regx = r'http://[\S]*/[0-9]{2}\.jpg'
复制代码
顺带又加上了建立文件夹前的if not os.path.exists和下载图片后time.sleep(0.5),代码结构已经基本完整。
可以改进的细节:
之前为了方便做文件大小判定,用的read()之后write()进文件的方式,现在不需要判定文件大小了,可以直接用 urllib.request.urlretrieve();
文件命名纯数字,可以获取每个网页的<title>然后保存成文件夹名;
总之这个图片站抓取完成,选这个网站的原因是一个页面直接几张图,后续需要尝试其他图片站,点击当前图片进入下一页浏览的模式。
看起来好像要学beautysoup

另一边,中文抓数据的那个由于网页非常简单,感觉似乎可以用 \w{2,} 的方式直接取中文,试试去。搞错了\w是包括抓中文不是只抓中文,网上找到这个成功了。
  1. r'[\u4e00-\u9fa5]{2,}'
复制代码
要的刚好是一些2个汉字以上的词语,那些被   隔开的中文本来就用不着。抓出来得到一个[],保留其中有用的数据。
抓的数据有问题,有些文本抓取错误,比如地址会带数字和符号等。改用:
  1. r'[\u4e00-\u9fa5]+\S+[\u4e00-\u9fa5]+'
复制代码
这样可以抓连续的以汉字开头以汉字结尾中间没有空格的数据,但是这样遇到只写到数字房间号结束的地址类型还会出问题,尝试把正则改一下:
  1. r'\S+[\u4e00-\u9fa5]+\S+'
复制代码
这样应该是连续的包含汉字的内容,但是不能识别2个字的名字。
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

5#
发表于 2017-8-16 09:20:24 |只看该作者
你学得挺快
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

1

主题

0

好友

45

积分

新手上路

Rank: 1

6#
发表于 2017-8-16 11:52:04 来自手机 |只看该作者
本帖最后由 vocaliu 于 2017-8-19 17:35 编辑
crossin先生 发表于 2017-8-16 09:20
你学得挺快

带着目的学就会快嘛,虽然是套话但是的确有道理。是真想要学会一种语言解决工作中遇到的各种情况。
跟编程的交集是大学要学C,没有感受到用处,混成补考。这些年是越来越觉得有点编程能力不管干啥都好一点,除非牛到干啥都可以掏钱找人实现。
回复

使用道具 举报

1

主题

0

好友

45

积分

新手上路

Rank: 1

7#
发表于 2017-8-17 16:06:25 |只看该作者
本帖最后由 vocaliu 于 2017-8-17 16:34 编辑

续前面的内容,关于抓网页的文字内容,整理成数据库。用
  1. r'[\u4e00-\u9fa5]+\S+[\u4e00-\u9fa5]+'
复制代码
的方式匹配得到list1,
然后用list2.append(list1[10])的方式把有用的数据重新填到新的list里,
用到了n.append(' '.join(m_t1[4][77:-7].split()))的形式来抓具体的内容,
再整理成一个二位列表 list3.append(list2)
实现了批量抓数据的工作。
之后通过优化正则方案,得到了更精确的结果。
由于还没有学数据处理相关的操作,学了一下xlwt的方式把上述二维list导入excel保存成xls文件。抓了上千个页面,导出成为一个1000*30的excel。
爬网页数据并整理的工作初步完成。。
回复

使用道具 举报

0

主题

0

好友

18

积分

新手上路

Rank: 1

8#
发表于 2017-8-20 11:48:57 |只看该作者
本帖最后由 feifeiwuda 于 2017-8-20 11:50 编辑

请教楼主,我按你的代码在pycharm中运行了一遍,怎么什么都没有啊??也没有在f盘下有新建的pic文件夹。。。求解答
以下是运行结果:

Parent process 36988.
All subprocesses done.

Process finished with exit code 0
回复

使用道具 举报

1

主题

0

好友

45

积分

新手上路

Rank: 1

9#
发表于 2017-8-20 13:40:26 |只看该作者
那个代码是四处拼的,多进程部分的代码可能把前面所有的报错都吃掉了。
你把54行以后的删掉,直接写一行
imgdownload_num(1, 3)
看看会报什么错吧
回复

使用道具 举报

1

主题

0

好友

45

积分

新手上路

Rank: 1

10#
发表于 2017-8-20 13:54:43 |只看该作者
feifeiwuda 发表于 2017-8-20 11:48
请教楼主,我按你的代码在pycharm中运行了一遍,怎么什么都没有啊??也没有在f盘下有新建的pic文件夹。。 ...

这个是我的第一个练手程序,每个功能实现都是百度之后抄一两行代码再改的,虽然能用但是小毛病很多。

1, 我用的mkdir,所以你得先自己建一个f:/pic 文件夹,否则你换成makedirs才能自动生成pic文件夹

2, 你把54行以后的删掉,直接写一行
imgdownload_num(1, 3)
看看会报什么错吧

3, 实际测试发现,这个网站现在卡的要死,我现在下载有的也下不下来。需要把request里的timeout设高一点,否则有时候明明有图片也报错。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即加入

QQ|手机版|Archiver|Crossin的编程教室 ( 苏ICP备15063769号  

GMT+8, 2024-11-23 03:41 , Processed in 0.023802 second(s), 21 queries .

Powered by Discuz! X2.5

© 2001-2012 Comsenz Inc.

回顶部