Meetup.com Attendance Lists

Nov 8, 2010
• Dave Hunt

For the recent London Selenium Users Meetup Event I was asked if I could provide
the attendance list in a suitable format for creating labels for the guests when
they arrive. Given the short timeframe I did this simply by highlighting the
names on meetup.com, copying them, and pasting them into a simple text editor. I
then quickly cleaned this up before sending the list on. Within a short while
the list was out of date due to some members dropping out.

It did occur to me at the time that I could write a simple Selenium script, but
I didn’t want to delay providing the list. Well I’ve now had some time to
revisit this, and hopefully for the next meetup event I’ll be more prepared. The
following script should work on both upcoming and past events. It doesn’t
support waiting lists, and may have problems if meetup.com truncates lists after
a certain number. I may revisit these items once I’ve scheduled the next event.

importorg.openqa.selenium.By;importorg.openqa.selenium.NoSuchElementException;importorg.openqa.selenium.WebElement;importorg.openqa.selenium.chrome.ChromeDriver;importorg.openqa.selenium.htmlunit.HtmlUnitDriver;importorg.testng.annotations.AfterTest;importorg.testng.annotations.BeforeTest;importorg.testng.annotations.Test;importjava.util.ArrayList;importjava.util.List;publicclassMeetup{HtmlUnitDriverdriver;Stringmeetup="seleniumlondon";//meetup name from URLStringevent="14712022";//event ID from URL@BeforeTestpublicvoidstartDriver(){driver=newHtmlUnitDriver();}@AfterTestpublicvoidstopDriver(){driver.close();}@TestpublicvoidlistResponses(){//open the event pagedriver.get("http://www.meetup.com/"+meetup+"/calendar/"+event+"/");if(driver.findElement(By.xpath("id('C_document')/descendant::dl[@class='stats'][2]/dt")).getText().equals("Who's coming?")){//this event has not yet occurredlistMembers("id('C_document')//li[div[@class='D_attendeeHeader D_yes']]//li[starts-with(@id, 'member_')]","Yes");listMembers("id('C_document')//li[div[@class='D_attendeeHeader D_maybe']]//li[starts-with(@id, 'member_')]","Maybe");listMembers("id('C_document')//li[div[@class='D_attendeeHeader D_no']]//li[starts-with(@id, 'member_')]","No");}else{//this event is in the pastlistMembers("id('C_document')//li[starts-with(@id, 'member_')]","Attended");}}publicvoidlistMembers(Stringxpath,Stringlabel){//get a list of all members that have responded or attendedList<WebElement>memberElements=driver.findElements(By.xpath(xpath));intguestTotal=0;//set guest total to zeroList<Member>members=newArrayList<Member>();//create a list to store our membersfor(WebElementmember:memberElements){Stringname=member.findElement(By.className("D_name")).getText();//member nameintguests=0;//set member's guests to zero//get the number of guests for this membertry{//upcoming events use a different class for the guest count as past eventsStringguestsTemp=member.findElement(By.className("guests")).getText();guests=newInteger(guestsTemp.substring(guestsTemp.indexOf("+")+1,guestsTemp.indexOf(" ")));}catch(NoSuchElementExceptione){}try{StringguestsTemp=member.findElement(By.className("D_guests")).getText();//past events use a different format for the guest countguests=newInteger(guestsTemp.substring(guestsTemp.indexOf("+")+1,guestsTemp.indexOf(")")));}catch(NoSuchElementExceptione){}guestTotal=guestTotal+guests;//update the total number of guests for this eventmembers.add(newMember(name,guests));//add the current member to our list}//output a label for this list including total member and guest countsSystem.out.println("\n"+members.size()+" "+label+getGuestSuffix(guestTotal));for(inti=0;i<members.size();i++){//output details for each memberSystem.out.println(i+1+". "+members.get(i).name+getGuestSuffix(members.get(i).guests));}}publicStringgetGuestSuffix(intguests){//return a suffix to indicate the number of guestsif(guests>0){return" (+"+guests+" guest"+(guests>1?"s":"")+")";}else{return"";}}//inner class for memberspublicclassMember{Stringname;intguests;publicMember(Stringname,intguests){this.name=name;this.guests=guests;}}}