十月故里 发表于 2020-5-5 21:16:15

python3代理池的搭建(一)

本帖最后由 十月故里 于 2020-5-6 18:39 编辑

最近看完崔庆才《网络爬虫开发实战》一书,对于里面的代理池搭建非常感兴趣,学习完迫不及待给大家分享下,里面的源码部分借鉴了书中的内容,部分内容由于有些库没装(外面的资源,下不来),有些是实测过后,部分网站代码结构变了,只能利用自己学过的东西魔改了下,还好折腾一晚上弄出来了~~~~

废话不多说,这一个系列大概有三部分:

[*]第一部分主要是构建爬取代理网站的代码块
[*]第二部分主要是构建一个数据库用于储存爬取的代理ip        https://fishc.com.cn/thread-168109-1-1.html
[*]第三部分主要是构建一个检测代码用于测试这些ip是否都好使        https://fishc.com.cn/thread-168112-1-1.html


下面的内容全部是在python3.8.2的版本搭建的,用到的库主要有pyquery,requests, sqlite3, threading

现在进入主题,由于本人五行缺钱,于是目标都放在来免费的代理网站上,这里主要对http://www.66ip.cn/,http://www.goubanjia.com/,https://www.kuaidaili.com/free/inha/三个代理网站进行爬取
在爬取网站之前,为了日后方便添加其他代理网站的爬取代码块,这里利用继承type的基类来动态添加类属性(这部分内容我也还是一知半解,想深究的童鞋可以百度metaclass,然后有很多大佬对这个内容进行的讲解)
首先我们看看代码
class ProxyMetaclass(type):
    def __new__(cls, name, bases, attrs):
      count=0
      attrs['__CrawlFunc__']=[]
      for k,v in attrs.items():
            #把爬取的方法名动态添加到crawlfunc集合中,用于遍历回调
            if 'crawl_' in k:
                attrs['__CrawlFunc__'].append(k)
                count +=1
      attrs['__CrawlFuncCount__']=count
      return type.__new__(cls, name, bases, attrs)

在继承type类后,我们调用attrs属性,通过检索后面定义的爬取方法的名字,只要里面出现’crawl_‘这样的结构,就动态的添加到'__CrawlFunc__'中,方便接下来的第二部分能够动态的调用我们提前写好的爬取网站的代码,也便于日后能进行简单的添加其他爬取代码后,不需要修改主体内容即可自动爬取(不明白的童鞋可以去看第二部分的内容,就应该理解为什么这么设置了)

接下来就是重头戏,搭建我们的爬取网站的代码,废话不多说,先看代码
from pyquery import PyQuery as pq
import requests
headers={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
}
def get_page(url):
    html=requests.get(url,headers=headers).text
    return html

class Crawler(object, metaclass=ProxyMetaclass):
    def get_proxies(self,callback):
      proxies=[]
      #eval用来执行字符串表达式,并返回表达式的值
      for proxy in eval("self.{}()".format(callback)):
            print('成功获取到代理',proxy)
            proxies.append(proxy)
      return proxies

    def crawl_daili66(self,page_count=3):
      start_url='http://www.66ip.cn/{}.html'
      urls=
      for url in urls:
            print('Crawling',url)
            html = get_page(url)
            if html:
                doc=pq(html)
                # main > div > div:nth-child(1) > table > tbody > tr:nth-child(2)
                #gt选取索引大于0的节点
                trs=doc('.containerbox table tr:gt(0)').items()
                for tr in trs:
                  # main > div > div:nth-child(1) > table > tbody > tr:nth-child(2) > td:nth-child(1)
                  ip = tr.find('td:nth-child(1)').text()
                  # main > div > div:nth-child(1) > table > tbody > tr:nth-child(2) > td:nth-child(2)
                  port=tr.find('td:nth-child(2)').text()
                  yield ':'.join()

    def crawl_goubanjia(self):
      start_url='http://www.goubanjia.com/'
      html=get_page(start_url)
      print('Crawling', start_url)
      if html:
            doc=pq(html)
            tds = doc('td.ip').items()
            for td in tds:
                #print(tr.text())
                td.find('p').remove()
                #print(td.text())
                yield td.text().replace('\n', '')

    def crawl_kuaidaili(self,page_count=1):
      start_url='https://www.kuaidaili.com/free/inha/{}/'
      urls =
      for url in urls:
            html=get_page(url)
            print('Crawling', url)
            if html:
                doc=pq(html)
                #.items()必须要有,否则trs只是一个element的集合,里面的元素都是str
                trs=doc('#list table tbody tr').items()
                for tr in trs:
                  # list > table > tbody > tr:nth-child(1) > td:nth-child(1)
                  ip = tr.find('td:nth-child(1)').text()
                  port=tr.find('td:nth-child(2)').text()
                  yield ':'.join()


上面的代码就是同过去相应的网站分析html代码格式,然后爬取需要的内容,这里我用的是pyquery库,这个库对css的筛选比较给力,直接去网站找到对应的内容然后copy一下就好了
同时我们注意到在构建这个类的时候,设置了一个属性metaclass=ProxyMetaclass,这一部分就是为了动态把爬取代码块添加到'__CrawlFunc__'列表用,方便后面调用,同时也方便日后添加其他网站的爬取代码,只要方法名中带有‘crawl_’就可以了

好了第一部分就讲到这里了,感兴趣的童鞋可以继续前往第二部分批评指导哈{:5_108:}

Hello. 发表于 2020-5-5 21:22:06

支持一下{:10_256:}

十月故里 发表于 2020-5-5 22:06:11

Hello. 发表于 2020-5-5 21:22
支持一下

谢谢大佬{:5_102:}

zwhe 发表于 2020-5-29 10:20:52

{:7_141:}
页: [1]
查看完整版本: python3代理池的搭建(一)