Tips for Securing a Training Contract at a Top Law Firm

My last six years have been a voyage of law career discovery, and it would have been so much simpler if someone had just told me what to do , what the risks were, and what the timescales were. As a good person, now being on the other side of that learning curve, I’m going to fulfil my moral duty and share the love.

Here’s what I wish someone told me:

First Year

So you’ve had your freshers’ year, snogged a few frogs, and are cruising through Contract Law 1, but haven’t had a chance to figure out what you want to do with your life. Now, at this point, you’re probably doing a law degree because you think it will lead to you becoming a lawyer. WELL, WRONG.

via GIPHY

Getting a training contract is now one of the hardest things in the world, next to getting a man to text you back within 45 minutes. You need to prep, prep, prep. Fortunately, you need look no further than this incendiary cheat sheet…

You’d better have your CV ready, girl. Like Tinder, it’s a numbers game. For perspective, before securing a training contract at a city law firm, I sent out my CV to every single firm in the city, and only had one response. Now, you shouldn’t take it personally, ever: it’s just like any other form of rejection. You gotta finesse that CV as if your boyfriend just left you, and you’re changing your Facebook picture. This is a game, and you’ve got to play it well.

In your first year, nobody is expecting you to have any experience. What they want is perseverance: you have to pester anyone and everyone until they let you sit in their office for a week, making tea and photocopying shizz. You might think this isn’t worthwhile, but any trainee solicitor will tell you that it’s not about what you’re doing, but that you have something on that CV when it comes to TC application day. Another thing you should definitely be doing is volunteering for the Citizens’ Advice Bureau. Graduate recruitment loves that shit. You get to show your “good human” and it’s one step closer to securing that job. Any legal-looking thing you can do in your first year is a bonus – miss classes if you must. After all, your first year doesn’t count towards your degree, so you go girl.

Second Year

Now you’ve been a good girl and followed my advice, and you’re well on track to securing a vacation scheme.

If you find yourself in second year and you’ve got nothing on your CV, you’re pretty much screwed. But fear not. It’s not the end of the world, you’ve just got to be smarter. Second year is that vacation scheme year. If you don’t secure that vac scheme place, you reduce your chance of getting a TC by 80%. Firms love people they’ve already vetted, and in some cases, the process for the vacation scheme is tougher than for the actual TC.

Research, research, research. Know the firm. Know their worth. Know your worth. I can’t stress this enough. You can’t stroll in to a national firm and say you want to do international cross-border work. And you can’t stroll up to a magic circle firm and say you want to do family law. Have an agenda, and follow it through. No one likes a confused girl, so why would you think it would work in the real world. You need to have the focus of a one-legged man in an ass-kickin contest.

A few tips include:

  1. Do not look at their graduate recruitment website for answers. You need to look at the client section: how they market themselves, is what they want to hear back.
  2. You need to find out if that particular firm is involved in any way with your current university, and if so, play on how much you appreciate the sponsorship.
  3. You need to know which city you want to be in. We all know that one person who wants to train in Leeds and then fuck off to London. You can’t be doing that – they see right through you.
  4. You need to have work experience. You’re never going to convince anyone in that interview room that you want to be a lawyer, if the last job you had was a barista in the hipster part of your city.
  5. You need to know why you want to be a lawyer. And saying that you liked Ally McBeal is not a valid answer 😛
  6. You need to explain why you’re doing a law degree, and if you’re one of those converts, you need to state your reasons for the conversion.
  7. You need to not appear to be a dick. Most lawyers are nice, and nothing like you see on TV, so don’t come in thinking that a show of aggression will endear you.

If you follow my advice, and secure yourself a TC, enjoy a life of a fully paid LPC and a maintenance grant (holiday money). Happy lawyering!

Third Year

So, if you’re reading this and you’re in third year, you have truly missed the boat. And… may be fucked beyond repair. I can’t really advise you much, because most firms recruit two years in advance, so you’re going to either have a year of “travelling”/”finding yourself”, or be a low-paid paralegal for some national firm/paralegal factory.

If you have no experience in your third year, you should probably reconsider your options. Whilst firms do like a mature candidate, if you have no valid reason for spending three years without having any kind of experience on your CV, you’re going to look incompetent.

You can still follow the advice above, but by the time you qualify, it might be a case of…


via GIPHY

Fourth Year

LOL.

The rules of dating a female lawyer

So you have gotten yourself a match on Tinder with an actual female. You peruse her profile and surprise, surprise, she has some legal sounding occupation. Guys, what do you do? Well, I suspect you have no idea what to do or else you would not stumble on to this virtual agony aunt platform. Don’t worry, I gotcha.

First things, first. Do not send a dick pic. I repeat, do not send a dick pic. Not only will a female lawyer not have time to look at your pee-pee, she probably spends most of her time proof reading lengthy contracts that her eye’s capacity for focussing on tiny penises is now probably rendered obsolete. You need to approach a female lawyer like you would approach the Holy Grail. Tread smoothly. A simple “hello …” with commendable punctuation would suffice. I mean if you are well hung, I am sure she won’t mind the random dick pic.

No, do not do that! That was a test. Keep your one minute wonder away from the female lawyer.

Ok so you have managed to engage her enough to get a response. She feigns an interest and replies to your messages a few times over the day but your obviously needy self wants to know how to get her to give you more. I mean at this point, the goal might just be to get her to send you some uncopyrighted nudes, but the principles will still apply here. You have to play it cool.

Female lawyers spend all day surrounded by old men telling them what to do, feeling high powered and drinking lots of coffee. You need to present a female lawyer with an alternative to her normal 8am – 8pm. I mean, be goofy if you must. All you need to understand is that she probably has hundreds of management consultants, doctors and software engineers lusting over her 24/7. If you are not man enough to handle it, leave this blog, man-child. Not many men are well equipped to deal with a woman who argues for a living. If you can’t take it, don’t waste her billable time!

If you have made it this far and are stupid enough to go ahead with dating a female lawyer, here are a few tips:

  1. Message her in the morning so she can reply to you on her commute. Do not expect communication during the day.
  2. Don’t appear emotionally needy – if you can’t handle not having attention during the day, you probably need to date batwoman’s attorney.
  3. Make weekday plans! Weekdays can be so exhausting and having company after a long day will set you apart from those weekend fuck-boys.
  4. Don’t forget that she probably lives for the weekend and there is plenty of sausage to be had on a Saturday.
  5. Ask her about her work – all lawyers like talking about themselves.
  6. Put things in her calendar – lawyers love that shit. It keeps us organised.
  7. At the earlier stages of dating, do not expect them to open up. I am sure claimant 1 thought defendant 1 would love her forever, but defendant 1 lied and now they are in the civil courts. We are risk averse because all we see are things when they go wrong, so don’t expect us to take you seriously if you promise us the world. Promissory estoppel has no place in the dating world.
  8. Female lawyers may value you according to how many units she would bill you. So you need to make every 6 minutes count or else she may have to write you off.
  9. Pencil skirts, that is all.
  10. You get the services of a lawyer for no consideration – Kerching!

If that hasn’t convinced you to go for that cold looking lawyer on Tinder, then take the above as obiter.

 

Regards,

Oxford Physics Admission Interview 2: Questions and Answers

It’s difficult to concisely say how my first interview left me feeling, but if I were forced to choose a word, I’d go with “bemused”. I’d gotten through one question fairly cleanly (like, I thought?), and one only with a significant amount of assistance from the tutors. Was that good? Was that expected? Having arrived 10 minutes early to the second interview on account of being extremely over-cautious in my estimates of how long it would take me to walk from my room to Tom Quad, there was nothing for it but to agonise over the dilemma whilst listening to the muffled voices in the room. Again I speculated how big the effect of having a good/bad candidate precede me would be.

After an awkward brushing past the previous candidate – it was a different one to before my first interview, so at least they were mixing it up that way – a face poked through the door and informed me that the interviewers would be with me in a minute. That was good. That was another unknown removed.

The setup was much the same as in the first interview: two tutors on one side of a desk upon which was some paper and biros, and me on the other. Once again, there was absolutely zero chit-chat about what I’d written in my personal statement, and question one came out…

Question 1

Imagine that you have two clocks. You can’t tell anything about their inner workings, just watch them tick. You take them both to the moon, and one goes crazy.

This was made no less funny by his saying it in a thick German accent. (I mean, he was German, he wasn’t putting it on just for the question.) I wouldn’t rise to that kind of cheap shot though, and merely nodded my understanding: sure, crazy clock. What of it? The other tutor took over…

Intuitively, what might you put this difference down to?

“GRAVITY?” I exploded, before quickly qualifying it with the more sober “I mean, a less-strong gravitational field?”

Dramatic shifts in seating positions.

What sort of clock might be affected by the gravitational field strength?

At this point, being aware that they were supposed to ask you about AS-Level stuff, I had an idea of where they might be going. I answered that a pendulum clock would.

If I were to tell you that the field strength on the surface of the moon is approximately a sixth of that on the surface of the earth, what would be the difference between the two clocks?

Ha! Rumbled. Fortunately, the formula for the time period of a pendulum clock was fresh in my mind from AS Level physics, and, thanks to that interview, still is to this day:

T=2\pi\sqrt\frac{l}{g}

… where l is the pendulum length and g is the field strength. In trying to compare the behaviour of the two clocks, I wrote two versions for earth-clock and moon-clock:

T_E=2\pi\sqrt\frac{l}{g_E} T_M=2\pi\sqrt\frac{l}{g_M}

And the interviewer had just told me that g_M=\frac{1}{6}g_E, so I could write

T_M=2\pi\sqrt\frac{l}{g_E/6}

… or, to form a more direct comparison I suppose,

T_M=\sqrt6T_E

There was, again, that awkward period where I felt I’d gotten to an answer and the tutors just stared at me, so I vocalised the result I’d just derived with “the time period of the clock on the moon is root six times the time period of the one on the earth.”

And root six is about, what?

WHAT KIND OF QUESTION IS THAT? Looking back, I suppose they were trying to see whether I thought that was a realistic answer or that alarm bells should be ringing, but at the time all I could think was “I’m being asked what the square root of 6 is in my Oxford interview.” I reasoned that it must be slightly above 2, so went with “about 2.3”. No feedback other than another awkward pause. The next question came out.

Question 2

Intuitively, what angle to the ground would you fire a cannon at in order to get the maximum range on the projectile?

I knew full-well that the answer was 45 degrees, having proved it at some stage during AS Level mechanics, and also having read recently that some guy had been the first to prove it. I was up front with this, but the interviewer was very keen that I was answering out of “intuition” rather than knowing the answer. Ah. Yes. Do let’s play that game. Talking about a reasonable compromise between vertical motion (for time of flight) and horizontal motion (for a greater rate of range progression), I went with 45 degrees with the air of one speculating that next summer might be warm.

Predictably, the extension was to prove this result, so I cracked out a cheeky diagram (framed prints are available – contact me):

Screen Shot 2014-08-20 at 12.50.14

… and wrote down the expressions for the vertical and horizontal components of the starting velocity:

v_V=Vsin\theta v_H=Vcos\theta

The time of flight is decided solely by the vertical motion: the projectile undergoes constant acceleration due to gravity, until it reaches a vertical velocity of the same magnitude but in the opposite direction, by which point it will hit the ground again. (Neglecting effects due to air resistance and other important real-world factors obviously.) Using one of the constant acceleration equations (difference between initial and final velocities is equal to the product of the acceleration and time of flight), and denoting the time of flight as t and the acceleration as g, you get:

2Vsin\theta=gt

ie, the time of flight is

t=\frac{2Vsin\theta}{g}

In the horizontal direction, no forces act, so the range of the projectile is just speed multiplied by time:

r=v_Ht r=(Vcos\theta)(\frac{2Vsin\theta}{g}) r=\frac{2V^2sin\theta cos\theta}{g}

This is all we need to answer the question – an expression for r as a function of θ, involving some constants V and g.

At this stage in the proceedings, the deities of trig identities threw me down a bone in the form of a memory. To find the maximum of this with respect to theta, you’d normally have to go through the rigmarole of differentiating, but by a lucky quirk of fate the relation sin(2\theta)=2sin\theta cos\theta was fresh in my mind, so I rewrote the above as

r=\frac{V^2}{g}sin(2\theta)

At this stage I took a chance that the interviewers would back me to know what a sine curve looks like, and that the (first) maximum occurs when the argument of the sine function is equal to 90 degrees, ie r_{max} occured when

2\theta_{max}=90^{\circ} \theta_{max}=45^{\circ}

The tutors looked at each other. One was clearly satisfied with this, and the other clearly wanted me to go through the differentiation rigmarole. Entertainingly, for some reason neither of them wanted to say this, so there was a good deal of grunting and widened eyes before one of them caved in and came out with the next question.

Question 3

You have a blob of metal that you can deform in any way you like. You start off with it in the form of a cuboid, and measure the resistance between each “end”. Now you want to deform it into another cuboid, where the resistance between the ends is double that of the original cuboid. How do you change its shape?

Ie, I wanted to go from something like this…

Screen Shot 2014-08-20 at 13.33.36

… to something like this…

Screen Shot 2014-08-20 at 13.34.28

… so that the resistance across the block in the latter case is double that of the block in the first place.

Given that we were talking about changing the length and cross-sectional area of a piece of metal, it seemed that the resistivity formula would be relevant, so I wrote that down:

R=\frac{\rho l}{A}

… where ρ is the resistivity of the material, l is the length of material, and A is the cross-sectional area.

One of the tutors encouraged me to write down “before” and “after” equations, and impose the relation between them that the “after” resistance be twice the “before” resistance.

R_1=\frac{\rho l_1}{A_1} R_2=\frac{\rho l_2}{A_2} R_2=2R_1

At this stage I supposed I needed some relationship between the various lengths and areas in order to eliminate some stuff and solve, so given that I was only changing the shape of the same bit of metal, I argued that the volumes before and after must be the same. If I multiplied the numerators and denominators on each side by the appropriate length, I could express the two in terms of volumes before and after thus:

\frac{\rho l_2^2}{A_2l_2} = 2\frac{\rho l_1^2}{A_1l_1} \frac{\rho l_2^2}{V_2} = 2\frac{\rho l_1^2}{V_1}

But, same piece of metal, so V_1=V_2, so…

l_2^2=2l_1^2

… ie,

l_2=\sqrt{2}l_1

So there you go, stretch it into a cuboid about 1.4 times as long and you’d have double the resistance. The interviewers nodded. There were a few very short questions about some areas of physics I’d mentioned in my personal statement, which amounted to little more than “so, you like that, do you?” And with that, my grand total of 40 minutes under the Oxford admissions microscope were over. In a haze of surreality I went and got my train.

Oxford Physics Admission Interview 1: Questions and Answers

Finding yourself at the culmination of two years’ anticipation and attempted preparation is oddly giddying. I’d visualised the beginning of my interviews so many times and in so many ways that standing in a dingy staircase in Blue Boar quad counting down the clock was absurdly low-key. For something that I myself had long-since defined as an important crossroads in my life, there should have been more drama. Maybe a murder. Something like that.

There I was though, sitting in one of those mass-produced plastic chairs that are ubiquitous through school, making forced conversation with some posh kid interviewing for History of Art or some rubbish, whose Mum turned out to be from the same town as me. Looking back, it was sort of disheartening how utterly flabbergasted he was to have come across another person who came from the town.

The interviewee before me scuttled out of the room and gave me no more than an inscrutable glance before going down the stairs. My competition; my rival. It’s strange to think that now, as we became, and remain to this day, great friends and shared most of the ups and down of uni. But in that moment, statistically, there was half a place that the two of us were going head-to-head for. Grr.

None of this was helpful to be thinking about, of course. A few minutes later I was sitting across the desk from the two interviewers, with a few sheets of blank A4 and a couple of biros between us. One was a tutorial fellow of the college who I’d stalked at length, the other a younger post-doc type. Someone had drawn a Gaussian and the number “1089” on the whiteboard. The manner of my showing in struck me at the time as bizarrely muted – was I in the bad books already? It didn’t occur to me until years later that the majority of professional physicists are simply awkward.

With very little in the way of preamble, the first question was forthcoming.

Question 1

Imagine that you have a length of fence, which you can bend at arbitrary points to make “corners”. You also have a wall, whose length is very much greater than the length of the fence. You’re going to use the fence to make three sides of a rectangle, and the fourth side will be some of the wall. What’s the maximum area you can enclose, and how do you arrange the fence to do that?

That was such an odd thing to hear said out loud that I thought I’d better draw a diagram to confirm whether I’d even understood the question…

Screen Shot 2014-08-12 at 12.23.05

(I know. Should have been an artist.)

The free variable was to be the length of wall incorporated, labelled x. Given that our enclosed area is rectangular, then the opposite side of the rectangle must also be of length x. If we denote the length of our fence by a, then we must have (a – x) length of fence left over for the “sides”. This must be shared equally, so each “side” must have a length of (a-x)/2.

Bringing out some pure Year 7 Maths gold, I proceeded to declare that the area must then be

A=\frac{x(a-x)}{2}

All going well. There were a few weary, affirmative nods. The lad is hot on rectangles. No worries there.

So what I wanted to find out was what value of x would result in the maximum A, which sounded comfortingly like a “differentiate, set to zero to find stationary point” thing. I announced that this was what I was going to do and sincerely hoped that they wouldn’t want me to go to first principles and show why that gave rise to a max/min. Thankfully they were happy with me just going ahead and doing it, so I wrote down the agreeable-looking expression

\frac{d}{dx}\frac{x(a-x)}{2}=0

Firmly in my comfort zone by this stage, I ploughed on…

a-2x=0 x=a/2

I underlined this with a flourish. There were frowns and tilting of heads as the tutors attempted to read upside down what I’d written. “So… what’s the area?” one said. Good point. I hadn’t actually answered the question. My value for x represented the length of wall which gave you the maximum area, rather than the area itself.

A_{max}=\frac{(a/2)(a-(a/2))}{2} A_{max}=\frac{a(a/2)}{4} A_{max}=\frac{a^2}{8}

Yes? Yes. Great. That went well.

Can you draw a graph of the area enclosed as a function of x?

Erm… Well… My eyes strayed towards the Gaussian on the whiteboard. But that couldn’t be right. It must be a parabola. And it must have zero value when x=0 and x=a. AND I’VE JUST FOUND the max point! With those three points I sketched something. With a=4 it looks like this:

Screen Shot 2016-04-20 at 20.53.13

The interviewers nodded to each other. From that, I took that my answer sufficed. HA! Gaussian, pfft.

The younger of the two interviewers piped up to move us onto the next question.

Right, let’s go on to something that’s not easy.

A layer or two beneath the nerves I was feeling, I felt a ripple of anger at this. “Don’t feel pleased to have done that because it was easy. This won’t be, though.” Since that night I’ve been on the other side of the interview table many, many times, and I can’t imagine being motivated to undermine or discourage someone like that. Anyway, there was no time for that, because…

Question 2

Choose any 3 digit number. The only constraint is that the first digit within it has to be bigger than the third. (Eg, 321). Reverse the order of its digits, and subtract this from the original number. (Eg, 321 – 123 = 198). Reverse the digits of this new number, and add the result of that, to the new number. (Eg, 198 + 891 = 1089). You’ll notice that the answer has been written on the whiteboard behind you for the duration of the interview. Why is it always 1089?

Now, I won’t lie, my initial reaction was simply to think “oh dear”, because I had absolutely no idea and didn’t really know where to start. The proof is as follows, and eventually I got to it, but it was very much with the prompting and cues or the interviewers. It would not be fair in any way to say I proved it myself, even laboriously.

The reason it happens is because the process of reversing and subtracting twice effectively recovers and cancels out the original digits you chose, but with a few artefacts left over from all the faffing about reversing them (flipping digits between the hundreds and units columns), which sum to 1089.

Denote your initial 3 digits (comprising your number) as A, B and C. (Recalling that it is stipulated that A>C.) The number is then given by

100A+10B+C

Following the sequence of steps set out in the question, then,

(100A+10B+C)-(100C+10B+a) =100(A-C)+C-A

Now we are instructed to reverse this number, which will be a 3 digit number because of the constraint A>C. We need to therefore rearrange it slightly to represent it in units of hundreds, tens and ones, and therefore be able to algebraically reverse it…

=100(A-C-1)+10(10)+(C-A)

But again, A>C, so we have to borrow a 10:

=100(A-C-1)+10(9)+(C-A+10)

Reversing again,

100(C-A+10) +10(9) +(A-C-1)

And adding this to the last variation, we get

((100(A-C-1)+10(9)+(C-A+10))+(100(C-A+10)+10(9)+(A-C-1)) =100(A-C-1+C-A+10)+10(9+9)+1(C-A+10+A-C-1) =100(9)+10(18)+1(9) =900+180+9 =1089

With the tutors prompting me through, I was as surprised as anyone when this number appeared on my page, but made some agreeable “ahhh” sounds of understanding. You can see just from the above that all it boils down to is addition and subtraction algebra, but of the kind that’s awkward to keep track of when you’re nervous and under pressure.

There was an awkward pause where nobody made eye contact. Obviously I felt pretty foolish. Apparently not being able to bring themselves to speak to me about maths and physics any further, The Man Who Found Things Easy piped up with “I’ll show you out, then” and proceeded to walk carefully to the door, open it, and watch me through it, all in utter silence. It was weird.

And with that, I was one interview down. I had literally no idea how I’d done. It was about half past five in Oxford in the pit of mid-winter. I headed back to the room I’d been loaned to de-suit and whiled away the 21 hours until my next interview. Read all about it in part 2…

Automated Anonymous Interactions with Websites Using Python and Tor

The debate around privacy and anonymity on the internet really grinds my gears, because tbh shouldn’t it be everyone’s basic right to make a script to vote 10,000 times from 10,000 different IPs in a poll on the website of your local newspaper? I think so. The battle against anonymity is kinda like the battle against piracy, in that thermodynamics favours the dissenters. What I mean by that is that whilst there may be many solutions to a problem like blocking The Pirate Bay, there are many MORE workarounds, so, although a certain system may be working now, there are inevitably many higher-entropy states. In a scenario where you’re trying to block, or even discern, a path between two entities, somehow there’ll be a way. And people are smart. Bless ’em. Leaky buckets.

ANYWAY, let’s bring things right back down and set out how you can do stuff on websites en-masse. Anonymity is only relevant because most sites are clever enough to recognise that when the same identity tries to do the same thing a few times, something a bit dodge may be afoot. To mitigate that, we’ll be harnessing the power of Tor. If you don’t know what Tor is, I hope you’re having a pleasant retirement.

A few swift disclaimers:

  • Don’t do anything bad. It’s not my fault if you do.
  • Whilst everything below seems to maintain anonymity, it’s not my fault if you end up living in the Ecuadorian embassy.

Python, wonderful, wonderful language that it is, has libraries that both interact with Tor, and interact with web pages. With a little jiggerypokery, you can get these to talk to each other and do amusing things.

Prerequisites

  1. Install the Tor browser bundle. We’re not actually going to use Tor browser for this shizz, but it’s the easiest way to get a fully configured Tor setup, and to start that service up.
  2. Install the Python splinter library. This is what we’ll use to control a browser window in code: send it to websites, click on things, fill in forms, and anything else we fancy.

    [code language=”bash”]sudo pip install splinter[/code]

  3. Install the Python stem module. We need this to talk to Tor.

    [code language=”bash”] sudo pip install stem[/code]

  4. Install the Firefox web driver, which is included in the Selenium installation. We need this because Firefox plays most nicely with the rest of the setup, and I’m too lazy and/or inept to figure out how to get everything working nicely with my preferred browser.

    [code language=”bash”] sudo pip install selenium[/code]

Now we’re laughing. HAHAHA.

Connecting to Tor

Open the Tor Browser, allow it to go through it’s little initialisation, then once you get to the green screen congratulating you on being connected, minimise but don’t close that window. Having the browser open means that a Tor connection is running on your computer, and, whilst we aren’t going to use the Tor Browser window we just opened because we can’t control it automatically through Python, we are going to funnel our traffic through said Tor connection.

What we now do, is instantiate a Splinter browser, and tell it to use the Tor instance running locally on port 9150 as a proxy for SSL, socks and ftp…

[code language=”python”]
import stem.process
from stem import Signal
from stem.control import Controller
from splinter import Browser

proxyIP = "127.0.0.1"
proxyPort = 9150

proxy_settings = {"network.proxy.type":1,
"network.proxy.ssl": proxyIP,
"network.proxy.ssl_port": proxyPort,
"network.proxy.socks": proxyIP,
"network.proxy.socks_port": proxyPort,
"network.proxy.socks_remote_dns": True,
"network.proxy.ftp": proxyIP,
"network.proxy.ftp_port": proxyPort
}
browser = Browser(‘firefox’, profile_preferences=proxy_settings)
browser.visit("http://www.icanhazip.com")
[/code]

If you run this and it’s working, a Firefox browser will open itself, go to www.icanhazip.com (which, for the rain men among you, is a website which tells you the IP you’re using to access it), and receive an IP other than your actual one.

If you get some error related to loading “the profile” or similar, check you have the most recent version of selenium via

[code language=”python”]sudo pip install –upgrade selenium[/code]

If you get some error about the proxy server not accepting connections, make sure you have Tor Browser open. (I did mention that earlier, if you recall.)

NB: you have to include the “http://” in the website url.

Getting a New IP

Given that this is potentially something that we’ll want to do often in…. whatever it is that we’re doing, it makes sense to make it into a cheeky function:

[code language=”python”]
def switchIP():
with Controller.from_port(port=9151) as controller:
controller.authenticate()
controller.signal(Signal.NEWNYM)
[/code]

The “NEWNYM” signal is apparently what you send to your Tor connection when you want a new identity. Who knew?

To test that this is working, we can request a new IP 10 times, and after each request visit www.icanhazip.com to verify that we are indeed coming via a different exit node…

[code language=”python”]
for x in range(10):
browser.visit("http://www.icanhazip.com")
switchIP()
time.sleep(5)
[/code]

Greatness beckons.

Interacting With Websites

Ah yes. Doing stuff. This is where Splinter delivers.

What this code looks like depends very much on the website you want to do stuff on, and what you want to do. For this example I’m going to a bit of commenting, but if that doesn’t cover whatever you want to do, then Splinter is extremely well-documented so just zip over there and look it up.

Purely by way of an example, let’s head over to dogdogfish.com and register our opinion once or twice…

[code language=”python”]
def interactWithSite(browser, deduplication):
browser.visit("http://dogdogfish.com/python-2/generating-b2b-sales-data-in-python/")
browser.fill("comment", "But the thing is… Why would anyone ever want to do this? I must have thought that "+str(deduplication)+" times…")
browser.fill("author", "Pebblor El Munchy")
browser.fill("email", "barack@tehwhitehouz.gov")
browser.fill("url", "https://upload.wikimedia.org/wikipedia/en/1/16/Drevil_million_dollars.jpg")
button = browser.find_by_name("submit")
button.click()
[/code]

For finding the names of textboxes, buttons, etc, just do a cheeky “inspect element” on the page:

Screen Shot 2016-04-19 at 20.53.43
Screen Shot 2016-04-19 at 20.25.19

Then finally you can draw all of this together with the following few lines:

[code language=”python”]
for x in range(1000):
interactWithSite(browser, x)
switchIP()
time.sleep(5)
[/code]

Internet, I am thy master.

Using Machine Learning to Generate Lyrics in the Style of your Favourite Artist

I once saw a pyramid depiction of human needs. At the bottom was basic sustenance, and on top of that shelter and safety, and on top of that was art and culture and that. It left me confused, because it omitted something which I think all of us want on a deep and fundamental level: A way to capture the lyrical idiosyncrasies of an artist in a machine learning model, and thereby churn out an arbitrary amount of pure poetry in the style of that artist. Fortunately that’s going to be addressed in this post.

We need three things.

  1. A means to get a bunch of lyrics from a given artist, in order to learn about their style.
  2. Some way of capturing said style – the way this artist tends to put lyrics together – in a model.
  3. Off the back of 1 and 2, something that uses the rules to spit out some pure artistry.

And so, without further ado!

1 – Getting Lyrics to Learn From

The good eggs at lyricsnmusic.com have got this covered for us with their dank API. Sign yourself up for an API key then it’s as simple as this to get some lyrics for, say, Coldplay. I heard that the favourite browser of the guys over there is Mozilla/5.0 so I’ve added that as our “browser signature” as a gesture of good faith… 😉

[code language=”python”]
url = "http://api.lyricsnmusic.com/songs?api_key="+apiKey+"&artist=coldplay"

opener = urllib2.build_opener()
opener.addheaders = [(‘User-agent’, ‘Mozilla/5.0’)] #lol
response = opener.open(url).read()

feed = json.loads(response)
for song in feed:
print(song["snippet"])
[/code]

...
He said I'm gonna buy this place and burn it down
I'm gonna put it six feet underground
He said I'm gonna buy this place and watch it fall
Stand he...
Come on, oh my star is fading
And I swerve out of control
If I, if I'd only waited
I'd not be stuck here in this hole
...

Martin, you pretentious beauty! What we have here is a JSON structure of songs, each of which has properties like “title” and “snippet”, which, lamentably, is not the full lyrics. The boys have got us covered again, though, because they also provide a URL to the page containing the full lyrics, so we can just mosey on over there and scrape the shit out of those.

While we’re at it, let’s think ahead, and simply condense all this band’s lyrics into one big string, which we’ll call trainingText. Strange name, you say? No stranger than “Nigella”, I respond.

[code language=”python”]
trainingText = ""
for song in feed:
snippet = song["snippet"]
fullUrl = song["url"]
fullPageHTML = opener.open(fullUrl).read()
page = BeautifulSoup(fullPageHTML, "html.parser")

try:
lyrics = str(page.findAll("pre")[0]).replace("
<pre itemprop=\"description\">","").replace("</pre>

","")
#There’s probably a better way of doing this, but I’m not, nor have I ever been, the queen.
trainingText += lyrics
except:
try: trainingText += snippet+"\n"
except: continue
print(trainingText)
[/code]

What this gives you is essentially one big song of everything available for the artist. AND THAT’S IT. Let’s generalise this to a function which accepts a band and an API key as inputs, helpfully keeps you posted on its song-learning progress, and then gives you back the compiled vocal material of the artist you give it…

[code language=”python”]
def getLyrics(band, apiKey):
encodedBand = urllib.quote_plus(band)
url = "http://api.lyricsnmusic.com/songs?api_key="+apiKey+"&artist="+encodedBand

opener = urllib2.build_opener()
opener.addheaders = [(‘User-agent’, ‘Mozilla/5.0’)] #lol
response = opener.open(url).read()
feed = json.loads(response)

trainingText = ""
songsProcessed = 0
for song in feed:
snippet = song["snippet"]
fullUrl = song["url"]
fullPageHTML = opener.open(fullUrl).read()
page = BeautifulSoup(fullPageHTML, "html.parser")

try:
lyrics = str(page.findAll("pre")[0]).replace("
<pre itemprop=\"description\">","").replace("</pre>

","")
#There’s probably a better way of doing this, but I’m not, nor have I ever been, the queen.
trainingText += lyrics
except:
try: trainingText += snippet+"\n"
except: continue
songsProcessed += 1
print("Learned "+str(songsProcessed)+" songs…")

return(trainingText)
[/code]

2 – Capturing the Artist’s Poetic Nuances

Where would such-and-such-an-artist go with a certain theme? How would their lines play out? How long would they be? When would they decide it was time for a new verse?

Based on the back catalogue provided by step 1, we can build a probabilistic model of this, called a Markov Chain. The below is a slight simplification, but captures the essence of how it works.

Supposing we feed into our model the line “the boys are back in town”.

The model takes the first two words – “the boys”, and looks what follows. It finds “are back”. So at this point, we know that “are back” follows “the boys” in 1 out of 1 occurences, ie, 100% of the time. If we’re asked the question of continuing something starting with “the boys”, we will choose “are back” every time, because it’s all we know.

But then supposing we read a little further in the catalogue and see the line “if the boys wanna fight, you better let ’em”. Now we enrich our model with the knowledge that if you see “the boys”, half the time “wanna fight” comes next. Half the time “are back” comes next. Based on that knowledge, if you asked us many times to carry on from “the boys”, on average half the time we would choose “are back”, and half the time we would choose “wanna fight”.

Of course, you wouldn’t just look at what follows “the boys”; you’d look at what follows every other combination of words in your “training” text. That’s what we’re going to do with the massive long list of lyrics. But rather than looking ahead one word, we’re going to look ahead one character, which will be helpful in deciding when to put punctuation in, when to break to a new line, and when to break into a new verse. And, similarly, rather than looking at what’s likely to come next after two words, we’re going to look at what’s likely to follow a certain number of characters. We’ll move this “window” all the way through the past lyrics we got in step 1, like so:

The boys are back in town
The boys are back in town
The boys are back in town
The boys are back in town
The boys are back in town
The boys are back in town
The boys are back in town
The boys are back in town
The boys are back in town
The boys are back in town
The boys are back in town
The boys are back in town
The boys are back in town
The boys are back in town
The boys are back in town
The boys are back in town
The boys are back in town
The boys are back in town

And every time we move the window, we have a look what the next character is, and amend our record of how many times we’ve seen that next character, for this window.

The width of that window is called the order of the Markov Chain, and is essentially a measure of how long the “memory” of our model is. It has a profound bearing on the outcome of the lyric generation, because declaring that “s” follows “y” is a lot different to declaring that “s” follows “the boy”.

Anyway. Here’s the code that does this with our lyrics:

[code language=”python”]
def generateModel(text, order):
model = {}
for i in range(0, len(text)-order):
fragment = text[i:i+order] #Range is exclusive at upper bound
nextLetter = text[i+order] #So this is the next letter
if fragment not in model:
model[fragment] = {}
if nextLetter not in model[fragment]:
model[fragment][nextLetter] = 1
else:
model[fragment][nextLetter] += 1
return(model)
[/code]

Here’s what the model looks like for the line “sometimes I run sometimes I hide”:

('un somet', {'i': 1})
(' sometim', {'e': 1})
(' run som', {'e': 1})
('ometimes', {' ': 2})
(' I run s', {'o': 1})
('I run so', {'m': 1})
('imes I h', {'i': 1})
('metimes ', {'I': 2})
('imes I r', {'u': 1})
('es I run', {' ': 1})
('mes I ru', {'n': 1})
('times I ', {'h': 1, 'r': 1})
('sometime', {'s': 2})
('etimes I', {' ': 2})
('mes I hi', {'d': 1})
('n someti', {'m': 1})
('run some', {'t': 1})
('es I hid', {'e': 1})
('s I run ', {'s': 1})

Your way forward is pretty well determined, until you hit “times I “, at which point you have a 50/50 chance of the next letter being “r” or “h”. Once you choose on of those, you’re on a one-way track to either running or hiding. This is a trivial example, but running the entire back catalogue of a band through creates an interesting tree of probabilities which will take you in a different direction every time.

3 – Letting the car drive itself

What we need to do now is create a means of using the model to build up some lyrics. The way this works in Markov Chains is to look at the current window, get the next character probabilistically, then with that, move the window one place along, and repeat.

First let’s make a function which, given a current “fragment” and a model, gives you a next character…

[code language=”python”]
def getNextCharacter(model, fragment):
letters = []
for letter in model[fragment].keys():
for occurences in range(0, model[fragment][letter]):
letters.append(letter)
return(choice(letters))
[/code]

This is doing something very simple. It looks up the possible next characters for this fragment in the model, creates a list where each character appears as many times as its weighting, then then chooses one at random and returns it. Skill.

So all that remains now is to use these functions to spool out some lyrics. Our function for that is going to look like this…

[code language=”python”]
def generateLyrics(trainingText, order, length):
model = generateModel(trainingText, order)
currentFragment = trainingText[0:order]
output = ""
for i in range(0, length-order):
newCharacter = getNextCharacter(model, currentFragment)
output += newCharacter
currentFragment = currentFragment[1:]+newCharacter
return(output)
[/code]

So what we’re saying to this function is: here’s some lyrics to learn from, use these to generate me some lyrics of a certain length, using a window size or order of such and such. The function uses the training lyrics to generate a model, then uses that to form, character-by-character, a meandering continuation of the first few characters of the training text. Once the lyrics are built up to the requested length, the string is returned.

The first thing you’re going to want to do with this is to try it for loads of different artists, and even try it for the same artist multiple times to appreciate how non-deterministic it is, so I’d suggest that the following is a nice way of calling the various functions:

[code language=”python”]
band = raw_input("Enter artist:\n")

lyrics = getLyrics(band, apiKey)

newLyrics = generateLyrics(lyrics, 8, 600)

print(newLyrics)
[/code]

I Can Haz Lyrics?

Yep. Who are some artists with distinctive styles?

Adele

Oh noooo
Let it burn
Oh oh ohhhh
Let it burned while I cried
‘Cause I heard it screaming out your name,
You said I’m stubborn and raised
In a summer haze bound by the surprise
And he will feel like he’s been there for hours
And you’ll walk that mile
Until you kissed my lips and you prefer the floor
God only known each other,
Think of me in the deep (Tears are gonna fall, rolling in the pavements?
Even if, it leads nowhere
And I hear but our eyes, and settle for wrong

via GIPHY

Cradle of Filth

Devildom voyeurs
Ascend to smother the spite seething Draconist
And commit this wolf of the graveyard, of the moon
Lowered Her mask to me
Your soul
Live for the reams
Of verses and curses
That heavenly brow
Crippled seraph shalt cower in illustrious courts
Whilst She entranced divined from the wolves are the rustic summers of my excess
Expurse of a whore
Receiving sole communion from fate
By alighting to discredit rebirth
Alone as a stone cold wish
To see the witch scholared Her
In even darker spheres
Delighting in my cold cell, when the priest comes

Kanye West

yeah yeah yeah, I got packs to get the clouds to break me down
The only rapper AND a producer and a glove, but didn’t have a buzz bigger than the souls of men
Louboutin on the street trying to get by
Stack ya money to buy her a few pairs of new Airs
Cause lately’s been a whole life (Ohh)
And I wonder if you used to feel invisible
Now that wet mouth
Uh, I know she find out what he is owed?
And throw away my bus pass any and every class
Lookin’ at every ass
Cheated on every song and
save their whole deal, Their wrist is on chill
They house warmin’
Sittin’ here, grillin’ people say

via GIPHY

Bob Dylan

Zanzinger killed for no reason to roam
Don’t forget to flash
We’re all gonna meet
At that million dollar bash
Well, the comic book and me, just us, we caught ’em
And that is not
It doesn’t matter of minutes, on bail was out walking
But you and I, we’ve been deceived by the Fountain Bank
One bird book, and a bottle of bread
Yea, heavy and a bottle of bread
Yea, heavy and a buzzard and his weapon took from him
As they rot
While paupers change possessions
Each one means
At times I think that you do
Make me glad I’m in love with your money, pull up your shawl
Won’t you descend from

Led Zeppelin

Brother, I brought you together baby, I’m sure my shot-gun will.
Gonna go walkin’ through the country lanes,
I’ll be singing a song,
Hear me call your friends coming back home.You know I’m the one you want.
I must be time I’m leavin’,
Baby, dry those silver,
I brought you smiling at me,
That’s alright, I’d be the western shore
So now you’d better lay your mornin’ time is now
To sing my song
I’m going ’round the world
I got to find you remember times like these?
To think of us again?
And I do
Tangerine, Tangerine, Tangerine, Tangerine, Tangerine

(The Tangerine line is interesting – I think what’s happened is that at some stage the fragment “Tangerine, Tangerine” has appeared, so literally the only thing that has a chance of following “Tangerine” is “, Tangerine”, because the word is longer than the order.)

Justin Bieber

Rumors spreading ’bout this other guys?
I can see right from wrong
Help me when I got-got your body
Baby no no nobody has got what I need
‘Cause I didn’t believe
When I need is one love, one heart
My one heart
‘Cause I’m in love with you I’m losin’ you
I’m a me tell you one time (girl I love you)
You look so deep
You know you’re standing in front of the camera
She don’t stop until I find) my runaway love
Why can I choose between us no one else,
Want me to,
Baby we can share mine!
I know you care
Just shout whenever

Metallica

Swing the scene
In the city tonight
We are gathered here to maim and kill
‘Cause this is what we have done unto you
But what is truth?I cannot die
Trapped far beyond my fate
I give
You take
This life off from me
Hold my breath as I wish for death
Oh please, God, help me
Hold my breath as I wish for death
Oh please, God, help me
Death in the fast lane is just how it seems to fade away
Drifting further everyday
Getting lost within myself
Nothing can save you
Justice is lost
Justice is raped

Queen

Your mother’s eyes, from your eyes gonna make a big noise
Playin’ in the sand cannot heal me like a jelly fish
I kinda like it
You call me Mister Fahrenheit
I’m trav’ling at the peak of the land
I seen every Wednesday evening
There´s no ending
The Seer he said
Beware the championsFlash a-ah
Savior of the night followed day
And the hub caps all gleam
When I’m cruisin’ in overdrive
Don’t you take me back to you
In rain or shine
You say shark I say bite
You say your folks are telling you
Write my letter feel much better
And use my fancy patter on the multit

You get the idea.

And of course (there’s always an “of course”) the fact that we’re using the Markov Chain approach to generate song lyrics is incidental. This code can be used to generate text that looks like any other text you care to feed it. That could be religious texts, product reviews, sales pitches, anything.

There’s a pretty diverse amount of material already out there, so, now we have this, we probably don’t need humans any more.

The complete code is available on Github.

SMS Spoofing with Python for Good and Evil

It all started with the best of intentions. I was an excitable graduate going through the second birth of discovering that if you propositioned customers in the right way, a small percentage of them would buy your stuff.

Having been reasonably successful with personalized emails, it seemed that SMS was fair game as an extension. I mean, Dominos and Royal Mail do it, and they’re only partially more time-relevant than a sale on a website you bought a novelty Luis Suarez biting bottle opener from two years ago. Turned out that my at-the-time boss didn’t agree, reacting in a way that can be summarized as “strongly negative” when he looked at a shirt on our site and simultaneously received a text which said something to the tune of “that shirt would go great with the brown size 11 shoes you bought 82 days ago.”

via GIPHY

(But bosssssss, it’s a nexus of many technologies! Absolutely no way? Bahhh, okay then. No, yeah, I’ve totally been working on other stuff too.)

I digress, though. Nobody cares about that.

It was the “misusing the tech to banter your friends” stage of that development which, ultimately, led to the discovery of something much creepier.

Experience gained from that same stage of development during my email days led me to start off with volume and persistence, because if there’s one thing that computers are good at (and there is), it’s the old water torture. Clockwork SMS, who will do your bidding at £0.05 per message, seemed as good a bet as any to me, so that’s who I “pip install”d. (And then angrily “sudo pip install”d, of course.)

Lolling delightedly to myself, I set this baby loose…

from clockwork import clockwork
import time api = clockwork.API("Your API code here")

lyrics = open("Bohemian Rhapsody Lyrics.txt", "r").readlines()

for line in lyrics:
    payload = line.replace("\n", "")
    message = clockwork.SMS(from_name = "F Mercury", to = "447000123456", message = payload)
    response = api.send(message)
    print(response)
    time.sleep(300)

 

… and, with the warm fuzzy feeling that accompanies the knowledge that a computer is busy doing one’s dirty work, retired to enjoy my evening partaking in my favourite pastime of throwing stones at traffic.

My friend was sent a line from “Bohemian Rhapsody” every 5 minutes until the song was done. Picture it: the numbingly-familiar “ding” of an incoming text and the muscle memory that responds by reaching for your nearby phone, maybe even the rational thought that, in all probability, this was just the latest in the pontifications of one F. Mercury, but the agonizing, irresistible, small-but-not-negligible chance THAT IT’S A LEGIT TEXT. No real hardship just to check. That swine. Wish I hadn’t checked. Not going to check the next one. Sublime.

Text from Freddie.

Turned out he was really ill and I made a basic arithmetic error which resulted in the texts continuing through the night instead of being spread over a couple of hours, so that was rather less funny than it could have been, but I was hardly to know that at the time. And anyway, the fires of curiosity had been stoked in my mind.

Because of course, annoying though this is, it’s fairly obviously banter. Beyond seeking a restraining order, it’s not really going to influence people. Now, saying that, I should also say that this is where the “in the field” element of my noble research ended: what follows involved the phones of others, but also always their knowledge and consent. The life-wrecking potential of unleashing this on people fo’ real should be reserved for elected governments and security agencies. DISCLAIMER: don’t do it etc.

You’ll have noticed that the “from” argument in the call is what appears on the recipient’s phone when the SMS comes in. That in mind, the logical extension from “F Mercury”, or any other experimental name, is “Mum”.

message = clockwork.SMS(from_name = "Mum", to = "447000123456")

Mum checking in.

Tehehehehe. Excellent. What a time to be alive.

There’s one pig in the poke, though: my phone is clever enough to know that this is only from “Mum” in a superficial sense. If I were forced to guess why this was, I’d probably go with the fact that this is from a string, not a number, which is where my real messages from “Mum” come from. So this message isn’t part of any thread. The real messages labeled as “Mum” come, at a presumably more fundamental level, from a phone number, which is saved under an alias in my contacts.

Ahh, but it's not real.

I wonder. I JUST WONDER.

The magic step is absurdly simple. What would happen if I put the from address as a phone number, the phone number stored under “Mum” in my contacts?

message = clockwork.SMS(from_name = "07999654321", to = "447000123456", message = "You don't know anything, and you stink.")

 

Seems Legit

Long have critics conjectured on the inspiration behind Lionel Ritchie’s time-immemorial opus “Hello, is it Me You’re Looking For?”. Now we know.

Here you have a trivially simple method of injecting legit-looking messages into text conversations with anyone, providing you know how your target stores the spoofee sender in their contacts. In the UK, that’s largely the difference between starting with 07, and +447.

The utterly exquisite reality is that, if your target then replies, that reply goes to the real sender, who is overwhelmingly likely to reply something like “what the hell are you on about?”, this being the first they’ve heard of this shady business. Does that look like backtracking or denial? I ain’t no Member of Parliament, but it sure sounds like it to me.

And if I may quote Mouse from The Matrix, that makes you wonder about a lot of things. How many friendships and/or relationships have fallen afoul of a simple misunderstanding, a simple miscommunication, one statement taken the wrong way, such as could be easily achieved through the above means?

How many fledgling romances need a seductive kick-start to get them over the stalemate of shyness?

Given that your communication is limited to one-way, what series of messages should you go with for maximum impact, and maximum imperviousness to whatever the replies might be?

Could you even construct some confusing pseudo-two-way thing, if you knew the numbers of both parties? Like two colleagues maybe?

Doesn’t bear thinking about, really. Much.