中国土地市场网 landChina爬虫(代理分布式版本)

main01

这个程序通过selenium采用ChromeDrive的无头浏览器方式,从 http://www.landchina.com/default.aspx?tabid=263&ComName=default 获取交易信息的url,并且存入redis中。

对于交易信息,可以加时间与地区做筛选:

def llq_main(start, end):
    print(start, end)
    time.sleep(2)
    # 对时间条件进行赋值
    driver.find_element_by_id('TAB_queryDateItem_270_1').clear()
    driver.find_element_by_id('TAB_queryDateItem_270_1').send_keys(start)
    driver.find_element_by_id('TAB_queryDateItem_270_2').clear()
    driver.find_element_by_id('TAB_queryDateItem_270_2').send_keys(end)
    # 进行行政区的选择
    driver.find_element_by_id('TAB_QueryConditionItem256').click()
    driver.execute_script("document.getElementById('TAB_queryTblEnumItem_256_v').setAttribute('type', 'text');")
    driver.find_element_by_id('TAB_queryTblEnumItem_256_v').clear()
    driver.find_element_by_id('TAB_queryTblEnumItem_256_v').send_keys('3205')  # 3701是济南; 37是山东
    driver.find_element_by_id('TAB_QueryButtonControl').click()  # 查询操作
    page_zh(i, l)

if __name__ == '__main__':
    llq_main('2005-01-01', '2006-7-30')

比如这里的3205就是地区码,最后一行的两个时间就表示起止时间。

设置代理很简单,我直接用了以前买的ssr,占用的是localhost的1080端口

proxy = '127.0.0.1:1080'
proxies = {
    'http': 'socks5://' + proxy,
    'https': 'socks5://' + proxy
}

对于selenium用代理,需要如下设置:

options.add_argument('--proxy-server=http://' + proxy)

完整代码如下:

# coding=utf-8
import time
import re
import redis
from bs4 import BeautifulSoup
from selenium import webdriver

proxy = '127.0.0.1:1080'
proxies = {
    'http': 'socks5://' + proxy,
    'https': 'socks5://' + proxy
}

r = redis.Redis(host='127.0.0.1', port=6379, db=0)  # host自己的ip地址
options = webdriver.ChromeOptions()
options.add_argument('--proxy-server=http://' + proxy)
options.set_headless()
driver = webdriver.Chrome(chrome_options=options)  # 打开chrome_headless浏览器
driver.get('http://www.landchina.com/default.aspx?tabid=263&ComName=default')  # 打开界面
i = 1
l = 0
date_list = []
time.sleep(8)
driver.find_element_by_id('TAB_QueryConditionItem270').click()



def page_zh(i, l):
    # 获取本时间段内的总页数(方法)int(reg[0])
    zys = driver.find_elements_by_css_selector(".pager")
    if (zys != []):
        str = zys[1].text;
        reg = re.findall(r'\d+', str)
        pages = int(reg[0])
        print("总页数为:" + reg[0])
        tds = driver.find_elements_by_css_selector(".pager>input")
        # 清空文本方法
        tds[0].clear()
        tds[0].send_keys(i)
        print("第" + tds[0].get_attribute("value") + "页")
        tds[1].click()
    elif (zys == []):
        pages = 1

    time.sleep(4)
    # 获取页面html
    html = driver.find_element_by_id('TAB_contentTable').get_attribute('innerHTML')
    soup = BeautifulSoup(html, 'lxml')  # 对html进行解析
    href_ = soup.select('.queryCellBordy a')
    for line in href_:
        print("http://www.landchina.com/" + line['href'])
        link = "http://www.landchina.com/" + line['href']
        # 链接redis
        r.sadd('mylist', "http://www.landchina.com/" + line['href'])

    if (i < pages):
        i = i + 1
        page_zh(i, l)

    else:
        print("本次采集结束!!!")


# 关闭浏览器(selenium)
# driver.quit()

def llq_main(start, end):
    print(start, end)
    time.sleep(2)
    # 对时间条件进行赋值
    driver.find_element_by_id('TAB_queryDateItem_270_1').clear()
    driver.find_element_by_id('TAB_queryDateItem_270_1').send_keys(start)
    driver.find_element_by_id('TAB_queryDateItem_270_2').clear()
    driver.find_element_by_id('TAB_queryDateItem_270_2').send_keys(end)
    # 进行行政区的选择
    driver.find_element_by_id('TAB_QueryConditionItem256').click()
    driver.execute_script("document.getElementById('TAB_queryTblEnumItem_256_v').setAttribute('type', 'text');")
    driver.find_element_by_id('TAB_queryTblEnumItem_256_v').clear()
    driver.find_element_by_id('TAB_queryTblEnumItem_256_v').send_keys('3205')  # 3701是济南; 37是山东
    driver.find_element_by_id('TAB_QueryButtonControl').click()  # 查询操作
    page_zh(i, l)


if __name__ == '__main__':
    llq_main('2005-01-01', '2006-7-30')

mian02

该程序的思路很简单:
0.selenium通过代理ip地址打开一个目标网站的界面,构造出一个可用的cookie:

def getCookie():
    options = webdriver.ChromeOptions()
    options.add_argument('--proxy-server=http://' + proxy)
    options.set_headless()
    driver = webdriver.Chrome(chrome_options=options)  # 打开chrome_headless浏览器
    driver.get('http://www.landchina.com/default.aspx?tabid=263&ComName=default')  # 打开界面
    time.sleep(5)
    cookie = driver.get_cookies()
    str1 = list(cookie)
    cookieStr = ''
    for i in range(0, 6):
        cookieStr = strnew + str1[i]['name'] + '=' + str1[i]['value'] + ';'
    print(cookieStr)
    driver.quit()
    return cookieStr

1.从redis取一个url:
通过r.spop()函数随机取一个url,调用parse()函数进行页面解析

def checkRedis(sleepCounter, headers):  # 从redis读url
    while 1:
        if r.scard('mylist') != 0:
            url = r.spop('mylist')
            # print(url)
            time.sleep(2)
            parse(url, headers)
        elif sleepCounter < 100:
            print('waiting...' + str(sleepCounter))
            sleepCounter += 1
            time.sleep(1)
        else:
            print('quit')
            break

2.通过代理ip地址,用最开始构造的cookie构造一个适用的headers;发出请求,完成页面解析:

def createHeaders(cookie):
    headers = {
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
        'Accept-Encoding': 'gzip, deflate',
        'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7',
        'Cache-Control': 'max-age=0',
        'Connection': 'keep-alive',
        'Content-Type': 'application/x-www-form-urlencoded',
        'Host': 'www.landchina.com',
        'Origin': 'http://www.landchina.com',
        'Upgrade-Insecure-Requests': '1',
        'Cookie': cookie,
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'
    }
    return headers

具体的页面解析我就没有放出来了,有兴趣的自己写写

def parse(url, headers):
    page = requests.get(url, headers=headers, proxies=proxies)
    doc = pq(page.text)

最后介绍一个我觉得很有用的包,叫做retry。顾名思义,用于方法出错后重试的包,对方法进行修饰。
我这里把整个爬虫的过程写在一个方法中,并加上了retry的修饰(出错了等待2秒后就重试,最多重试5次):

@retry(tries=5, delay=2)
def doTheJob():
    cookie = getCookie()
    headers = createHeaders(cookie)
    checkRedis(0, headers=headers)

doTheJob()

最后完整代码如下:

# coding=utf-8
import requests
from pyquery import PyQuery as pq
from redis import StrictRedis
from selenium import webdriver
import time
from pymongo import MongoClient
from retry import retry

r = StrictRedis(host='127.0.0.1', port=6379, db=0)
client = MongoClient()
db = client['landchina_qd']
collection = db['landchina_qd']

proxy = '127.0.0.1:1080'
proxies = {
    'http': 'socks5://' + proxy,
    'https': 'socks5://' + proxy
}


def saveToMongo(data):
    if collection.insert(data):
        print('Saved to mongo.')


def checkRedis(sleepCounter, headers):  # 从redis读,并解析页面
                                        # 如果redis中暂无数据,等待。等待时间超过100秒后退出程序。
    while 1:
        if r.scard('mylist') != 0:
            url = r.spop('mylist')
            # print(url)
            time.sleep(2)
            parse(url, headers)
        elif sleepCounter < 100:
            print('waiting...' + str(sleepCounter))
            sleepCounter += 1
            time.sleep(1)
        else:
            print('quit')
            break


def getCookie():
    options = webdriver.ChromeOptions()
    options.add_argument('--proxy-server=http://' + proxy)
    options.set_headless()
    driver = webdriver.Chrome(chrome_options=options)  # 打开chrome_headless浏览器
    driver.get('http://www.landchina.com/default.aspx?tabid=263&ComName=default')  # 打开界面
    time.sleep(5)
    cookie = driver.get_cookies()
    str1 = list(cookie)
    strnew = ''
    for i in range(0, 6):
        strnew = strnew + str1[i]['name'] + '=' + str1[i]['value'] + ';'

    print(strnew)
    driver.quit()
    return strnew


def createHeaders(cookie):
    headers = {
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
        'Accept-Encoding': 'gzip, deflate',
        'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7',
        'Cache-Control': 'max-age=0',
        'Connection': 'keep-alive',
        'Content-Type': 'application/x-www-form-urlencoded',
        'Host': 'www.landchina.com',
        'Origin': 'http://www.landchina.com',
        'Upgrade-Insecure-Requests': '1',
        'Cookie': cookie,
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36'
    }
    return headers


def parse(url, headers):
    page = requests.get(url, headers=headers, proxies=proxies)
    doc = pq(page.text)
      #页面解析部分感兴趣可以自己写
    data = [{
        'district': district,
        'name': name,
        'location': location,
        'size': size,
        'usage': usage,
        'price': price,
        'time': time,
        'url': url
    }]
    saveToMongo(data)


@retry(tries=5, delay=2)
def doTheJob():
    cookie = getCookie()
    headers = createHeaders(cookie)
    checkRedis(0, headers=headers)


doTheJob()

最后程序运行结果很稳定,速度快的飞起

跑的时候开了20个程序一起跑,能做到一分钟爬30条左右。
main01

该程序获取交易信息的url,存入redis
main02

可以看到这里的main02 和 4 ,5 三个程序运行正常,他们都是跑的同一个程序。


分布式

勉强算个分布式爬虫吧,毕竟只有一台电脑。。。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,591评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,448评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,823评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,204评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,228评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,190评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,078评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,923评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,334评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,550评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,727评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,428评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,022评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,672评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,826评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,734评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,619评论 2 354

推荐阅读更多精彩内容