爬虫中如何科学上网

为什么爬虫也要科学上网

因为有时候我们还想spider一下外面的世界,油管小鸟谷歌什么的,这时候肯定要出去啦。

构成

简单的科学上网爬虫,我们一般会做这么几件事情。第一是set-up,然后是Request请求(headers来spoof browser),然后是打开页面读取内容,最后是分析并且获取内容。

详细操作

  1. Set-up
  • opener。其中opener包含了proxy作为其中一个handler。对于ProxyHandler,其中包含的proxy必须为一对一对的。

    proxyhandler = urllib2.ProxyHandler(‘http’: ‘proxy地址’,’https’: ‘proxy地址’)

    上面的proxy地址,一般为一个类似于blah.blah.com:8080这样的字符串,包含了地址和端口。

  • 如果需要urllib2.urlopen全部都使用该opener的话,安装这个opener。否则不用安装,在需要使用该opener的时候调用该opener即可。
  1. urllib2.Request是一个URL Request的abstraction,包含了url,headers等参数。urllib2.Request(url, data, headers, originreqhost, unverifiable)
    • headers:因为有很多网站以及proxy对爬虫不太友好;。我们通常需要用headers来伪装成一个浏览器。另外referer有时候也有需要。

      headerinfo =
      ‘User-Agent’:’Mozilla/5.0 (Macintosh; Intel Mac OS X 10105) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36′,
      ‘Proxy-Connection’: ‘keep-alive’,
      ‘Connection’:’keep-alive’

      req = urllib2.Request(url, headers = headerinfo)

  2. 打开页面读取内容这一步没有什么特别的。无非就是

    response = urllib2.urlopen(req)

    content = response.read()

  3. 分析并且获取内容这里涉及到正则表达式,数据分析,数据保存等等问题,这一块涉及到的问题比proxy这块多得多。以后再学习添加相关内容。

小结

这只是爬虫中的一个trick。不过如果使用proxy的时候,记得看看你的proxy服务有没有对爬虫限制哦。

面向对象的爬虫(以百度贴吧为例)

其实很早就学过python的正则表达式了,然而一直没有很好的实践,直到最近在网上找到这个帖子,做了一个爬虫出来,效果还挺好。代码就不贴了(可以到原帖找),这里记一下我写的思路。

 

Step 1 设定目标
Step 2 定义一个爬虫类,包含两个methods:一个初始化、一个获取页面信息
Step 3 定义更多的methods,来使用正则表达式提取内容,包含

  1. 帖子标题
  2. 帖子的总页数
  3. 帖子的正文内容
Step 4 使用re,对正文内容进行进一步整理。并且为了方便重用,把这个封装成一个类
Step 5 加上行号
Step 6 保存在文件中
Step 7 写外面的大循环,将每一页都循环出来
Step 8 问答式GUI
  1. 设定目标

1.对百度贴吧的任意帖子进行抓取

2.指定是否只抓取楼主发帖内容

3.将抓取到的内容分析并保存到文件

  1. 定义一个爬虫类:BaiduTieba

方法:

Init 初始化。 属性包含BaseURL,seeLZ的标志。
getPage 获取页面 通过URL获取到页面的内容,以便于后面通过RE进行处理

 

如果在内网或者要通过proxy,还需要定义proxy_handler,然后写到opener之中。

 3. RE处理

内容(red is for 提取) RE 分析 作用
帖子标题

getTitle(self, page)

<h3 class=”core_title_txt pull-left text-overflow  ” title=”纯原创我心中的NBA2014-2015赛季现役50大” style=”width: 396px”>纯原创我心中的NBA2014-2015赛季现役50大</h3> <h3 class=”core_title_txt.*?>(.*?)</h3> 得到的帖子标题,可以在后面用于保存文件时使用
帖子的总页数

getPageNum(self, page)

<li class=”l_reply_num” style=”margin-left:8px” ><span class=”red” style=”margin-right:3px”>140</span>回复贴,共<span class=”red”>5</span>页</li> <liclass=”l_reply_num.*?<span.*?>(.*?)</span>.*?<span.*?>(.*?)</span> 由于这个class出现了4次,所以需要以更严格的RE来筛选。注意这个公式里,我用的gorup(2)表示的总页数 可以写循环,让每一页都被拔下来
帖子的正文内容

getContent(self, page)

<div id=”post_content_…>……</div> <divid=”post_content_.*?>(.*?)</div>

4. 通过REcontent进行进一步处理

为了方便以后重用,将这个写作单独的一个class<Tool>

内容 代码 分析 RE
图片 <img class=…> 删除
超链接tag <a …>…</a> 删除
换行tag <tr>|<div>|</div>|</p> n
制表符 <td> t
段落开头 <p> n+2space
换行,双换行 <br><br>|<br> n
其他标签 <.*?> 删除

 

5. 加上行号

很简单,在writeContent的时候加上计数器即可

6.保存在文件中

Self.file = open(“xxx.txt”, “w+”)

Self.file.write(content)

7. 外面的大循环

其实这里就是要将getPageContent(pageNum)这个动作函数化

 8.问答式GUI

这里可以用一个问答式的GUI询问用户想看的内容。

这个如果做到后面,也可以 做成GUI