Repository: openstates/openstates-scrapers

Issue:
OH failing since at least 2018-05-20
OH has been failing since 2018-05-20

Based on automated runs it appears that OH has not run successfully in 3 days (2018-05-20).


```
  03:05:08 INFO scrapelib: GET - http://search-prod.lis.state.oh.us/solarapi/v1/general_assembly_132/bills/hb659/
03:05:09 INFO scrapelib: GET - http://search-prod.lis.state.oh.us/solarapi/v1/general_assembly_132/bills/hb659/actions
03:05:10 INFO scrapelib: GET - http://search-prod.lis.state.oh.us/solarapi/v1/general_assembly_132/bills/hb659/votes
03:05:11 INFO scrapelib: GET - http://search-prod.lis.state.oh.us/solarapi/v1/general_assembly_132/bills/hb659/cmtevotes
03:05:12 INFO scrapelib: GET - http://search-prod.lis.state.oh.us/solarapi/v1/general_assembly_132/bills/hb659/veto
03:05:13 INFO scrapelib: GET - http://search-prod.lis.state.oh.us/solarapi/v1/general_assembly_132/bills/hb659/disapprove
03:05:14 INFO pupa: save bill HB 659 in 132 as bill_d7ea6180-5d96-11e8-957c-0234d94f4d20.json
03:05:14 INFO scrapelib: GET - http://search-prod.lis.state.oh.us/solarapi/v1/general_assembly_132/bills/hb660/
03:05:15 INFO scrapelib: GET - http://search-prod.lis.state.oh.us/solarapi/v1/general_assembly_132/bills/hb660/actions
03:05:16 INFO scrapelib: GET - http://search-prod.lis.state.oh.us/solarapi/v1/general_assembly_132/bills/hb660/votes
03:05:17 INFO scrapelib: GET - http://search-prod.lis.state.oh.us/solarapi/v1/general_assembly_132/bills/hb660/cmtevotes
03:05:18 INFO scrapelib: GET - http://search-prod.lis.state.oh.us/solarapi/v1/general_assembly_132/bills/hb660/veto
03:05:19 INFO scrapelib: GET - http://search-prod.lis.state.oh.us/solarapi/v1/general_assembly_132/bills/hb660/disapprove
03:05:20 INFO pupa: save bill HB 660 in 132 as bill_db781cb6-5d96-11e8-957c-0234d94f4d20.json
03:05:20 INFO scrapelib: GET - http://search-prod.lis.state.oh.us/solarapi/v1/general_assembly_132/bills/hb661/
03:05:21 INFO scrapelib: GET - http://search-prod.lis.state.oh.us/solarapi/v1/general_assembly_132/bills/hb661/actions
03:05:22 INFO scrapelib: GET - http://search-prod.lis.state.oh.us/solarapi/v1/general_assembly_132/bills/hb661/votes
03:05:23 INFO scrapelib: GET - http://search-prod.lis.state.oh.us/solarapi/v1/general_assembly_132/bills/hb661/cmtevotes
03:05:24 INFO scrapelib: GET - http://search-prod.lis.state.oh.us/solarapi/v1/general_assembly_132/bills/hb661/veto
03:05:25 INFO scrapelib: GET - http://search-prod.lis.state.oh.us/solarapi/v1/general_assembly_132/bills/hb661/disapprove
03:05:26 INFO pupa: save bill HB 661 in 132 as bill_df18594e-5d96-11e8-957c-0234d94f4d20.json
loaded Open States pupa settings...
oh (scrape, import)
  people: {}
  bills: {}
import jurisdictions...
import organizations...
import people...
import posts...
import memberships...
Traceback (most recent call last):
  File "/opt/openstates/venv-pupa//bin/pupa", line 11, in <module>
    load_entry_point('pupa', 'console_scripts', 'pupa')()
  File "/opt/openstates/venv-pupa/src/pupa/pupa/cli/__main__.py", line 68, in main
    subcommands[args.subcommand].handle(args, other)
  File "/opt/openstates/venv-pupa/src/pupa/pupa/cli/commands/update.py", line 260, in handle
    return self.do_handle(args, other, juris)
  File "/opt/openstates/venv-pupa/src/pupa/pupa/cli/commands/update.py", line 307, in do_handle
    report['import'] = self.do_import(juris, args)
  File "/opt/openstates/venv-pupa/src/pupa/pupa/cli/commands/update.py", line 211, in do_import
    report.update(membership_importer.import_directory(datadir))
  File "/opt/openstates/venv-pupa/src/pupa/pupa/importers/base.py", line 196, in import_directory
    return self.import_data(json_stream())
  File "/opt/openstates/venv-pupa/src/pupa/pupa/importers/base.py", line 233, in import_data
    obj_id, what = self.import_item(data)
  File "/opt/openstates/venv-pupa/src/pupa/pupa/importers/base.py", line 272, in import_item
    raise DuplicateItemError(data, obj, related.get('sources', []))
pupa.exceptions.DuplicateItemError: attempt to import data that would conflict with data already in the import: {'label': '', 'role': '', 'person_id': 'ocd-person/2490e84f-38e3-4805-a9d1-db54532daab9', 'person_name': 'Kenny Yuko', 'organization_id': 'ocd-organization/401c065d-0f85-4c93-b87b-1675a7ef6c1a', 'post_id': 'ocd-post/695e62ab-91d5-4fde-b530-9727a981010a', 'on_behalf_of_id': None, 'start_date': '', 'end_date': '', 'extras': {}} (already imported as Kenny Yuko in Senate ())
obj1 sources: []
obj2 sources: []
```

Visit http://bobsled.openstates.org for more info.



Discussion:
I believe this requires access to the OpenStates reference pupa Postgresql database (or a replica) to work on.
this is referring to an import-time duplicate, the duplicate should be in
the local copy


Resolving patch:
diff --git a/openstates/oh/people.py b/openstates/oh/people.py
--- a/openstates/oh/people.py
+++ b/openstates/oh/people.py
@@ -189,8 +189,9 @@ def scrape_senator_page(self, chamber, url):
         page = lxml.html.fromstring(page)
         page.make_links_absolute(url)
 
-        for legislator in page.xpath("//div[contains(concat(' ', normalize-space(@class), ' '), "
-                                     "' portraitContainer ')]"):
+        for legislator in page.xpath(
+                "//div[@id='senators']//div[contains(concat(' ', normalize-space(@class), ' '), "
+                "' portraitContainer ')]"):
             img = legislator.xpath(".//div[@class='profileThumbnailBoundingBox']/@style")[0]
             img = img[img.find('(')+1:img.find(')')]
             full_name = legislator.xpath(".//div[@class='profileName']/a/text()")[0]


Test patch: